CLAUDE.md shrinks to rules + status + index (175 lines, down from 476). Dev setup, prod deploy, and per-phase build records move to docs/. Gotchas regrouped by domain (auth, frontend, PWA, testing, backend, deploy, platform) and unnumbered so they don't drift as new ones land. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.1 KiB
3.1 KiB
Deployment
Production stack — ambrosio (OVH VPS)
Live URLs: https://erosi.oier.ovh (app + Supabase API, single-domain) + https://auth.oier.ovh (Keycloak). OVH VPS, Ubuntu 24, Docker 29.
infra/docker-compose.erosi.yml— full stack bound to127.0.0.1only (db, auth, rest, realtime, storage, imgproxy, kong, keycloak, app).studio+metaintentionally dropped for prod.infra/caddy/erosi.Caddyfile— snippet appended to the host's/etc/caddy/Caddyfilebetween# BEGIN colectivo-erosi/# END colectivo-erosimarkers. Host Caddy 2.11.2 handles TLS (Let's Encrypt via tls-alpn-01).erosi.oier.ovhroutes/auth/v1/*,/rest/v1/*,/realtime/v1/*,/storage/v1/*,/graphql/v1/*,/pg/*→ Kong :8000; everything else → SvelteKit :3000.auth.oier.ovh→ Keycloak :8090 withX-Forwarded-Portexplicitly (Caddy auto-sets Proto/Host/For).infra/scripts/deploy-erosi.sh— idempotent redeploy: rsync → generate secrets on first run (viainfra/scripts/rotate-jwt.sh) → substitute__KEYCLOAK_CLIENT_SECRET__inkeycloak/realm-export.erosi.json→ docker compose build + up → run pending migrations → re-install Caddy snippet → reload.keycloak/realm-export.erosi.json— prod realm:registrationAllowed: true, redirect URIs scoped tohttps://erosi.oier.ovh/*, client secret placeholder that the deploy script substitutes with a per-install random value. No dev users..env.erosi.example— committed template. The real/opt/colectivo/.envon ambrosio is 600 and stays on the server.- UFW allows
80/tcp,443/tcp,22/tcp. All other ports remain DENY. Docker services listen on127.0.0.1only, so Kong / Keycloak / the app are unreachable from the public internet except via Caddy.
Prod-specific fixes
Had to be made for the stack to boot cleanly on a fresh volume:
infra/db-init/00-role-passwords.sh— rewrote as idempotent bootstrap (see the "supabase/postgres doesn't bootstrap Supabase roles" gotcha inCLAUDE.md): creates all Supabase service roles if absent, enablespg_cron+pgcrypto+uuid-ossp, createsauth/storage/graphql_public/_realtime/realtimeschemas + emptysupabase_realtimepublication +keycloakdatabase + role, setssupabase_auth_adminsearch_path toauth. The old00-role-passwords.sql(ALTER-only) has been removed.apps/web/vite.config.ts— PWA strategy switchedinjectManifest→generateSW(see the "injectManifest hardcoded filename" gotcha inCLAUDE.md).- Keycloak container uses
start --import-realm(no--optimized) so Quarkus re-builds with the Postgres driver on first boot; with--optimizedit silently falls back to H2 and fails with "jdbc:h2 URL format error".
Keycloak admin password
Generated per-install — retrieve with ssh ambrosio 'grep KEYCLOAK_ADMIN_PASSWORD /opt/colectivo/.env'. Console at https://auth.oier.ovh/admin.
Not yet configured on ambrosio
- SMTP (Resend)
- Automated backups — script exists at
infra/scripts/backup.sh, not scheduled - Lighthouse run against prod URL
- Final production icons