updating documentation

This commit is contained in:
lila 2026-05-16 01:59:43 +02:00
parent 1ba57c7e9d
commit 7e0311683f
25 changed files with 2660 additions and 226 deletions

View file

@ -0,0 +1,144 @@
# 06 — Deployment
> **Purpose:** Condensed infrastructure reference for LLMs working on deployment, CI/CD, or ops tasks. For full setup details (VPS provisioning, Forgejo configuration, backup scripts), see the human-readable DEPLOYMENT.md.
> **Last updated:** 2026-05-15
> **Depends on:** 00-project-overview.md
---
## Infrastructure Overview
```
Internet
Caddy (Docker container, ports 80/443)
├── lilastudy.com → web container (nginx:alpine, static files)
├── api.lilastudy.com → api container (Express, port 3000)
└── git.lilastudy.com → forgejo container (git + registry, port 3000)
SSH (port 2222) → forgejo container (git push/pull)
```
**VPS:** Hetzner, Debian 13, ARM64 (aarch64), 4GB RAM
**Domain:** lilastudy.com, wildcard `*.lilastudy.com` configured
**Only Caddy faces the internet.** All other services communicate over internal Docker network.
---
## Docker Compose Stack
Services on shared `lila-network`:
| Service | Image | Ports (internal) | Notes |
| -------- | ------------------------------------------------ | ---------------- | -------------------------------------------------- |
| caddy | caddy:alpine | 80, 443 | Only container with published ports |
| api | `git.lilastudy.com/forgejo-lila/lila-api:latest` | 3000 | Multi-stage Dockerfile, runs migrations on startup |
| web | `git.lilastudy.com/forgejo-lila/lila-web:latest` | 80 | nginx:alpine, SPA fallback via try_files |
| database | postgres:16 | 5432 | Named volume `lila-db` for persistence |
| forgejo | forgejo:... | 3000, 2222 | Git + container registry, SSH on 2222 |
**No ports exposed on internal services.** Only Caddy (80/443) and Forgejo SSH (2222) are public.
---
## Build & Deploy Flow
```
Dev laptop: git push to main
Forgejo Actions triggers (runner on VPS)
Build API image (target: runner)
Build Web image (target: production, VITE_API_URL baked in)
Push both to git.lilastudy.com registry
SSH into VPS, docker compose pull, restart containers
API container runs migrations on startup (migrate.js before server.js)
App updated (~25 min total)
```
**Cross-compilation:** Images built natively on ARM64 VPS (no QEMU). Dev laptop used for initial pushes before CI/CD was set up.
---
## Environment-Driven Config
Same code runs in dev and production. Environment variables control behavior:
| Variable | Dev | Production |
| ----------------- | ------------------------------------ | ------------------------------------------------- |
| `DATABASE_URL` | `postgres://...@localhost:5432/lila` | `postgres://...@database:5432/lila` |
| `BETTER_AUTH_URL` | `http://localhost:3000` | `https://api.lilastudy.com` |
| `CORS_ORIGIN` | `http://localhost:5173` | `https://lilastudy.com` |
| `COOKIE_DOMAIN` | undefined | `.lilastudy.com` |
| `VITE_API_URL` | `http://localhost:3000` | `https://api.lilastudy.com` (baked at build time) |
**Note:** `VITE_API_URL` is baked into the frontend at Docker build time via `--build-arg`. It cannot be changed at runtime.
---
## Database
### Migrations
Drizzle migrations run automatically on API container startup. The Dockerfile entrypoint:
```dockerfile
CMD ["node", "dist/src/migrate.js", "&&", "node", "dist/src/server.js"]
```
**Deploy order enforced automatically:** migrations before server starts.
### Backups
- Daily cron job at 3:00 AM: `pg_dump` → compressed SQL → `~/backups/`
- 7-day retention on VPS
- Dev laptop auto-syncs new backups on login via `rsync`
- **Offsite storage:** Planned (Hetzner Object Storage or S3-compatible)
### Seeding
Idempotent (`onConflictDoNothing`). Safe to re-run for adding new languages without affecting existing data or user tables.
---
## Auth & OAuth
**Better Auth** embedded in Express API. No separate auth service.
**Social providers:**
- Google OAuth — consent screen in testing mode (100 user cap). Must publish before reaching 80 users.
- GitHub OAuth — configured for both dev and production redirect URIs
**Cross-subdomain cookies:** `COOKIE_DOMAIN=.lilastudy.com` (leading dot) makes auth cookie valid across all subdomains.
---
## Known Issues & Limitations
| Issue | Impact | Status |
| --------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------- |
| lila-web has no healthcheck | Vite dev server has no health endpoint; `depends_on` uses API healthcheck as proxy | Acceptable for dev |
| Valkey memory overcommit warning | Harmless in dev. Fix before production: `vm.overcommit_memory = 1` | Documented |
| No centralized monitoring/logging | No uptime alerts or log aggregation on VPS | Planned (BACKLOG.md) |
| Backups only on VPS + dev laptop | No offsite protection against VPS failure | Planned (BACKLOG.md) |
| Google OAuth in testing mode | 100 user cap | Must publish before 80 users |
---
## Key Files
| File | Purpose |
| ------------------------------- | ------------------------------------------------------ |
| `docker-compose.yml` (root) | Local dev stack |
| `docker-compose.yml` (VPS) | Production stack |
| `apps/api/Dockerfile` | Multi-stage: deps → dev → builder → runner |
| `apps/web/Dockerfile` | Multi-stage: deps → dev → builder → production (nginx) |
| `apps/web/nginx.conf` | SPA fallback routing |
| `Caddyfile` | Reverse proxy routing, automatic HTTPS |
| `.forgejo/workflows/deploy.yml` | CI/CD pipeline |
| `apps/api/src/migrate.ts` | Drizzle migration runner |