deadhead-space-freight-tycoon/deploy/README.md

2.6 KiB

Deploying Deadhead

The production stack runs on one machine with Docker Compose: Postgres, the API server and Caddy. Caddy serves the web app, proxies /api to the server and gets HTTPS certificates for the domain automatically.

Before the first start

  1. DNS: point an A record for deadhead.belowland.com at the public IP of the network the server is on.
  2. Router: forward TCP ports 80 and 443 (and UDP 443 for HTTP/3) to the server. Let's Encrypt checks port 80 before it issues a certificate.
  3. Docker: Docker Engine with the Compose plugin (docker compose version).
  4. Settings: in this folder, cp .env.example .env and fill in POSTGRES_PASSWORD and BETTER_AUTH_SECRET (the comments say how to make them). Keep .env private; it is ignored by git.

Start and update

From this folder, on the server:

git pull
APP_BUILD=$(git rev-parse --short HEAD) docker compose up -d --build

The server applies database migrations on every start, then begins serving. docker compose ps shows each service's health; docker compose logs -f server follows the API log. The About screen in Settings shows the build you deployed.

On a LAN only (no domain)

Set SITE_ADDRESS=:80 and PUBLIC_URL=http://<server-ip> in .env. Caddy then serves plain HTTP. Installing the app to a phone home screen needs HTTPS, so this is for testing.

Check a build before deploying

deploy/check.sh

This builds and starts the whole stack under a separate project name with throwaway secrets, on port 8088. It checks the API, the app, caching, a guest sign-up with a tutorial run, and a backup restored into a fresh database. Then it removes everything. It never touches the real stack.

Backups

The backup service writes a compressed dump of the database every night at BACKUP_HOUR:00 (TZ, default UTC) to BACKUP_DIR, and deletes dumps older than BACKUP_KEEP_DAYS. Point BACKUP_DIR at a folder that lives on another disk, such as a NAS share mounted on the server (for example through /etc/fstab). Make sure the share is mounted before Docker starts, or the dumps land on the server's own disk.

Take a backup now:

docker compose exec backup /scripts/backup.sh

Test a restore without touching the live data. This loads the newest dump into a separate deadhead_restore database:

docker compose exec backup /scripts/restore.sh

Recover the live database from a dump (stop the server first so nothing writes while it loads):

docker compose stop server
docker compose exec backup /scripts/restore.sh /backups/deadhead-<stamp>.dump deadhead
docker compose start server