fix(ops): the hourly backup never ran, and an unset POSTGRES_USER crash-loops silently
**The backup that did not exist.** `.env.example` ships `EVENT_NAME=Max & Maria's Wedding` and the runbook tells you to `cp .env.example .env`. Compose's env_file parser reads that fine. POSIX `sh` does not: `. ./.env` aborts with "Unterminated quoted string" (verified, rc=2), and every variable defined after that line is left unset. The §10.2 cron script is `#!/bin/sh` + `set -eu` + `. ./.env`, so it exited before `pg_dump` — every hour, into a log nobody reads. The only automated backup of the one thing the runbook calls irreconstructible produced nothing, and §10.2's own "prove it works NOW" only catches it if `.env` is already final at that moment. The script reads NOTHING from `.env` — `POSTGRES_USER`/`POSTGRES_DB` are expanded inside the db container by the single-quoted `sh -c`. The source line was pure liability and is gone. `EVENT_NAME` is now double-quoted in `.env.example`, which both parsers read identically (verified), and the three interactive sourcing sites now read just `$DOMAIN` instead of sourcing the whole file. The verify step also proves the dump is a non-empty valid gzip containing tables, rather than that a file exists. Also fixes the script's `cd /root/eventsnap`, which contradicts §5's non-root deploy and §13's `~/eventsnap` — under a non-root deploy it failed the same way, silently. **The crash loop with no message.** `docker-compose.yml` interpolated `POSTGRES_USER`/`POSTGRES_DB` with no default and no `:?` guard, into `environment:`, which OVERRIDES `env_file`. Unset does not fall back — it resolves to the empty string, initdb creates a role and database named "", `DATABASE_URL` still says `eventsnap`, and the app hits `FATAL: role "eventsnap" does not exist` forever. `pg_isready -U "" -d ""` never passes, so `app` never turns healthy and Caddy — gated on `service_healthy` — never starts: port 443 dead for the whole event, exit only via `down -v`. Both now carry `:?` guards (verified they fire), and §3's ".env template — ALL of them" list, which omitted both, now includes them. Other runbook corrections: the backup/restore pointer named a line range that had drifted into an unrelated section and stopped mid-restore, before the media restore and the mandatory `chown` — now referenced by heading, which cannot go stale. §7.3 told you to verify that `EXPORT_PATH` is not pinned when §3 correctly says it is. Stale counts: rev-list 196 -> 217, "versions 007–022" -> 007–031, `frontend/Dockerfile:9` -> :8, and the low-disk description now matches the code (the 10 GB absolute floor was removed as unreachable). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,9 +18,18 @@ services:
|
||||
logging: *default-logging
|
||||
env_file: .env
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
# `:?` for the same reason EVENTSNAP_VERSION and DOMAIN use it, and this is the worst place
|
||||
# to omit it. These are interpolated into `environment:`, which OVERRIDES `env_file` — so an
|
||||
# unset value does not fall back to `.env`, it resolves to the empty string and initdb
|
||||
# creates a role and database literally named "". `DATABASE_URL` still points at `eventsnap`,
|
||||
# so the app hits `FATAL: role "eventsnap" does not exist` forever, `pg_isready -U "" -d ""`
|
||||
# never passes, `app` never turns healthy, and Caddy — gated on `service_healthy` — never
|
||||
# starts, so port 443 is dead for the whole event. The only clean exit is `down -v`, which
|
||||
# destroys the volume. The runbook's §3 secrets list omitted both of these, so an operator
|
||||
# writing `.env` from the runbook rather than from `.env.example` walked straight into it.
|
||||
POSTGRES_USER: ${POSTGRES_USER:?set POSTGRES_USER in .env (see .env.example)}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
|
||||
POSTGRES_DB: ${POSTGRES_DB:?set POSTGRES_DB in .env (see .env.example)}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
|
||||
Reference in New Issue
Block a user