A status page from one YAML file
By June there were enough small things running at home that I couldn't tell at a glance whether they were all alive. I wanted one page that answers that.
- Project
- yamlstatus
- Stack
- TypeScript, Node, YAML
- Time spent
- About 4 evenings
- Status
- every 5 minutes
didWhat I did
Every check lives in one YAML file. There are three kinds: an HTTP request that expects a status code, a TCP connection to a port, and the age of a file. The third one exists because of the backup script, which touches a timestamp file when it succeeds.
checks:
- name: File share
type: tcp
host: 192.168.1.20
port: 445
- name: Feed digest
type: http
url: http://localhost:8080/health
expect: 200
- name: Nightly backup
type: file-age
path: /var/lib/backup/last-success
max_age: 36h
A Node script reads the file, runs every check, and writes a single static HTML page with a row per check: name, state, how long it took and when it last changed. The existing web server serves that page. No database, no daemon; a systemd timer runs the script every five minutes.
- File sharetcp4 ms
- Feed digesthttp 20038 ms
- Nightly backupfile age18 h
- Old laptoptcptimeout 5 s
brokeWhat broke
Strings versus numbers. The HTTP check always failed for one service. I had written expect: "200" in that entry, with quotes, and the code compared it with === to a number. The loader now validates the file against a schema at startup and rejects anything it doesn't understand, with the line number, instead of guessing.
One slow check stalled everything. The checks ran one after another, and a TCP connect to a machine that was switched off has no timeout by default. One run took over two minutes. Now every check runs at once with its own five-second limit:
const CHECK_TIMEOUT_MS = 5_000
const results = await Promise.allSettled(
checks.map((check) => runCheck(check, AbortSignal.timeout(CHECK_TIMEOUT_MS))),
)
A page that lies. When the timer itself stopped (I had broken the unit file while editing it), the last page stayed up, all green, for a day. The page now shows when it was generated, and a few lines of script on the page turn the header amber if that time is more than fifteen minutes old. A status page has to be able to say "I don't know".
nextWhat's next
- History: keep the last 24 hours of results in a JSON file and draw a thin strip per check.
- An RSS feed of state changes only. The morning digest from March can then tell me when something went down overnight.
- A check type for the temperature sensor, once that project exists.