docs: record the deployed homepage + the Caddyfile handle design
The homepage is live on Dankclaw. Update the Status (deployed) and the Auth section (the handle-block design, the Caddyfile directive-sorting pitfall, the host /srv/homepage mount, and the container-recreate note). Cross-reference the agent KB Caddyfile syntax page.
This commit is contained in:
@@ -4,11 +4,11 @@ A password-protected web site on Dankclaw lists the services that are up, with a
|
||||
|
||||
**Served by:** Caddy, `file_server` + `basicauth` — **Docs:** this page
|
||||
|
||||
## Status — 2026-08-23: built, pending deploy
|
||||
## Status — 2026-08-23: deployed to production
|
||||
|
||||
The homepage is built and tested (112 tests pass). The assets are in `shared/homepage/` (the pages, the theme, the toggle, `services.json`), the checker is in `scripts/` (`homepage-status.py` + the timer + service), and `deploy.sh` ships it. The render logic is verified with a Node DOM shim.
|
||||
The homepage is live on Dankclaw. `./scripts/deploy.sh dankclaw` copies the static assets to `/srv/homepage/`, installs the status checker (systemd timer, every 3 min, writes `status.json`), writes `deployed.js` (the last master deployment datetime), renders the Caddyfile (both basicauth hashes from the host `.env`), reloads Caddy, and checks health. 116 tests pass. The Caddyfile auth uses `handle` blocks (see [Auth](#auth)); the caddy container mounts the host's `/srv/homepage` (not the repo source) so the generated files serve.
|
||||
|
||||
It is not yet deployed to `/srv/homepage/` on the target. To go live, the operator adds `CADDY_ADMIN_HASH` (the operator-only password, `caddy hash-password`) to the target `.env`, then runs `./scripts/deploy.sh dankclaw`. Until then the admin hash stays a placeholder and the `/admin/` page auth is not live.
|
||||
To change the operator password: regenerate `CADDY_ADMIN_HASH` (`caddy hash-password`) in the host `.env`, then redeploy. The per-service `/docs/` pages, the *arr stack, and the optional `/how/` page remain separate threads.
|
||||
|
||||
## Design decision — 2026-08-22
|
||||
|
||||
@@ -110,22 +110,43 @@ Styling is **toggleable** (Q27). The default is the full terminal theme. A toggl
|
||||
|
||||
## Auth
|
||||
|
||||
Caddy wraps the site with HTTP basic auth. The root page uses the shared password. The `/admin/` page uses a second, operator-only password. The hashes come from the host `.env` (git-ignored). Do not commit the hash or the password.
|
||||
Caddy wraps the site with HTTP basic auth. The root page uses the shared password. The `/admin/` page uses a second, operator-only password. The shared data + assets accept **both** (the browser reuses the page's credential for the data fetches). The hashes come from the host `.env` (git-ignored). Do not commit the hash or the password.
|
||||
|
||||
The pages are served from `handle` blocks, not a top-level `rewrite`. Caddy **sorts** top-level directives, so a `rewrite` runs before a `basicauth`; the rewrite would change `/admin/` to `/admin.html` and the path-based auth matchers would then see the rewritten path and apply the wrong block. A `handle` block preserves file order, so the auth is checked on the original path.
|
||||
|
||||
```
|
||||
dankclaw.franksdank.cloud {
|
||||
@admin path /admin/*
|
||||
basicauth {
|
||||
dank {env.CADDY_BASICAUTH_HASH}
|
||||
}
|
||||
basicauth @admin {
|
||||
frank {env.CADDY_ADMIN_HASH}
|
||||
}
|
||||
root * /srv/homepage
|
||||
file_server
|
||||
|
||||
handle /admin* {
|
||||
basicauth {
|
||||
frank REPLACE_WITH_ADMIN_HASH
|
||||
}
|
||||
try_files /admin.html
|
||||
file_server
|
||||
}
|
||||
|
||||
@data path /services.json /status.json /app.js /style.css /deployed.js
|
||||
handle @data {
|
||||
basicauth {
|
||||
dank REPLACE_WITH_HASH
|
||||
frank REPLACE_WITH_ADMIN_HASH
|
||||
}
|
||||
file_server
|
||||
}
|
||||
|
||||
handle {
|
||||
basicauth {
|
||||
dank REPLACE_WITH_HASH
|
||||
}
|
||||
try_files /index.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A `handle` inline matcher is a single token; the multi-path `@data` match is a named matcher. The caddy container mounts the host's `/srv/homepage` (where the deploy writes the static files and the checker writes `status.json`), not the repo's `shared/homepage`. A compose change needs a container recreate (`podman compose up -d caddy`), not a reload. The Caddyfile syntax is documented in the agent knowledge base (`~/.pi/agent/docs/caddy/caddyfile.md`).
|
||||
|
||||
## Service entry format
|
||||
|
||||
```json
|
||||
|
||||
Reference in New Issue
Block a user