Discord is the default communication hub for most homelab runners. This guide covers creating a webhook and wiring it into the Homelab Backup Stack, the Homelab Monitoring Stack, or both.
Takes about 5 minutes.
Create the Webhook
- Open Discord and navigate to the server where you want notifications
- Click the gear icon next to the channel name (or right-click the channel and select Edit Channel)
- Go to Integrations > Webhooks > New Webhook
- Name it something descriptive -- "Homelab Backups" or "Server Alerts"
- Copy the webhook URL. It looks like this:
https://discord.com/api/webhooks/1234567890/abcdefghijklmnop_QRSTUVWXYZ
The two parts after /webhooks/ are your webhook ID and webhook token. You'll need both.
I recommend creating separate webhooks for backups and monitoring. Keeps the channels focused and lets you mute one without losing the other.
Configure for the Backup Stack
The backup stack uses shoutrrr for notifications. Shoutrrr's Discord URL format is different from the raw webhook URL:
discord://TOKEN@WEBHOOK_ID
Note the order: token first, then ID. This trips people up because the raw URL has them reversed.
Extract the Values
From your webhook URL:
https://discord.com/api/webhooks/1234567890/abcdefghijklmnop_QRSTUVWXYZ
^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
WEBHOOK_ID TOKEN
Your shoutrrr URL becomes:
discord://abcdefghijklmnop_QRSTUVWXYZ@1234567890
Add to .env
Edit your backup stack's .env file:
NOTIFICATION_URLS=discord://YOUR_TOKEN@YOUR_WEBHOOK_ID
NOTIFICATION_LEVEL=all
Set NOTIFICATION_LEVEL to all for success + failure notifications, or failures for failures only.
Multiple Channels
Send to multiple channels (or multiple services) by comma-separating URLs:
NOTIFICATION_URLS=discord://token1@id1,discord://token2@id2,slack://tokenA/tokenB/tokenC
Test It
./scripts/notify.sh success "Test Notification" "Discord webhook is working"
You should see a message in your Discord channel within a few seconds.
Configure for the Monitoring Stack
The monitoring stack uses Alertmanager for notifications. Alertmanager's Discord config is different from shoutrrr -- it uses the raw webhook URL directly.
Edit .env
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/abcdefghijklmnop_QRSTUVWXYZ
Edit alertmanager.yml
The monitoring stack's alertmanager/alertmanager.yml needs the Discord receiver configured. If the setup wizard already configured it, verify it looks like this:
receivers:
- name: discord
discord_configs:
- webhook_url: "${DISCORD_WEBHOOK_URL}"
title: '{{ .GroupLabels.alertname }}'
message: '{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
route:
receiver: discord
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
Restart Alertmanager after editing:
docker compose restart alertmanager
Test It
Fire a test alert through Alertmanager's API:
curl -X POST http://localhost:9093/api/v2/alerts \
-H "Content-Type: application/json" \
-d '[{
"labels": {"alertname": "TestAlert", "severity": "info"},
"annotations": {"summary": "Discord webhook test from Alertmanager"}
}]'
Both Stacks Together
If you run both the backup stack and the monitoring stack, use two webhooks in two different channels:
| Channel | Webhook | Stack | What fires |
|---|---|---|---|
| #server-backups | Backup webhook | Backup Stack (shoutrrr) | Backup success/failure, verification results |
| #server-alerts | Alerts webhook | Monitoring Stack (Alertmanager) | CPU/memory/disk alerts, container down, Proxmox alerts |
This separation means backup noise doesn't bury critical infrastructure alerts.
n8n Workflows
In n8n, use an HTTP Request node to POST JSON to the webhook URL. The embeds array in the payload controls rich formatting:
{
"embeds": [{
"title": "Digest Title",
"description": "Message body with **markdown**",
"color": 5814783,
"fields": [
{ "name": "Field", "value": "Value", "inline": true }
]
}]
}
Webhooks support color-coded embeds with fields, thumbnails, and footers. No bot account, no OAuth flow, no permissions to manage.
Troubleshooting
Notification not arriving:
- Verify the webhook URL hasn't been regenerated (Discord invalidates old URLs when you create a new webhook for the same channel)
- For shoutrrr: confirm token and ID are in the right order (
token@id, notid@token) - For Alertmanager: check logs with
docker logs nxsi-alertmanager --tail 20
Rate limiting:
- Discord allows 30 requests per minute per webhook. Daily backup notifications won't hit this. If you're running backups every few minutes during testing, you might see 429 errors -- they resolve when you back off.
Embeds look wrong:
- Shoutrrr sends plain text messages, not rich embeds. If you want formatted embeds, you'd need a custom notification script that posts directly to the Discord webhook API with embed JSON. For backup notifications, plain text works fine.
This guide applies to the Homelab Backup Stack, Homelab Monitoring Stack, and Homelab Health Dashboard. All available at nxsi.io.