# Phase 1 deployment runbook — `mail.lab.audasmedia.com.au` Status: **prepared, not executed.** The deploy is [AUD-61](/AUD/issues/AUD-61) and is blocked on [AUD-58](/AUD/issues/AUD-58) (Phase 1.1 skeleton) and [AUD-59](/AUD/issues/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](/AUD/issues/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//` 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: ```sh 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`** ```sh 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** ```sh docker exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile ``` 6. **Verify the public URL** ```sh 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. ## 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`. - **Not yet done:** a password login and the empty dashboard need `EMAIL_AGENT_SESSION_SECRET`. This waits on human approval of the **Confirm secret binding** card on AUD-61 (`c1a0ea92-b969-4ad2-94c0-74641b19203c`, from secret proposal `c02b3052-...`). Until the secret is configured, `/login` shows “Login is not configured”.