v0.0.4
docker/login-action@v3 fails with 'Username and password required' on Gitea Actions — secrets not passed to action with: inputs. Switch to direct docker login CLI which reliably interpolates secrets in run: steps.
ntfy-discord
A lightweight Go bridge that forwards ntfy notifications to Discord webhooks.
Features
- SSE Subscription: Real-time message streaming from ntfy
- Auto-reconnection: Exponential backoff on connection failures
- Hot Reload: Watches mounted secrets for changes (no pod restart needed)
- Native Vault Support: Direct HashiCorp Vault integration with Kubernetes auth
- Message Transformation: Converts ntfy format to Discord embeds
- Priority Mapping: ntfy priorities → Discord embed colors
- Tag → Emoji: Converts common ntfy tags to Discord-friendly emojis
- Prometheus Metrics:
/metricsendpoint for observability - Tiny Footprint: ~10MB image, 16-32MB memory
Configuration
Core Settings
| Environment Variable | Description | Default |
|---|---|---|
NTFY_URL |
ntfy server URL | http://ntfy.observability.svc.cluster.local |
NTFY_TOPICS |
Comma-separated topics to subscribe to | (required) |
HTTP_PORT |
Port for health/metrics endpoints | 8080 |
LOG_LEVEL |
Log level (info or debug) |
info |
Secret Sources (Priority Order)
The bridge loads the Discord webhook URL from the first available source:
- Vault (if
VAULT_ENABLED=true) - Mounted Secret (if
SECRETS_PATHis set) - Environment Variable (
DISCORD_WEBHOOK_URL)
Vault Configuration
| Environment Variable | Description | Default |
|---|---|---|
VAULT_ENABLED |
Enable Vault integration | false |
VAULT_ADDR |
Vault server address | http://vault.vault.svc.cluster.local:8200 |
VAULT_AUTH_METHOD |
Auth method: kubernetes or token |
kubernetes |
VAULT_ROLE |
Vault role for Kubernetes auth | ntfy-discord |
VAULT_MOUNT_PATH |
Secrets engine mount path | secret |
VAULT_SECRET_PATH |
Path within the mount | ntfy-discord |
VAULT_TOKEN_PATH |
SA token path (for K8s auth) | /var/run/secrets/kubernetes.io/serviceaccount/token |
Expected Vault secret structure (KV v2):
secret/data/ntfy-discord
├── webhook-url: https://discord.com/api/webhooks/...
File-Based Secrets
| Environment Variable | Description | Default |
|---|---|---|
SECRETS_PATH |
Path to mounted secrets directory | (optional) |
DISCORD_WEBHOOK_URL |
Discord webhook URL (fallback) | (optional) |
When using SECRETS_PATH, the bridge expects:
webhook-url- Discord webhook URL
The bridge watches for file changes and reloads automatically.
Endpoints
| Path | Description |
|---|---|
/health |
Health check (webhook configured?) |
/ready |
Readiness check (connected to ntfy?) |
/metrics |
Prometheus metrics |
Priority → Color Mapping
| Priority | Name | Color |
|---|---|---|
| 5 | Max/Urgent | 🔴 Red |
| 4 | High | 🟠 Orange |
| 3 | Default | 🔵 Blue |
| 2 | Low | ⚪ Gray |
| 1 | Min | ⚪ Light Gray |
Building
# Build binary
go build -o ntfy-discord .
# Build container
docker build -t ntfy-discord .
Kubernetes Deployment
See homelab-k8s2 for deployment manifests.
License
MIT
Languages
Go
98.9%
Dockerfile
1.1%