Harden prod deploy: versioned secrets, healthchecks, migration lock, dry-run

Swarm stack
- Resource limits on all services, stop_grace_period 60s on api/worker/admin
- Dozzle bound to manager loopback only (ssh -L required for access)
- Worker health server on :6060, admin /api/health endpoint
- Redis 200M LRU cap, B2/S3 env vars wired through to api service

Deploy script
- DRY_RUN=1 prints plan + exits
- Auto-rollback on failed healthcheck, docker logout at end
- Versioned-secret pruning keeps last SECRET_KEEP_VERSIONS (default 3)
- PUSH_LATEST_TAG default flipped to false
- B2 all-or-none validation before deploy

Code
- cmd/api takes pg_advisory_lock on a dedicated connection before
  AutoMigrate, serialising boot-time migrations across replicas
- cmd/worker exposes an HTTP /health endpoint with graceful shutdown

Docs
- deploy/DEPLOYING.md: step-by-step walkthrough for a real deploy
- deploy/shit_deploy_cant_do.md: manual prerequisites + recurring ops
- deploy/README.md updated with storage toggle, worker-replica caveat,
  multi-arch recipe, connection-pool tuning, renumbered sections

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-04-14 15:22:43 -05:00
parent ca818e8478
commit 33eee812b6
11 changed files with 908 additions and 30 deletions

View File

@@ -12,11 +12,21 @@ DEPLOY_HEALTHCHECK_URL=https://api.honeyDue.treytartt.com/api/health/
# Replicas and published ports
API_REPLICAS=3
WORKER_REPLICAS=2
# IMPORTANT: keep WORKER_REPLICAS=1 until Asynq PeriodicTaskManager is wired.
# The current asynq.Scheduler in cmd/worker/main.go has no Redis-based
# leader election, so running >1 replica fires every cron task once per
# replica → duplicate daily digests / onboarding emails / etc.
WORKER_REPLICAS=1
ADMIN_REPLICAS=1
API_PORT=8000
ADMIN_PORT=3000
DOZZLE_PORT=9999
# Build behavior
PUSH_LATEST_TAG=true
# PUSH_LATEST_TAG=true also tags and pushes :latest on the registry.
# Leave false in production to keep image tags immutable (SHA-pinned only).
PUSH_LATEST_TAG=false
# Secret retention: number of versioned Swarm secrets to keep per name after each deploy.
# Older unused versions are pruned post-convergence. Default: 3.
SECRET_KEEP_VERSIONS=3