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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

edwh_restic_discord-0.1.1.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

edwh_restic_discord-0.1.1-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file edwh_restic_discord-0.1.1.tar.gz.

File metadata

  • Download URL: edwh_restic_discord-0.1.1.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for edwh_restic_discord-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f57902c7091f29a1d81bc1a1e4962f403d63ddfe16fb18b5e2bb317fe7a7db8b
MD5 9d5ce36626ac623c2e5a395192cd3864
BLAKE2b-256 93bb7dadc2bafbadb38d2f84924023ccb0849aea175f84c61d157eec48a0cbe1

See more details on using hashes here.

File details

Details for the file edwh_restic_discord-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: edwh_restic_discord-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for edwh_restic_discord-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8577dab98bed3c5f2f6ca5d514e2aa7e47cbf7eae3b01f7b49f2d3a40ac52f8c
MD5 300a3962adbfc7872ed7989168712491
BLAKE2b-256 9912f3b9353711a7bceb627fbff59fda2851976a5da258b49729355450ab432a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page