Fix healthcheck + verify commands; reframe deploy runbook for a capable agent

Real bug: the container healthcheck (and the docs' verify step) hit
/api/capabilities, which returns 403 unauthenticated; curl --fail treats
403 as an error, so a healthy container would report "unhealthy" and the
verify step would look like a failure. Healthcheck now hits /accounts/login/
(200, no auth). Verify commands now print the status code and note not to
use curl -f on the 403.

Also reframed cloud_agent_deploy.md's intro for an Opus-class deploy agent:
it's a guide + Daybook-specific gotchas, not a rigid script — points at the
authoritative sources (repo incl. the git-SSH :2222 note, deploy/ files,
requirements.txt deps auto-installed, entrypoint runs migrate+collectstatic,
docs/deployment.md) and trusts the agent's judgment. Dropped the now-
redundant Source Of Truth section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
peter 2026-09-03 14:32:39 +01:00
parent a355285f3b
commit ca8e364010
3 changed files with 41 additions and 24 deletions

View file

@ -1,25 +1,33 @@
# Cloud Deployment Runbook For A Dedicated Deploy Agent
This document is written for an autonomous AI agent responsible for deploying
and operating Daybook on a cloud VM, without a human walking through each
step. Follow it in order. Where a decision depends on information you don't
have (VM IP, domain, whether TLS is required), ask the operator once, then
proceed autonomously for routine redeploys.
This is written for a capable (Opus-class) agent deploying and operating
Daybook on a cloud VM. Treat it as a guide and a source of Daybook-specific
facts, **not a rigid script** — you're expected to use judgment, adapt to
the actual VM, and read the authoritative sources rather than follow steps
blindly. The steps below are a sensible default path; deviate where the host
warrants it.
For background on the app itself and the general (human-facing) version of
this workflow, see `docs/deployment.md`. This file is the operational SOP;
that one is the reference.
Ground truth, in order of authority (prefer these over this doc if they ever
disagree):
## Source Of Truth
- **The repo** — `https://git.cygnus.systems/peter/daybook.git` (private
Forgejo). Everything ships from here; deploy from a clone so `git pull`
works. Note: this Forgejo's git-SSH is on port **2222**, not 22.
- **`deploy/`** — `Dockerfile`, `docker-compose.yml`, `entrypoint.sh`,
`env.example`. These *are* the deployment: the image installs all Python
deps from `requirements.txt` (Django, DRF, Markdown, Pygments, nh3,
openpyxl, gunicorn, whitenoise), and `entrypoint.sh` runs `migrate` +
`collectstatic` on every start, so schema and static assets are always
current. Read them; don't assume.
- **`docs/deployment.md`** — the general (host-agnostic) deployment
reference and rationale.
The canonical source is a private Forgejo repository:
```text
https://git.cygnus.systems/peter/daybook.git
```
Do not deploy from a copied/rsynced tree. Always deploy from a git clone of
this repository so `git pull` is available for fast redeploys.
Where a decision needs info you don't have (VM IP, domain, whether it's
internet-facing, whether a reverse proxy/secondary volume exists), ask the
operator once, then proceed autonomously for routine redeploys. The rest of
this file is the recommended path plus the non-obvious, Daybook-specific
gotchas (SSH port, CSRF-behind-proxy, bind address, data volume, healthcheck)
that are easy to get wrong.
## 0. Get Repo Access
@ -166,11 +174,14 @@ every start.
```bash
docker compose -f deploy/docker-compose.yml ps
curl -fsS http://127.0.0.1:8000/api/capabilities
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/api/capabilities # expect 403
```
A `403` with `"Login or a valid API token is required"` is the **expected**
response when unauthenticated — it confirms the app is up. This `curl` runs
response when unauthenticated — it confirms the app is up. (Don't use
`curl -f` here: `--fail` treats the 403 as an error and hides it. The
container's own healthcheck hits the login page instead, which is 200
without auth.) This `curl` runs
against `127.0.0.1` from on the VM itself, so it works regardless of whether
`DAYBOOK_BIND_ADDR` is set. Log in from a browser at whichever address is
actually externally reachable at this point in the runbook — `http://<vm-ip>:8000/`