Repository navigation
Operations
-
GET /health— liveness: the process is up. Always200 {"status":"ok"}. -
GET /health/ready— readiness: dependencies are reachable. Returns200with{"status":"ready","checks":{"database":"ok","redis":"ok"}}when the database (and Redis, if configured) respond, or503 {"status":"not ready", ...}otherwise.
The Compose backend service uses /health/ready as its container healthcheck, so
docker compose ps reports the backend healthy only once it can serve real traffic.
Off unless SENTRY_DSN is set in backend/.env. When set, unhandled errors are reported to
Sentry with request context (method, path, status) via the auto-enabled FastAPI integration.
SENTRY_ENVIRONMENT (default production) and SENTRY_TRACES_SAMPLE_RATE (default 0.0) are
optional. send_default_pii is off, so no user PII is attached.
To enable: create a project at https://sentry.io (free tier), copy its DSN, set
SENTRY_DSN=... in backend/.env, and redeploy.
The React app reports client errors and Web Vitals (LCP/CLS/INP) to Sentry when
VITE_SENTRY_DSN is set. Unlike the backend DSN, this is a build-time value: Vite inlines
it into the bundle, so it is passed as a Docker build arg (--build-arg VITE_SENTRY_DSN=...),
wired in CI from the VITE_SENTRY_DSN repository variable. With no DSN the Sentry SDK is
tree-shaken out entirely (no bundle cost). The DSN is public/client-safe, so it is a repo
variable, not a secret. Source maps are emitted so minified stack traces symbolicate.
To enable: create a React project in Sentry, copy its DSN, set the VITE_SENTRY_DSN repository
variable (GitHub → Settings → Variables), and let the next main build ship it.
scripts/backup-db.sh dumps the db service to a gzipped file under backups/ and prunes
files older than RETENTION_DAYS (default 14). The backups/ directory is git-ignored.
It runs in two places: on a cron schedule, and from deploy.yml immediately before up -d —
migrations apply automatically when the backend starts, so that is the last moment a rollback
is cheap. The script writes to a .part file and renames only on success, so a failed
pg_dump leaves nothing behind that looks like a usable backup; the deploy gates on its exit
code.
./scripts/backup-db.shSchedule it daily on the VM with cron (crontab -e):
15 3 * * * cd /home/ubuntu/Palette && ./scripts/backup-db.sh >> backups/backup.log 2>&1Restore a dump:
gunzip -c backups/palette-YYYYMMDD-HHMMSS.sql.gz | docker compose exec -T db psql -U palette -d paletteDependabot opens its version-update pull requests against the long-lived deps branch, not
main, so routine churn collects in one place and reaches main as a single deliberate merge.
git checkout deps && git merge main # after any release that touched a manifestThat merge is not optional housekeeping. Dependabot compares manifests against deps, so a
package bumped by hand on main is invisible to it and the next update arrives on a stale
base.
Security updates ignore this setting. Dependabot always raises those against the default branch, which is the behaviour you want — an urgent patch should not sit in a queue behind a routine minor bump.