Skip to main content

edwh-restic-discord

Discord webhook notifications for edwh-restic-plugin: a failed backup reaches your Discord server instead of dying in a cron log.

Core emits an event per restic operation and ships no notifiers itself. This package is one: it registers a channel called discord, and does nothing at all until [restic.notify] channels names it.

Installation

(uv) pip install edwh-restic-discord

Installed beside edwh-restic-plugin, it is discovered through its entry point; no import or module list is needed.

Quick start

.env (gitignored, secrets only):

DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/token_value

.toml (or default.toml, the committed template):

[restic.notify]
channels = ["discord"]

Then check it works without waiting for a real failure:

edwh restic.notify-test
edwh restic.notify-test --all-events

A webhook url is what activates the channel: named in channels but without one, it is skipped with a note and your backups run on.

Routing: one webhook, or one per anything

The .env url above is the default for every event. The general form is a table whose keys say which events go where:

[restic.notify.discord]

[restic.notify.discord.urls]
"*" = "https://discord.com/api/webhooks/1/all"          # everything
"backup" = "https://discord.com/api/webhooks/2/backups" # one operation
"warning" = "https://discord.com/api/webhooks/3/noisy"  # one level
"failed" = "https://discord.com/api/webhooks/4/oncall"  # one phase
"check.failed" = "https://discord.com/api/webhooks/5/damage"

Five kinds of key, freely mixed:

Key Means Matches
"*" everything any event
"backup", "backup.*" one operation backup.started, backup.failed, …
"failed", "*.failed" one phase, across operations backup.failed, check.failed, …
"error", "warning", "info" one level whatever core gives that level
"check.failed" one exact event only that one

Operations are backup, restore, check, forget, wipe; phases are started, succeeded, failed, slow.

The most specific key wins, and exactly one webhook set is chosen per event. A list value is how you deliberately fan out:

[restic.notify.discord.urls]
"failed" = [
    "https://discord.com/api/webhooks/4/oncall",
    "https://discord.com/api/webhooks/6/audit",
]

webhook and webhooks are accepted aliases for url and urls. Values must be complete https:// webhook urls; there is no Discord equivalent of a bare-topic plus server form.

Mentions by friendly name

Discord pings by numeric id, so [restic.notify.discord.users] and [restic.notify.discord.roles] map names you choose to the ids from Discord:

[restic.notify.discord]
webhook = "https://discord.com/api/webhooks/1/all"

[restic.notify.discord.roles]
oncall = "123456789012345678"

[restic.notify.discord.users]
robin = "234567890123456789"

[restic.notify.discord.mentions]
"failed" = ["oncall"]
"backup.failed" = ["oncall", "robin"]

The mention table uses the same keys and precedence as webhooks. Values can be mapped names, or raw Discord mentions such as <@id>, <@&id>, @everyone and @here. A matched route adds one short content line to the message and allows those mention types to ping.

What a notification looks like

Each event becomes a Discord embed:

  • Title: ⏳ backup.failed - acme-prod@db-01 (phase picks the emoji)
  • Description: a one-line headline, plus restic logs on failures
  • Fields: repository, host, project, target, failed scripts, and other event details
  • Color: info is blue, warning is orange, error is red

All options

Under [restic.notify.discord]:

Key Default Meaning
url, webhook — shorthand for the "*" route
urls, webhooks — the route table (or a bare value, same as url)
logs true include restic's stdout/stderr on failures
timeout 4.0 seconds per request
max_chars 3900 character budget for the embed description
username — webhook display-name override
avatar_url — webhook avatar override
users — map of friendly name to Discord user id
roles — map of friendly name to Discord role id
mention, mentions — mention route table

Environment:

Key Meaning
DISCORD_WEBHOOK_URL default webhook when TOML has no url route

events and min_level are read by core, not by this plugin, and still apply:

[restic.notify.discord]
webhook = "https://discord.com/api/webhooks/1/all"
min_level = "warning"      # core drops info events before routing ever sees them

You rarely need events: this plugin narrows core's subscription to what its own table can deliver, so restic.notify-test reports an event with no matching route as filtered rather than as a silent success. An event that reaches us with no route sends nothing and says so once per event name.

A worked setup

[restic.notify]
channels = ["discord"]
project = "acme-prod-db01"

[restic.notify.discord]
logs = true
username = "restic"

[restic.notify.discord.urls]
"*" = "https://discord.com/api/webhooks/1/timeline"
"failed" = "https://discord.com/api/webhooks/2/oncall"
"check.failed" = "https://discord.com/api/webhooks/3/urgent"
"backup.slow" = "https://discord.com/api/webhooks/1/timeline"

[restic.notify.discord.roles]
oncall = "123456789012345678"

[restic.notify.discord.mentions]
"check.failed" = ["oncall"]

Security note

A notifier runs in-process and is trusted like any other dependency. Events carry an allowlist of fields and never the repository URI, but logs on a failure event is restic's full stdout/stderr, which can include repository paths and hostnames. A Discord webhook url is also a secret: anyone who has it can post to that channel. Keep it in .env, point failure routes only at channels you trust, and set logs = false when the full terminal output should stay off Discord.

Development

uv pip install -e .[dev]
edwh test.run
edwh plugin.release # to publish a new version with vommit

License

edwh-restic-discord is distributed under the terms of the MIT license.

Metadata

Release files for edwh-restic-discord 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for edwh-restic-discord 0.1.1
File Size Uploaded
edwh_restic_discord-0.1.1.tar.gz 11.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for edwh-restic-discord 0.1.1
File Interpreter ABI Platform
edwh_restic_discord-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 24.0 kB

Release files / edwh_restic_discord-0.1.1.tar.gz

Download URL edwh_restic_discord-0.1.1.tar.gz
Size 11.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f57902c7091f29a1d81bc1a1e4962f403d63ddfe16fb18b5e2bb317fe7a7db8b
BLAKE2b-256 checksum
How to use checksums
93bb7dadc2bafbadb38d2f84924023ccb0849aea175f84c61d157eec48a0cbe1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / edwh_restic_discord-0.1.1-py3-none-any.whl

Download URL edwh_restic_discord-0.1.1-py3-none-any.whl
Size 12.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8577dab98bed3c5f2f6ca5d514e2aa7e47cbf7eae3b01f7b49f2d3a40ac52f8c
BLAKE2b-256 checksum
How to use checksums
9912f3b9353711a7bceb627fbff59fda2851976a5da258b49729355450ab432a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.3","id":"zena","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page