Static status page for consolving services, deployed via GitHub Pages at https://status.consolving.de.
A GitHub Action runs every 30 minutes, checks all configured hosts via their
/health endpoint, appends the result to rolling history files
(daily / weekly / monthly / yearly) and regenerates the static HTML page from
that history.
GitHub Action (cron */30)
└─ scripts/check.py checks every host from config/hosts.json
│ └─ appends entry to data/daily|weekly|monthly/
│ └─ updates per-day summary in data/yearly/
│ └─ prunes history beyond retention
├─ commits data/ back to the repo (history lives in git)
└─ scripts/generate.py renders site/index.html from the history files
└─ deployed to GitHub Pages
Each checked host runs the small health-status daemon (private repo on git-lab.de) which answers with a JSON like:
{
"status": "ok",
"timestamp": "2026-11-09T12:00:00Z",
"infrastructure": {"ok": 3, "warning": 0, "error": 0},
"workloads": {"ok": 24, "warning": 0, "error": 0}
}- A host is error when unreachable, answering non-200/invalid JSON, or
when any of
infrastructure/workloadsreportserror > 0. - Warning when any of them reports
warning > 0, else ok. - Uptime = runs without
error/ total runs.
| Path | Purpose |
|---|---|
.github/workflows/status.yml |
Cron check + history commit + Pages deploy |
config/hosts.json |
Hosts to monitor (name + full health URL) |
scripts/check.py |
Runs the checks, writes history files |
scripts/generate.py |
Renders site/ from history |
assets/template.html |
HTML template used by the generator |
data/ |
History files, committed by the action |
CNAME |
Custom domain for GitHub Pages (status.consolving.de) |
Edit config/hosts.json:
{
"hosts": [
{ "name": "host1.consolving.net", "url": "http://host1.consolving.net:11012/health" }
]
}The URL points to the health-status daemon of that host — not routed
through traefik, so the check still works when traefik is down. The daemon
listens on its own port (default 11012).
Raw check results (one entry per run) are stored per period:
| Period | File | Retention |
|---|---|---|
| Daily | data/daily/YYYY-MM-DD.json |
90 days |
| Weekly | data/weekly/YYYY-Www.json |
2 years |
| Monthly | data/monthly/YYYY-MM.json |
2 years |
| Yearly | data/yearly/YYYY.json |
forever, aggregated per day |
Retention is applied on every run by scripts/check.py (constants at the top
of the file).
python3 scripts/check.py # run checks, update data/
python3 scripts/generate.py # rebuild site/index.html
python3 scripts/check.py --config config/hosts.json --data-dir dataBoth scripts are Python stdlib only — no dependencies.
- Push this repo to GitHub. The repo must be public — GitHub Pages for private repos needs a paid plan.
- Pages: enabled once via API (
gh api -X POST repos/consolving/status/pages -f build_type=workflow); the org's GITHUB_TOKEN policy does not allow the workflow to enable it itself. - DNS:
status.consolving.de→CNAME consolving.github.io.(theCNAMEfile in this repo must containstatus.consolving.de).
- Hosts must be reachable from GitHub-hosted runners — public IPs / open health ports only, no LAN-only services.
- Scheduled workflows are delayed during GitHub load peaks and get disabled after 60 days of repo inactivity (any push resets the timer; data commits count as activity).