# ntfy-discord A lightweight Go bridge that forwards [ntfy](https://ntfy.sh/) 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**: `/metrics` endpoint 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: 1. **Vault** (if `VAULT_ENABLED=true`) 2. **Mounted Secret** (if `SECRETS_PATH` is set) 3. **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 ```bash # Build binary go build -o ntfy-discord . # Build container docker build -t ntfy-discord . ``` ## Kubernetes Deployment See [homelab-k8s2](https://github.com/Billy-Davies-2/homelab-k8s2) for deployment manifests. ## License MIT