The fabledscryer->steward rename had only ever reached host_agent. The other five bundled plugins (http, snmp, traefik, unifi, docker) still imported `from fabledscryer.*` (package no longer exists) and read FABLEDSCRYER_* env vars — so every one of them was broken at import since the original rebrand. CI stayed green only because none are enabled by default and migrations don't import plugin modules. Now that they version in-tree, complete the rename: - fabledscryer.* -> steward.* imports across all five plugins - FABLEDSCRYER_* -> STEWARD_* in plugin migration env.py files - author/repository/homepage + user-facing 'Fabled Scryer' strings -> Steward - snmp/scheduler.py: also drop dead `now`/datetime; record_metric from steward Adds tests/test_no_legacy_names.py — fails if 'scryer'/'roundtable' ever reappear in shipped code (the drift bit twice; this stops a third time). Also clears pre-existing ruff lint debt (unused imports, semicolon statements, mid-file import) surfaced by the new lint lane. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Steward
A self-hosted network monitoring and infrastructure management hub for home servers. Steward gives you a single pane of glass over your hosts, services, and automation — with live-updating dashboards, alerting, and Ansible integration.
What It Does
- Ping monitoring — TCP/ICMP probes with live latency history and configurable thresholds
- DNS monitoring — resolution checks with optional expected-IP validation
- Ansible — browse playbooks, trigger runs, stream output live
- Alerting — threshold-based rules against any monitored metric, with email and webhook (Discord-compatible) notifications
- Plugins — extend with additional data sources; Traefik metrics included out of the box
- Dashboard widgets — all monitors and plugins contribute live-updating widgets
No JavaScript framework. No build step. No external workers or message brokers.
Quick Start — Docker
cp .env.example .env
# Set STEWARD_DATABASE_URL in .env
docker compose up -d
Open http://localhost:5000. On first run you'll be prompted to create the admin account.
Quick Start — Bare Metal
Requires Python 3.11+ and PostgreSQL.
python -m venv .venv && source .venv/bin/activate
pip install -e .
cp config.example.yaml config.yaml
# Edit config.yaml — set database.url at minimum
steward --host 0.0.0.0 --port 5000
ICMP ping requires CAP_NET_RAW or the setuid ping binary. TCP mode (the default) needs no elevated privileges.
Configuration
Only two things must be set to run the app:
| What | How |
|---|---|
| Database URL | STEWARD_DATABASE_URL env var or database.url in config.yaml |
| Secret key | Auto-generated on first run and saved to /data/secret.key |
Everything else — SMTP, webhooks, monitor intervals, Ansible sources, plugin settings — is configured through the web UI at /settings/.
Plugins
Drop a directory into plugins/ and enable it via the Settings UI. The Traefik plugin is included:
plugins/
└── traefik/ ← included; enable in Settings
See docs/plugins/ for a full plugin development guide.
Documentation
| Document | Contents |
|---|---|
docs/architecture.md |
How the app works: startup sequence, routing, scheduler, DB pattern |
docs/core/configuration.md |
Bootstrap config, DB-backed settings, all setting keys and defaults |
docs/core/monitors.md |
Ping and DNS monitors: probe logic, metrics emitted, data models |
docs/core/alerting.md |
Alert rules, state machine, notification channels, template variables |
docs/core/ansible.md |
Playbook sources, run lifecycle, SSE streaming |
docs/plugins/overview.md |
Plugin system: how loading works, plugin.yaml schema, required exports |
docs/plugins/writing-a-plugin.md |
Step-by-step plugin development guide |
docs/plugins/traefik.md |
Traefik plugin: config, metrics, alert rule examples |
docs/reference/code-map.md |
Where every key function, model, and route lives in the codebase |