Skip to main content

Deployment Overview

:::warning Legacy Rails version This page documents the older Rails version of Campbooks. It is unstable and unmaintained, and it no longer gets fixes. Campbooks is being rebuilt from scratch in Rust: for new installs, see Self-hosting. :::

Campbooks deploys as a self-contained Docker Compose stack. docker compose up runs the whole app on a single server — there's no Node build, no Redis, and no external services to wire up beyond a TLS-terminating reverse proxy.

Want the step-by-step? This page is the lay of the land. The Self-Hosting guide walks through a real production server end to end.

The stack​

docker compose up starts three containers:

ServiceWhat it is
postgresPostgreSQL with the pgvector extension (required — it holds app data, cache, jobs, Action Cable, and vector embeddings)
webThe Rails app — Puma behind Thruster
workerBackground jobs — email scanning, AI, indexing, calendar sync (Solid Queue)

A fourth service, opensearch, is optional (enabled with the search profile) and only powers contact full-text autocomplete. Everything else — email search, document search, the Cmd+K palette — uses Postgres + pgvector.

Uploaded files (email attachments saved as Documents) live on a local Docker volume by default, or in S3-compatible object storage if you configure it.

What you need​

  • A server with Docker and the Docker Compose plugin (Docker Engine ≥ 24)
  • About 2 GB RAM for the default stack (add ~1 GB if you enable OpenSearch)
  • A domain name and a reverse proxy that terminates TLS (Caddy, Traefik, or nginx)

Configuration​

Everything is configured through environment variables in .env. bin/generate-secrets fills the required secrets; the rest are optional and each unlocks one integration. The annotated list lives in .env.example.

VariableRequiredPurpose
SECRET_KEY_BASEYesRails session/signing key
ACTIVE_RECORD_PRIMARY_KEYYesEncrypts OAuth tokens & AI keys at rest
ACTIVE_RECORD_DETERMINISTIC_KEYYesAs above
ACTIVE_RECORD_KEY_DERIVATION_SALTYesAs above
CAMPBOOKS_DATABASE_PASSWORDYesPassword for the bundled Postgres
APP_HOSTYesThe hostname you reach the app on (must match the Host header)
FORCE_SSLYestrue behind a TLS proxy, false for plain-HTTP local use
SELF_HOSTEDYes1 — open registration + reads AI keys from env

You don't need config/master.key. Self-hosting reads SECRET_KEY_BASE from the environment. Generate the required secrets with bin/generate-secrets.

Going to production​

  1. Point a domain at the server and set APP_HOST, FORCE_SSL=true, and WEB_PORT in .env.
  2. Put a TLS-terminating reverse proxy in front (with Caddy it's a two-line config — automatic HTTPS).
  3. docker compose up -d --build. The entrypoint runs database migrations on boot.

Never expose the app over plain HTTP on the internet. With FORCE_SSL=false sessions and cookies travel unencrypted. Always sit behind a TLS proxy in production.

Updates​

git pull
docker compose up -d --build # the entrypoint runs migrations on boot

Back up the database first.

Health check​

Campbooks exposes a health endpoint at /up (returns 200 when healthy). Use it for load-balancer probes and monitoring — it stays reachable over plain HTTP even with FORCE_SSL=true.

See the Self-Hosting guide for the full walkthrough, including backups and every integration.