# 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 ```bash 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. This compose file builds the image locally and bind-mounts the source for live editing. To run a persistent instance off the published CI image instead, see **Remote dev instance** below. --- ## Remote dev instance For a long-lived instance on a remote server that tracks the `dev` CI line, use `compose.deploy.yml`. It pulls the published image (`git.fabledsword.com/bvandeusen/steward:dev`) rather than building, runs no source bind-mounts, and persists data in named volumes. **One-time prerequisite — registry push token (on the Git host).** CI publishes the image, so the FabledSteward repo needs a push credential. The injected `GITHUB_TOKEN` lacks `write:package`, so create a Forgejo token scoped **`read:package` + `write:package`** and add it as the repo Actions secret **`REGISTRY_TOKEN`**. Until this exists, the `publish` CI job 401s and no `:dev` image is produced. **Standup (on the server):** ```bash # 1. Authenticate to the registry (read:package token is enough to pull) docker login git.fabledsword.com -u # 2. Configure secrets cp .env.example .env # Set POSTGRES_PASSWORD. Leave STEWARD_SECRET_KEY unset to let the app # generate + persist one on the /data volume. # 3. Pull + boot docker compose -f compose.deploy.yml up -d ``` Open `http://:5000` and create the admin account on first run. **Update to the latest dev build:** ```bash docker compose -f compose.deploy.yml pull docker compose -f compose.deploy.yml up -d ``` Every push to `dev` that goes CI-green publishes a fresh `:dev` (and an immutable `:` for rollback). To pin a specific commit, change the `image:` tag in `compose.deploy.yml` to `:`. --- ## Quick Start — Bare Metal Requires Python 3.11+ and PostgreSQL. ```bash 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 |