# Deploy Folder This folder is the full production deploy toolkit for `honeyDueAPI-go`. Run deploy with: ```bash ./.deploy_prod ``` The script will refuse to run until all required values are set. ## First-Time Prerequisite: Create The Swarm Cluster You must do this once before `./.deploy_prod` can work. 1. SSH to manager #1 and initialize Swarm: ```bash docker swarm init --advertise-addr ``` 2. On manager #1, get join commands: ```bash docker swarm join-token manager docker swarm join-token worker ``` 3. SSH to each additional node and run the appropriate `docker swarm join ...` command. 4. Verify from manager #1: ```bash docker node ls ``` ## Security Requirements Before Public Launch Use this as a mandatory checklist before you route production traffic. ### 1) Firewall Rules (Node-Level) Apply firewall rules to all Swarm nodes: - SSH port (for example `2222/tcp`): your IP only - `80/tcp`, `443/tcp`: Hetzner LB only (or Cloudflare IP ranges only if no LB) - `2377/tcp`: Swarm nodes only - `7946/tcp,udp`: Swarm nodes only - `4789/udp`: Swarm nodes only - Everything else: blocked ### 2) SSH Hardening On each node, harden `/etc/ssh/sshd_config`: ```text Port 2222 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes AllowUsers deploy ``` ### 3) Cloudflare Origin Lockdown - Keep public DNS records proxied (orange cloud on). - Point Cloudflare to LB, not node IPs. - Do not publish Swarm node IPs in DNS. - Enforce firewall source restrictions so public traffic cannot bypass Cloudflare/LB. ### 4) Secrets Policy - Keep runtime secrets in Docker Swarm secrets only. - Do not put production secrets in git or plain `.env` files. - `./.deploy_prod` already creates versioned Swarm secrets from files in `deploy/secrets/`. - Rotate secrets after incidents or credential exposure. ### 5) Data Path Security - Neon/Postgres: `DB_SSLMODE=require`, strong DB password, Neon IP allowlist limited to node IPs. - Backblaze B2: HTTPS only, scoped app keys (not master key), least-privilege bucket access. - Swarm overlay: encrypted network enabled in stack (`driver_opts.encrypted: "true"`). ### 6) Dozzle Hardening - Keep Dozzle private (no public DNS/ingress). - Put auth/SSO in front (Cloudflare Access or equivalent). - Prefer a Docker socket proxy with restricted read-only scope. ### 7) Backup + Restore Readiness - Postgres PITR path tested in staging. - Redis persistence enabled and restore path tested. - Written runbook for restore and secret rotation. - Named owner for incident response. ## Files You Fill In Paste your values into these files: - `deploy/cluster.env` - `deploy/registry.env` - `deploy/prod.env` - `deploy/secrets/postgres_password.txt` - `deploy/secrets/secret_key.txt` - `deploy/secrets/email_host_password.txt` - `deploy/secrets/fcm_server_key.txt` - `deploy/secrets/apns_auth_key.p8` If one is missing, the deploy script auto-copies it from its `.example` template and exits so you can fill it. ## What `./.deploy_prod` Does 1. Validates all required config files and credentials. 2. Builds and pushes `api`, `worker`, and `admin` images. 3. Uploads deploy bundle to your Swarm manager over SSH. 4. Creates versioned Docker secrets on the manager. 5. Deploys the stack with `docker stack deploy --with-registry-auth`. 6. Waits until service replicas converge. 7. Runs an HTTP health check (if `DEPLOY_HEALTHCHECK_URL` is set). ## Useful Flags Environment flags: - `SKIP_BUILD=1 ./.deploy_prod` to deploy already-pushed images. - `SKIP_HEALTHCHECK=1 ./.deploy_prod` to skip final URL check. - `DEPLOY_TAG= ./.deploy_prod` to deploy a specific image tag. ## Important - `deploy/shit_deploy_cant_do.md` lists the manual tasks this script cannot automate. - Keep real credentials and secret files out of git.