3
Deployment
Gabriel Kaszewski edited this page 2026-05-15 15:17:05 +00:00

Deployment

Production deployment uses compose.prod.yml. Traefik is used as the reverse proxy (expected to be running as a shared external service on the host). No Nginx is involved.

API and frontend are exposed on separate subdomains via Traefik labels with automatic Let's Encrypt TLS.

Services

Service Image Role
api registry.gabrielkaszewski.dev/thoughts:latest API server on port 8000
worker Same image, entrypoint ./thoughts-worker Event consumer — AP fan-out, notifications
frontend registry.gabrielkaszewski.dev/thoughts-frontend:latest Next.js SSR on port 3000
database postgres:16-alpine PostgreSQL with persistent volume

NATS runs as a shared external service (k_nats) — not managed by this compose file in production.

Networks

Network Type Purpose
internal bridge DB ↔ API ↔ worker (isolated)
shared-services external Access to shared infra (NATS, etc.)
traefik external Traefik can reach the containers

Steps

1. Clone and configure

git clone <repo-url>
cd thoughts

cp .env.example .env
# Edit: POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB,
#        JWT_SECRET, BASE_URL, CORS_ORIGINS, ALLOW_REGISTRATION

BASE_URL must be the public API domain (e.g. https://api.thoughts.example.com). ActivityPub IDs are derived from it.

2. Pull images and start

docker compose -f compose.prod.yml pull
docker compose -f compose.prod.yml up -d

Migrations run automatically when the api container starts.

Traefik Routing

Routing is configured via Docker labels on each container. Traefik must be running with:

  • A traefik Docker network
  • A letsencrypt cert resolver configured

The api container is routed to api.<your-domain>, the frontend to <your-domain>.

Updating

docker compose -f compose.prod.yml pull
docker compose -f compose.prod.yml up -d

Migrations run on next API container start — no manual step needed.

Data Persistence

PostgreSQL data lives in a named Docker volume (postgres_data). Safe across docker compose down and image updates. Only destroyed with docker compose down -v.

Environment Variables Reference

Variable Required Description
POSTGRES_USER Yes PostgreSQL username
POSTGRES_PASSWORD Yes PostgreSQL password
POSTGRES_DB Yes PostgreSQL database name
JWT_SECRET Yes Secret for JWT signing
BASE_URL Yes Public API base URL (used for AP IDs)
CORS_ORIGINS No Allowed CORS origins (default: *)
ALLOW_REGISTRATION No Enable public registration (default: false)