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>
112 lines
5.3 KiB
Markdown
112 lines
5.3 KiB
Markdown
# 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/<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:
|
||
```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
|
||
|
||
- [x] The app runs on `.13` (`docker compose ps` shows `email-agent` up and healthy).
|
||
- [x] Login works (redirect from `/` to login, log in with the configured password).
|
||
- [x] The empty dashboard renders.
|
||
- [x] `/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.
|
||
|