From 1694995df2ad43992dea139ffb492c89c55c81bc Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Fri, 15 May 2026 15:05:42 +0000 Subject: [PATCH] Update wiki page 'Deployment' --- Deployment.md | 73 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/Deployment.md b/Deployment.md index 8d60ae3..e88d179 100644 --- a/Deployment.md +++ b/Deployment.md @@ -1,15 +1,17 @@ # Deployment -Production deployment uses Docker Compose (`compose.prod.yml`) with four services behind Nginx. +Production deployment uses `compose.prod.yml` with Docker Compose. The backend Docker image contains both binaries (`thoughts` API server and `thoughts-worker`); they run as separate containers from the same image. ## Services -| Service | Image | Description | +| Service | Binary / Image | Role | |---|---|---| +| `thoughts` | `thoughts` (from `Dockerfile`) | API server on port 8000 | +| `thoughts-worker` | `thoughts-worker` (same image, different entrypoint) | Event consumer — AP fan-out, notifications | +| `thoughts-frontend` | `thoughts-frontend/Dockerfile` | Next.js SSR | +| `database` | `postgres:15` | PostgreSQL with persistent volume | +| `nats` | `nats:latest` | NATS JetStream | | `proxy` | Nginx (custom) | TLS termination, reverse proxy | -| `thoughts-frontend` | Built from `thoughts-frontend/Dockerfile` | Next.js SSR frontend | -| `thoughts-backend` | Built from `thoughts-backend/Dockerfile` | Rust API server | -| `database` | `postgres:latest` | PostgreSQL with persistent volume | ## Steps @@ -20,49 +22,72 @@ git clone cd thoughts # Backend env -cp thoughts-backend/.env.example thoughts-backend/.env -# Edit: DATABASE_URL, JWT_SECRET, etc. - -# Root env (shared by compose) cp .env.example .env -# Edit: POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, domain settings +# Edit: DATABASE_URL, JWT_SECRET, BASE_URL, NATS_URL ``` +`BASE_URL` **must** be your public domain (e.g. `https://thoughts.example.com`). ActivityPub IDs are derived from it. + ### 2. Build and start ```bash docker compose -f compose.prod.yml up -d --build ``` -### 3. Run migrations +Migrations run automatically when the API container starts. No manual migration step needed. -```bash -docker compose -f compose.prod.yml exec thoughts-backend \ - ./migration -``` +### 3. Nginx / TLS -### 4. Nginx / TLS +`nginx/nginx.conf` routes traffic: -The `nginx/nginx.conf` routes traffic: - -- `yourdomain.com/api/*` → `thoughts-backend:3001` +- `yourdomain.com/api/*` → `thoughts:8000` +- `yourdomain.com/.well-known/*` → `thoughts:8000` (WebFinger, NodeInfo) +- `yourdomain.com/users/*/inbox` → `thoughts:8000` (AP inbox) - `yourdomain.com/*` → `thoughts-frontend:3000` -For TLS, add a Certbot/Let's Encrypt step or use an external TLS terminator in front of the Nginx container. +For TLS, add Certbot/Let's Encrypt or put a TLS-terminating reverse proxy in front. + +### 4. Frontend build args + +The frontend image requires build-time env args: + +```bash +docker build -t thoughts-frontend \ + --build-arg NEXT_PUBLIC_API_URL=https://thoughts.example.com \ + --build-arg NEXT_PUBLIC_SERVER_SIDE_API_URL=http://thoughts:8000 \ + thoughts-frontend/ +``` + +`docker compose -f compose.prod.yml` handles this automatically if the args are in the compose file. ## CI/CD -A Gitea Actions workflow lives at `.gitea/workflows/deploy.yml`. It builds and pushes Docker images on push to `master` and triggers a redeploy on your server. +Gitea Actions workflows in `.gitea/workflows/`: + +| Workflow | Trigger | Action | +|---|---|---| +| `deploy.yml` | Push to `master` | Build images, push to registry, redeploy | +| `lint.yml` | PR / push | `cargo clippy` + `cargo fmt --check` | +| `test.yml` | PR / push | `cargo test --workspace` | ## Updating ```bash git pull docker compose -f compose.prod.yml up -d --build -# Run migrations if schema changed -docker compose -f compose.prod.yml exec thoughts-backend ./migration ``` +Migrations run on next API container start. + ## Data Persistence -PostgreSQL data is stored in a named Docker volume. It survives container restarts and `docker compose down`. Use `docker compose down -v` only if you intentionally want to wipe the database. +PostgreSQL data lives in a named Docker volume. Safe across `docker compose down` and rebuilds. Only destroyed with `docker compose down -v` — use with caution. + +## Environment Variables Reference + +| Variable | Required | Description | +|---|---|---| +| `DATABASE_URL` | Yes | PostgreSQL connection string | +| `JWT_SECRET` | Yes | Secret for JWT signing | +| `BASE_URL` | Yes | Public base URL (used for AP IDs) | +| `NATS_URL` | No | NATS connection (federation/notifications) |