Update wiki page 'Deployment'
@@ -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 <repo-url>
|
||||
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) |
|
||||
|
||||
Reference in New Issue
Block a user