- pnpm 10 workspace + TypeScript strict + ESLint flat + Prettier - CLAUDE.md as canonical brief - docs/tasks/ — 22 task briefs broken out by phase for sub-sessions - docs/decisions/ — ADR scaffold Implements task 01 (repo-init).
64 lines
1.9 KiB
Markdown
64 lines
1.9 KiB
Markdown
# 05 — Compose stack & Caddy
|
|
|
|
## Goal
|
|
|
|
Produce the production deploy artifacts: Dockerfile, `deploy/compose.yaml`, Caddy snippet, `.env.production.example`.
|
|
|
|
## Depends on
|
|
|
|
- 02 (so `output: "standalone"` exists)
|
|
- 03 (so DB service is defined)
|
|
|
|
## Scope
|
|
|
|
### Dockerfile (multi-stage)
|
|
|
|
- Stage 1: `node:22-alpine` + pnpm, install deps, build (`pnpm build`).
|
|
- Stage 2: `node:22-alpine` runtime, copy `.next/standalone`, `.next/static`, `public/`. Run as non-root. `CMD ["node", "server.js"]`.
|
|
|
|
### `deploy/compose.yaml`
|
|
|
|
Services:
|
|
|
|
- `famapp` (built from Dockerfile)
|
|
- `famapp-db` (postgres:16, volume `famapp_db_data`)
|
|
- `authentik-server`, `authentik-worker`, `authentik-db` (postgres:16, volume `authentik_db_data`), `authentik-redis` — leave fully configured but task 06 will tune env
|
|
|
|
All services on a `famapp_net` network. famapp depends on famapp-db. No host port exposure for the DBs/redis.
|
|
|
|
### Caddy snippet (`deploy/Caddyfile.snippet`)
|
|
|
|
```
|
|
fam.ginnoir.com {
|
|
reverse_proxy famapp:3000
|
|
}
|
|
|
|
auth.ginnoir.com {
|
|
reverse_proxy authentik-server:9000
|
|
}
|
|
```
|
|
|
|
Comment at the top: "Include from main Caddyfile or paste into the existing one."
|
|
|
|
### `.env.production.example`
|
|
|
|
All vars needed by the compose stack, with comments explaining each.
|
|
|
|
## Out of scope
|
|
|
|
- Actually running the stack against ginnoir.com (Matt does that).
|
|
- Backups, log shipping (later tasks).
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] `docker build -t famapp .` succeeds.
|
|
- [ ] `docker compose -f deploy/compose.yaml config` validates without errors.
|
|
- [ ] famapp container starts against famapp-db when given a populated `.env`.
|
|
- [ ] Image size under ~300 MB.
|
|
- [ ] No secrets committed; only `.env.production.example`.
|
|
|
|
## Notes
|
|
|
|
- Use `pnpm fetch` + `pnpm install --offline` in the build stage for cache locality.
|
|
- `output: "standalone"` (set in task 02) means we copy `.next/standalone/server.js`, not run `next start`.
|