Notifications

dvb-WarpPool can notify the operator over several independent channels when relevant pool events occur — most importantly block found. Configuration lives in config.toml under [notifier]; secrets (API tokens, webhook URLs, SMTP passwords) are always referenced via env var, never inline.

Currently active (Phase 15):

SinkProtocolConfig keySecret via env
ntfyHTTP POST[notifier.ntfy](none — public topic URL suffices)
TelegramBot API[notifier.telegram]bot_token_env
DiscordWebhook[notifier.discord]webhook_url_env
SlackIncoming Webhook[notifier.slack]webhook_url_env
EmailSMTP via lettre/TLS[notifier.email]password_env (optional)

Events

The daemon emits five event types:

EventWhenPriority
block-foundAfter a successful submitblock in the daemonhigh
miner-disconnectAn authenticated worker closes the Stratum connection; per-worker debounce 30smedium
rpc-downHealth check first hits RPC=failmedium
rpc-recoveredHealth check first hits RPC=ok again after a down statelow
testOperator clicks the test button in the admin UIlow

Each sink can toggle which events it cares about (on_block_found, on_miner_disconnect, on_rpc_down — all bool). The default everywhere is on_block_found = true, others off; for Slack/Email all three are toggleable.

Retry: 3 attempts with exponential backoff (2s / 10s / 30s). If everything fails, it gets logged but the daemon keeps running — a notifier failure must never disrupt mining.

ntfy.sh

Simple and account-free. A single topic URL is enough.

[notifier.ntfy]
topic_url = "https://ntfy.sh/my-secret-pool-topic-abc123"
on_block_found = true
on_miner_disconnect = false
on_rpc_down = true

On your phone, install the ntfy app, subscribe to the same topic name, done. Topic names are effectively a shared secret — choose a hard-to-guess string.

For self-hosted ntfy, just use topic_url = "https://ntfy.your-domain.com/topic".

Telegram

Create a bot via @BotFather → note the token. You get a chat_id by sending the bot a message and then fetching https://api.telegram.org/bot<TOKEN>/getUpdates (look for "chat":{"id":…}).

[notifier.telegram]
bot_token_env = "TELEGRAM_BOT_TOKEN"
chat_id = "123456789"
on_block_found = true

Then in the daemon environment:

TELEGRAM_BOT_TOKEN="123:abc..." dvb-warppool-daemon

With systemd: Environment="TELEGRAM_BOT_TOKEN=…" in the unit file, or better an EnvironmentFile=/etc/default/dvb-warppool with chmod 600.

Discord

In the server settings under Integrations → Webhooks, create a new webhook and copy the URL. The URL is effectively the auth token — anyone who has it can post.

[notifier.discord]
webhook_url_env = "DISCORD_WEBHOOK_URL"
on_block_found = true
DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/…" dvb-warppool-daemon

Slack

Create a Slack app in your workspace → enable Incoming Webhooks → generate a webhook for a channel. The payload uses Block Kit (header + section with mrkdwn) for clean layout.

[notifier.slack]
webhook_url_env = "SLACK_WEBHOOK_URL"
on_block_found = true
on_miner_disconnect = false
on_rpc_down = true

Email (SMTP)

lettre-based, with rustls — no openssl-sys. Two URL schemes:

  • smtps://user@host:465 — implicit TLS (common with providers like Posteo, Migadu, Fastmail, Hetzner)
  • smtp://user@host:587 — STARTTLS (gmail, many mail servers)
[notifier.email]
smtp_url = "smtps://pool@mail.example.com:465"
from = "pool@example.com"
to = ["operator@example.com", "monitoring@example.com"]
password_env = "POOL_SMTP_PASSWORD"
on_block_found = true
on_miner_disconnect = false
on_rpc_down = true
POOL_SMTP_PASSWORD="…" dvb-warppool-daemon

password_env is optional — if omitted, no SMTP AUTH is attempted (useful for a local MTA like Postfix on localhost:25 that relays internally).

With multiple recipients, each one gets their own letter — also a simple way to notify the whole team at once.

Test workflow

After configuration:

  1. Restart the daemon — logs show notifier sink ready for each working sink. If an env var is missing or a required config field is empty, you'll see notifier sink skipped with a reason; the daemon starts anyway.
  2. In the admin UI under /admin/notifications → "Server-Side Sinks (Daemon)" lists all active sinks.
  3. Per sink, a Test button → POST /api/admin/notifier/test?sink=<name> fires a test event at just that one. The badge switches to ok/err.
  4. Test all sinks button → POST /api/admin/notifier/test with no param.

The same via CLI:

curl -X POST \
  -H "Authorization: Bearer wpat_…" \
  http://pool.local:18334/api/admin/notifier/test?sink=ntfy

Web Push (PWA, VAPID — Phase 21)

In addition to the 5 server-side sinks above, there's background push straight to your phone via VAPID Web Push. Works even when the PWA is closed (iOS 16.4+, Android, desktop). No 3rd-party service required — push goes directly from the pool daemon to the browser push service (FCM/Mozilla/Apple).

Operator setup

# 1. Generate VAPID keys
dvb-warppool-cli gen-vapid-keys >> /etc/dvb-warppool/secrets.toml

# 2. Optional: set contact mailto (otherwise defaults to mailto:operator@localhost)
echo 'vapid_contact = "mailto:operator@example.org"' >> /etc/dvb-warppool/secrets.toml

# 3. Restart the daemon
systemctl restart dvb-warppool

Daemon log shows web-push sender ready. If not: VAPID keys weren't found in secrets.toml — push stays disabled, other notifiers run anyway.

User subscribe flow

  1. Open the pool UI, log in
  2. Go to /admin/notifications"Enable background push" button
  3. Browser asks for permission → "Allow"
  4. Subscription is registered with the pool, from now on pushes arrive

Which events fire push

EventTagWhen
block-foundblock-foundEvery block found (requireInteraction=true → notification stays until the user acknowledges it)
healthhealthRPC down OR health snapshot with warnings
updateupdatePool update available (Phase 8e SSE event)

Other events (SharesAccepted tick, NewJob, etc.) do NOT fire push — too spammy for background notifications.

iOS quirks

  • Required: add the PWA to the home screen (Safari share menu → "Add to Home Screen"). In a regular Safari tab, iOS ignores Web Push.
  • iOS 16.4+ is the minimum version (March 2023). On older iOS versions the UI shows a Browser unsupported badge.

Security note

The VAPID private key is sensitive — anyone holding it can impersonate your pool to the push services. secrets.toml chmod 600. On suspected leak: generate new keys + invalidate all subscriptions (a restart is enough — stale subscriptions get deleted on the first 401 response).

Other Phase B options

  • Matrix — not implemented; PR welcome, analogous to the Slack sink pattern.
  • PagerDuty / Opsgenie — same; a generic webhook sink with HMAC signing would solve this without vendor lock-in.

See also