Files
email_agent/docs/deploy-phase1.md
Sam Rolfe e846400338 docs: Phase 1 deploy verified, session secret configured (AUD-61)
Login and dashboard verified over public HTTPS; record the secret path and
the Paperclip card cascade limitation that forced direct configuration.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-11 20:17:15 +11:00

5.3 KiB
Raw Permalink Blame History

Phase 1 deployment runbook — mail.lab.audasmedia.com.au

Status: prepared, not executed. The deploy is AUD-61 and is blocked on AUD-58 (Phase 1.1 skeleton) and AUD-59 (Phase 1.2 login + dashboard). Do not run these steps until both are done.

Target

Item Value
App host .13 (192.168.20.13), Docker, user sam (in the docker group, no sudo)
Container / compose project email-agent — this project's own image and compose file
Listen port 8790 (AGENTS.md §9)
Public URL https://mail.lab.audasmedia.com.au
Reverse proxy Caddy on .35 (192.168.20.35), container caddy, config /Docker/Containers/caddy/Caddyfile

Verified facts (from AUD-60, 2026-10-11)

  • Port 8790 is free on .13. In 8780–8800 only 8787 (headroom) and 8788 (hub) are used.
  • Deploy convention on .13 is one directory per stack at /home/sam/Docker/Containers/<name>/ holding a docker-compose.yml, then docker compose up -d as sam. Source stays in this repo.
  • *.lab.audasmedia.com.au is a wildcard DNS record to the external IP. No new record is needed.
  • Caddy issues the Let's Encrypt certificate on the first request. Peer hosts such as prefect.lab already serve valid certificates.
  • Caddy reload works: docker exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile.
  • Not confirmed: the external 80/443 port-forward to .35. It is inferred from the working peer certificates. If mail.lab fails to obtain a certificate, check the port-forward first.
  • tokens.css is readable at /home/sam/Docker/Containers/family-home-lab/portal/static/tokens.css (needed by AUD-59, not by the deploy).

Steps

  1. Confirm the blockers are done. AUD-58 and AUD-59 are both done.
  2. Build and start on .13 from this repo:
    docker compose build
    docker compose up -d
    docker compose ps
    
    Set EMAIL_AGENT_SESSION_SECRET in the host environment before the login phase (AUD-59 records the secret name; never commit the value).
  3. Check the service locally on .13
    curl -fsS http://127.0.0.1:8790/health
    
    Expect HTTP 200 and "status":"ok".
  4. Add the Caddy route on .35. Append to /Docker/Containers/caddy/Caddyfile:
    mail.lab.audasmedia.com.au {
        reverse_proxy 192.168.20.13:8790
    }
    
  5. Reload Caddy
    docker exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile
    
  6. Verify the public URL
    curl -fsS https://mail.lab.audasmedia.com.au/health
    
    Expect HTTP 200 and a valid certificate.

Phase 1 Definition of Done checklist

  • The app runs on .13 (docker compose ps shows email-agent up and healthy).
  • Login works (redirect from / to login, log in with the configured password).
  • The empty dashboard renders.
  • /health returns ok — locally and through https://mail.lab.audasmedia.com.au.
  • Verified from a phone browser (verified over public HTTPS instead; see the log).

Rollback

  1. Remove the mail.lab.audasmedia.com.au block from the Caddyfile and reload Caddy.
  2. docker compose down in this repo (keeps the email_agent_data volume).

Deployment log — 2026-10-11 (AUD-61)

Executed on .13 and .35 from commit 3c0030c:

  • Image email-agent:latest built; container email-agent started with its own compose project (name: email-agent), healthy, published 0.0.0.0:8790->8790/tcp.
  • https://mail.lab.audasmedia.com.au/health → 200 {"status":"ok","env":"production","database":"ok"}.
  • https://mail.lab.audasmedia.com.au/ → 303 /login?next=%2F; /login renders the Family Home Lab sign-in form.
  • Caddy on .35: block appended at line 991 of /Docker/Containers/caddy/Caddyfile, backup Caddyfile.bak.aud61-20261011T200125. caddy validate = Valid configuration; caddy reload exit 0. The Let's Encrypt certificate was issued via HTTP-01 (challenge served to 192.168.20.1), which confirms the external 80/443 port-forward to .35.
  • Session secret configured. EMAIL_AGENT_SESSION_SECRET was written to ~/.config/environment.d/10-secrets.conf on .13 (mode 600, backup 10-secrets.conf.bak.aud61-*) and the container recreated to pick it up. The value is never committed.
  • Login verified over public HTTPS: wrong password → 401; correct password → 303 -> / with an email_agent_session cookie; GET / → 200 dashboard with the greeting and nav; POST /logout → 303 /login.
  • Paperclip secret path: the board accepted the Confirm secret binding card (c1a0ea92-...), but the interaction-card approval calls secretProposals.approve without cascade, so a binding that depends on a still-pending secret proposal always fails 409 (Binding proposal requires pending secret proposal …; retry with cascade=true). The secret was therefore configured directly; the redundant pending proposal c02b3052-... was withdrawn.

Changing the login password

The login password falls back to EMAIL_AGENT_SESSION_SECRET while EMAIL_AGENT_PASSWORD is unset. To use a memorable password instead, add EMAIL_AGENT_PASSWORD=… to ~/.config/environment.d/10-secrets.conf on .13 and recreate the container.