An open API service indexing awesome lists of open source software.

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

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
```