https://github.com/jaiwargacki/alertbot
Configurable, YAML-driven Discord bot that monitors services, files, and more — and alerts you on Discord
https://github.com/jaiwargacki/alertbot
alerting discord-bot self-hosted yaml
Last synced: 14 days ago
JSON representation
Configurable, YAML-driven Discord bot that monitors services, files, and more — and alerts you on Discord
- Host: GitHub
- URL: https://github.com/jaiwargacki/alertbot
- Owner: jaiwargacki
- Created: 2026-06-06T02:07:21.000Z (20 days ago)
- Default Branch: main
- Last Pushed: 2026-06-06T18:06:18.000Z (19 days ago)
- Last Synced: 2026-06-06T18:16:08.871Z (19 days ago)
- Topics: alerting, discord-bot, self-hosted, yaml
- Language: Python
- Homepage:
- Size: 81.1 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# AlertBot
## Requirements
- [uv](https://docs.astral.sh/uv/getting-started/installation/) — used for dependency management and running the bot
**Windows:**
```powershell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
**Linux/macOS:**
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
## Setup
Install dependencies:
```bash
uv sync
```
Then point AlertBot at a config directory (see **Configuration** below). The
service reads its Discord token and root user from `alertbot.yaml` /
`secrets.env` — not a `.env` file.
## Running
```bash
uv run src/bot.py
```
`bot.py` loads the configuration, builds the monitors, and runs the engine: it
polls each monitor on its schedule and posts alerts (with ack/snooze/mute
buttons) to the Discord channels named by `notify:`, DMing the root user for
`critical`. Monitor state persists to the SQLite store, so `alertbot list` /
`alertbot status` reflect what the running service sees.
While it runs, the root user can open the **`/monitors` control panel** in a DM
to enable/disable monitors at runtime — individually or by group (a group is one
`monitors.d/*.yaml` file) — straight from a phone, no YAML edit or shell access.
Toggles persist across config reloads and restarts; a disabled monitor stops
being polled on the next cycle. Set `dm_control: false` on a monitor to keep it
out of the panel's reach.
Config and store locations are resolved the same way the CLI resolves them, so
the service and `alertbot` agree:
| Variable | Default | Purpose |
|---|---|---|
| `ALERTBOT_CONFIG_DIR` | `/etc/alertbot` | directory holding `alertbot.yaml`, `secrets.env`, `monitors.d/` |
| `ALERTBOT_STORE` | `/var/lib/alertbot/alertbot.db` | SQLite state store |
| `ALERTBOT_PID_FILE` | `/run/alertbot/alertbot.pid` | PID file (lets `alertbot status` report "running") |
| `ALERTBOT_READY_FILE` | `/run/alertbot/ready` | readiness marker, stamped once Discord connects — the health signal `deploy/update.sh` polls |
On the Windows dev box, point these at local paths, e.g.:
```powershell
$env:ALERTBOT_CONFIG_DIR = "examples\alertbot"
$env:ALERTBOT_STORE = "$env:LOCALAPPDATA\AlertBot\alertbot.db"
uv run src/bot.py
```
The service fails fast — invalid config, a missing token, or a bad `schedule:`
exits with a clear `file:line` error before it connects — and shuts down
cleanly on SIGINT/SIGTERM (and Windows Ctrl-C), draining in-flight checks first.
Config changes hot-reload without a restart: `alertbot reload` (or
`systemctl reload` / SIGHUP on Linux) re-validates and swaps the monitor set in
place — a bad config is rejected and the running config keeps serving.
## Deployment (Ubuntu / systemd)
For a production box, run AlertBot as a long-lived systemd service — auto-restart,
start on boot, config-validate on start, hot-reload on `systemctl reload`, and
logs to the journal. Everything you need is in [`deploy/`](deploy):
```bash
git clone https://github.com/jaiwargacki/AlertBot.git
cd AlertBot
sudo ./deploy/install.sh # sets up the service user, /etc/alertbot, the venv, the unit
# then fill in /etc/alertbot/secrets.env + alertbot.yaml and:
sudo systemctl start alertbot
journalctl -u alertbot -f
```
Updating is operator-run and safety-checked: `deploy/update.sh` fast-forwards the
source checkout, runs the tests, redeploys, restarts, health-checks via the
readiness marker, and **rolls back automatically** if the new version doesn't come
up healthy. An opt-in staleness monitor (`deploy/alertbot-self-stale.yaml` +
`check-update.sh`) nudges you in Discord when the deployed bot falls behind
`origin/main`.
See [`deploy/README.md`](deploy/README.md) for the full walkthrough (manual steps,
secrets permissions, journald logging, reload/restart, reboot recovery, updating,
the staleness monitor, and uninstall).
## Configuration (monitors)
AlertBot is driven by YAML config, not code changes. A config directory holds:
```
alertbot/
├── alertbot.yaml # global: Discord token ref, channel IDs, defaults
├── secrets.env # ${VAR} values, chmod 600, never committed
└── monitors.d/ # drop-in directory — one concern per file
├── 10-incoming-image.yaml # directory watch: post each new image to a channel
└── 20-backup-script.yaml # command: run a script, alert on failure + recovery
```
See [`examples/alertbot/`](examples/alertbot) for a working template with exactly
this layout.
- **Drop-in:** add a watch by dropping a `*.yaml` file in `monitors.d/`. Numeric
prefixes control load order.
- **Disable:** rename a file to `*.yaml.off`, or set `enabled: false` on a monitor.
At runtime, the root user can also toggle monitors (or whole files' worth) from
the `/monitors` panel in Discord — see **Running** above.
- **Secrets:** config references secrets as `${DISCORD_BOT_TOKEN}`, resolved from
`secrets.env` (or the environment). Config is safe to commit; secrets are not.
- **Validation:** the loader reports every problem with a `file:line` location and
an "did you mean" hint for misspelled fields, and never crashes on bad input.
## CLI (`alertbot`)
`uv sync` installs an `alertbot` command that reads the same config and store
the service does, so you can build confidence in a config before and while the
service runs. It resolves paths via the same flags / `ALERTBOT_*` env vars.
```bash
uv run alertbot validate # parse + schema-check every file and monitor; non-zero exit on error
uv run alertbot list # table of configured monitors (type, schedule, severity) + current state
uv run alertbot status # whether the service is running (PID file) + last state/event per monitor
uv run alertbot reload # signal the running service to re-validate and hot-swap its config
uv run alertbot test # fire one monitor now and preview the exact embed (--send to deliver)
uv run alertbot send "msg" # deliver an ad-hoc alert to confirm the pipe end to end (--preview to dry-run)
```
`validate` catches a bad config before it ever applies. `list` and `status` are
read-only — a missing store simply reports unknown state, never creating it —
and show monitors disabled from the `/monitors` panel as `disabled` (distinct
from config-disabled monitors, which aren't loaded at all).
## Tests
```bash
uv run pytest
```