DOCS · ADMIN · ALERTS

Know when it breaks.

A small shell script — qnt-alert.sh — fans out to whichever of Slack and Discord you've configured. Set the webhook URLs through a systemd drop-in, declare it as an OnFailure= handler, and a server that bounces sends you a message instead of dying quietly.

1 How alerting works

Alerting is a single shell script, deploy/qnt-alert.sh, that pushes a message out to webhooks. There's a companion systemd template unit, deploy/qnt-alert@.service, you can wire as a failure handler. No daemon, no extra moving parts.

Env-gated fan-out

The script reads webhook URLs from the environment and fans out to whichever are set. Each destination is guarded — if its variable is empty, that destination is simply skipped:

  • SLACK_WEBHOOK_URL — a Slack incoming-webhook URL.
  • DISCORD_WEBHOOK_URL — a Discord webhook URL.

Set one, set both, or set neither. With neither, the script runs but sends nothing — there's no hard dependency on either provider.

What you'll do

  • Create a webhook URL in Slack and/or Discord.
  • Hand those URLs to qnt-server via a systemd drop-in.
  • Declare OnFailure= on the unit you want watched.
  • Send a test alert to confirm the wiring.

2 Create the webhook URLs

Both providers hand you a single URL that accepts an HTTP POST. Create whichever you want, then keep the URLs for the next step. The exact dashboard click-path moves around, so follow each provider's own docs rather than a screenshot here.

Slack

Create an Incoming Webhook in your Slack workspace — under Apps → Incoming Webhooks. Pick the channel the alert should land in; Slack gives you a URL of the form https://hooks.slack.com/services/....

See Slack's own Incoming Webhooks documentation for the current setup flow.

Discord

Create a webhook in the target channel's Integrations settings. Discord gives you a URL of the form https://discord.com/api/webhooks/....

See Discord's own webhook documentation for the current setup flow.

3 Wire the env vars via a systemd drop-in

The script reads the URLs from the environment, so qnt-server (and the alert unit) need to see them. The runbook way is a systemd drop-in .conf — that keeps the URLs out of the main unit file and survives package upgrades.

Slack drop-in

Make the drop-in directory and create a .conf with the Slack URL:

mkdir -p /etc/systemd/system/qnt-server.service.d

Then put this in /etc/systemd/system/qnt-server.service.d/slack.conf:

[Service]
Environment=SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...

Discord drop-in

Same pattern for Discord — add it to the same .conf or a separate one:

[Service]
Environment=DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...

Reload and restart

Pick up the drop-in and restart so qnt-server sees the new environment:

systemctl daemon-reload
systemctl restart qnt-server

4 Fire on crash

Setting the env vars doesn't send anything on its own — you still need something to invoke the alert. The mechanism that turns "server bounced" into a notification is systemd's OnFailure=.

Declare the handler on the watched unit

deploy/qnt-alert@.service is a template unit. The watched unit declares it as an OnFailure= handler in its [Unit] section — the %n passes the failing unit's name through to the template:

[Unit]
OnFailure=qnt-alert@%n.service

When the watched unit enters a failed state, systemd starts qnt-alert@<unit>.service, which runs the script and fans out to whichever webhooks you wired in step 3.

5 Test it

Don't wait for a real crash to find out a URL was pasted wrong. The script has a test mode that sends an alert immediately.

Send a test alert

qnt-alert.sh test-unit

You should see the message land in every channel you configured. If a destination stays silent, re-check that its Environment= line is present in the drop-in and that you ran systemctl daemon-reload.

Honest about scope

This is webhook-push alerting — good enough for a single-operator setup that mostly wants to know when a unit fell over. It does not do metric-threshold alerting (an error-rate spike, say). For that you'd pair it with Prometheus Alertmanager, which is not pre-wired here. The monitoring page covers the metrics surface to build that on.

Next

Alerts wired and tested. Round out the operational guides.