diff options
| author | batsumaru <> | 2026-07-01 15:38:51 +0900 |
|---|---|---|
| committer | batsumaru <> | 2026-07-01 15:38:51 +0900 |
| commit | dfec6df2fb876fadb20d24a5bd8f4b4400a0f659 (patch) | |
| tree | 3fc126f5bbaeef31b3a7a6d3e2afda968473c9b9 /statuspage/README.md | |
Split monolithic status check.sh into modular check scripts
Replace the single-file prototype with independently-addable check
scripts (checks/*.sh) that each emit JSONL rows, a shared helper lib,
and one orchestrator/renderer (render.sh) that groups rows by section
and writes the static status page. A broken check script now shows up
as a down/warn row instead of crashing the whole render.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'statuspage/README.md')
| -rw-r--r-- | statuspage/README.md | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/statuspage/README.md b/statuspage/README.md new file mode 100644 index 0000000..3c2ae85 --- /dev/null +++ b/statuspage/README.md @@ -0,0 +1,109 @@ +# dandokmang status console + +Static status page for the dandokmang homelab server. A cron job runs +`render.sh`, which runs every check script in `checks/`, collects their +output, and writes a static `index.html` served by Caddy on the WireGuard +interface only. + +## Layout + +``` +statuspage/ + checks/ one script per metric or group of related metrics + lib/ + common.sh shared helpers (svc_status, port_check, jail_status, json_line) + render.sh orchestrator + HTML renderer + README.md +``` + +## The check-script contract + +This is the part to remember when you come back in six months to add a +metric: **every script in `checks/` is independent. `render.sh` never +changes to support a new check.** + +A check script must: + +- Be executable (`chmod +x`). +- Emit **one JSON object per line** (JSONL) to stdout, and nothing else. +- Emit no output to stdout on failure (send diagnostics to stderr if you + want them, but they're discarded by the renderer). + +Each JSON object has exactly these fields: + +| field | meaning | +|-----------|-------------------------------------------------------------------| +| `section` | groups rows under a heading: `hardware`, `host services`, `jails` (or a new section name - unrecognized sections are rendered after the known ones, in the order first seen) | +| `label` | display name for the row | +| `value` | display value; use `""` for a plain up/down check with no value | +| `status` | one of `ok`, `warn`, `down` - maps to a green/yellow/red square | + +Example (`checks/wireguard.sh`): + +```json +{"section": "host services", "label": "wireguard (wg0)", "value": "", "status": "ok"} +``` + +A script can emit multiple lines - `hw.sh` emits one line each for load +avg, uptime, free mem, zroot usage, and zpool health. + +Use `json_line SECTION LABEL VALUE STATUS` from `lib/common.sh` instead of +hand-rolling the JSON - it escapes backslashes, quotes, and embedded +newlines (e.g. a multi-line `zpool status -x` when a pool is degraded) so +the JSONL stays one object per line no matter what a command prints. + +### Adding a new check + +1. Create `checks/<section>-<name>.sh` (or reuse an existing section + script if the metric belongs with it). +2. `. "$(dirname "$0")/../lib/common.sh"` and call `json_line` for each row. +3. `chmod +x` it. + +That's it - no changes to `render.sh`, no template edits. It picks up any +executable `checks/*.sh` file automatically and renders whatever sections +it finds. + +## Failure isolation + +`render.sh` runs each check script and handles three failure modes without +aborting the whole render: + +- **Non-zero exit** -> a `down` row labeled with the script's filename under + a synthetic `checks` section. +- **No output** -> a `warn` row, same treatment. +- **Output that doesn't look like our JSONL** -> a `warn` row, same + treatment. + +So a broken check shows up as a visible red/yellow row on the page instead +of silently disappearing or crashing the render. + +## Dependencies + +Parsing is done with plain `awk`/`sed`/`grep` against the constrained JSONL +shape our own `json_line` helper produces - no `jq` dependency. If checks +ever need to emit richer JSON (nested objects, arrays), the awk parser in +`render.sh` (`jsonval()`) will need to grow or be swapped for `jq`. + +## Deployment + +Cron (as root): + +``` +* * * * * /usr/local/etc/statuspage/render.sh +``` + +Caddyfile (bind to the WireGuard interface IP only): + +``` +172.16.0.1:8080 { + root * /usr/local/www/status + file_server +} +``` + +Reload Caddy after editing: `service caddy reload`. +Access from a WireGuard peer: `http://172.16.0.1:8080`. + +`render.sh` writes to `/usr/local/www/status/index.html` by default; +override with the `STATUSPAGE_OUT` environment variable (useful for local +testing without root). |
