···
3
-
*100% vibe coded, use at your peril*
5
-
A webhook service that receives notifications from Netdata Cloud and forwards them to Zulip channels. Features HTTPS with Let's Encrypt certificates and mutual TLS authentication for secure communication with Netdata Cloud.
3
+
A production-ready webhook service that receives notifications from Netdata Cloud and forwards them to Zulip channels. Designed to run behind a reverse proxy (like Caddy) that handles HTTPS and mutual TLS authentication.
9
-
- 🔐 **Automated SSL Certificates**: Built-in Let's Encrypt integration with automatic renewal
10
-
- 🤝 **Mutual TLS**: Secure authentication with Netdata Cloud
7
+
- 🔗 **Reverse Proxy Ready**: HTTP service designed to run behind Caddy/nginx
8
+
- 🤝 **Mutual TLS Support**: When configured with reverse proxy
- 📊 **Rich Formatting**: Beautiful Zulip messages with emojis and markdown
- 🏷️ **Topic Organization**: Automatic topic routing by severity level
- 📝 **Structured Logging**: JSON-structured logs for monitoring
- ⚡ **High Performance**: FastAPI-based webhook endpoint
15
-
- 🚀 **Standalone**: No external dependencies like certbot required
13
+
- 🔧 **Flexible Configuration**: Support for .zuliprc files or environment variables
14
+
- ✅ **Webhook Verification**: Built-in Netdata challenge/response handling
···
### 2. Create Configuration
# Generate sample configuration files
33
-
netdata-zulip-bot --create-config
29
+
uv run netdata-zulip-bot --create-config
cp .zuliprc.sample ~/.zuliprc
### 3. Configure Zulip Settings
···
51
-
### 4. Set Server Environment Variables
48
+
### 4. Configure Environment Variables
50
+
Edit `.env` file or set environment variables:
54
-
export SERVER_DOMAIN=your-webhook-domain.com
55
-
export SERVER_PORT=8443
56
-
export SERVER_ENABLE_MTLS=true
53
+
# Server configuration (HTTP only)
54
+
export SERVER_HOST=0.0.0.0
55
+
export SERVER_PORT=8080
58
-
# For automated SSL certificates (recommended)
59
-
export SERVER_AUTO_CERT=true
60
-
export SERVER_CERT_EMAIL=admin@example.com
61
-
# Use staging for testing (optional)
62
-
export SERVER_CERT_STAGING=false
57
+
# Required: Netdata webhook challenge secret
58
+
export SERVER_CHALLENGE_SECRET=your-challenge-secret-here
60
+
# Optional: Override Zulip stream
61
+
export ZULIP_STREAM=netdata-alerts
68
-
# With automated SSL certificates
67
+
# Start the HTTP service
68
+
uv run netdata-zulip-bot
71
-
# The bot will automatically:
72
-
# 1. Obtain SSL certificates from Let's Encrypt
73
-
# 2. Start the HTTPS server
74
-
# 3. Renew certificates before expiration
70
+
# Or with custom configuration
71
+
uv run netdata-zulip-bot --zuliprc /path/to/.zuliprc
73
+
# The service runs on HTTP (default: localhost:8080)
74
+
# Use a reverse proxy like Caddy for HTTPS and mutual TLS
···
export ZULIP_STREAM=netdata-alerts
104
-
Use `--env-config` flag to use environment variables instead of zuliprc.
104
+
Use the `--env-config` flag to use environment variables instead of zuliprc:
107
+
uv run netdata-zulip-bot --env-config
Set these environment variables:
110
-
- `SERVER_DOMAIN`: Your public domain (required)
- `SERVER_HOST`: Bind address (default: `0.0.0.0`)
112
-
- `SERVER_PORT`: HTTPS port (default: `8443`)
113
-
- `SERVER_ENABLE_MTLS`: Enable mutual TLS (default: `true`)
115
+
- `SERVER_PORT`: HTTP port (default: `8080`)
116
+
- `SERVER_CHALLENGE_SECRET`: Netdata webhook challenge secret (required)
115
-
#### Automated SSL Configuration (Recommended)
118
+
### Reverse Proxy Setup
117
-
- `SERVER_AUTO_CERT`: Enable automatic certificate management (default: `false`)
118
-
- `SERVER_CERT_EMAIL`: Email for Let's Encrypt account (required when auto_cert is true)
119
-
- `SERVER_CERT_PATH`: Directory for storing certificates (default: `./certs`)
120
-
- `SERVER_CERT_STAGING`: Use Let's Encrypt staging server for testing (default: `false`)
121
-
- `SERVER_ACME_PORT`: Port for ACME HTTP-01 challenge (default: `80`)
120
+
The bot is designed to run behind a reverse proxy that handles HTTPS and mutual TLS:
123
-
#### Manual SSL Configuration
122
+
#### Using Caddy (Recommended)
125
-
If not using automated certificates:
126
-
- `SERVER_CERT_PATH`: Path to certificate directory
127
-
- Place `fullchain.pem` and `privkey.pem` in `{SERVER_CERT_PATH}/{SERVER_DOMAIN}/`
124
+
1. Update `Caddyfile` with your domain name
125
+
2. Place Netdata CA certificate in `netdata-ca.pem`
126
+
3. Run both services:
130
+
uv run netdata-zulip-bot &
133
+
caddy run --config Caddyfile
136
+
#### Using Docker Compose
139
+
docker-compose up -d
···
**Time:** 2024-01-15 14:30:00 UTC
**Details:** CPU usage has exceeded 90% for 5 minutes
**Summary:** Critical alert: High CPU usage detected
[View Alert](https://app.netdata.cloud/spaces/...)
···
174
-
Create `/etc/systemd/system/netdata-zulip-bot.service`:
188
+
See `examples/netdata-zulip-bot.service` for a complete systemd service configuration.
178
-
Description=Netdata Zulip Bot
179
-
After=network.target
190
+
### Automated Setup
184
-
WorkingDirectory=/opt/netdata-zulip-bot
185
-
Environment=SERVER_DOMAIN=your-domain.com
186
-
ExecStart=/opt/netdata-zulip-bot/venv/bin/netdata-zulip-bot
192
+
Use the provided setup script:
191
-
WantedBy=multi-user.target
196
-
sudo systemctl enable netdata-zulip-bot
197
-
sudo systemctl start netdata-zulip-bot
195
+
sudo ./scripts/setup.sh --domain your-domain.com --email admin@example.com
203
-
FROM python:3.11-slim
200
+
The included `Dockerfile` and `docker-compose.yml` provide a complete setup with Caddy reverse proxy:
207
-
RUN pip install -e .
211
-
CMD ["netdata-zulip-bot"]
203
+
docker-compose up -d
216
-
### SSL Certificate Management
218
-
The bot includes fully automated SSL certificate management:
210
+
The bot uses a security-focused architecture:
220
-
1. **Automatic Provisioning**: Obtains certificates from Let's Encrypt on first run
221
-
2. **Automatic Renewal**: Checks daily and renews certificates 30 days before expiration
222
-
3. **Zero Downtime**: Certificate renewal happens in the background
223
-
4. **ACME HTTP-01 Challenge**: Built-in challenge server (requires port 80 access)
212
+
1. **HTTP Backend**: Simple HTTP service with no direct internet exposure
213
+
2. **Reverse Proxy**: Caddy handles HTTPS, certificates, and client authentication
214
+
3. **Mutual TLS**: Client certificate validation at the reverse proxy level
225
-
### Mutual TLS Authentication
216
+
### Webhook Security
227
-
The service supports mutual TLS to authenticate Netdata Cloud webhooks:
218
+
- **Challenge/Response**: Built-in Netdata webhook verification using HMAC-SHA256
219
+
- **Payload Validation**: Strict payload parsing and validation
220
+
- **Request Logging**: Comprehensive logging of all webhook requests
221
+
- **Error Handling**: Secure error responses without information disclosure
229
-
1. **Server Certificate**: Automatically managed via built-in ACME client
230
-
2. **Client Verification**: Validates Netdata's client certificate
231
-
3. **CA Certificate**: Built-in Netdata CA certificate for client validation
223
+
### SSL Certificate Management
233
-
### Webhook Endpoint Security
225
+
SSL certificates are managed by the reverse proxy (Caddy):
235
-
- HTTPS-only communication
236
-
- Request logging and monitoring
237
-
- Payload validation and sanitization
238
-
- Error handling without information disclosure
227
+
1. **Automatic Provisioning**: Caddy obtains Let's Encrypt certificates
228
+
2. **Automatic Renewal**: Built-in certificate renewal
229
+
3. **Mutual TLS**: Client certificate validation using Netdata CA certificate
···
258
-
curl -k https://your-domain.com:8443/health
249
+
# Direct HTTP check (backend service)
250
+
curl http://localhost:8080/health
252
+
# Through reverse proxy
253
+
curl https://your-domain.com/health
···
269
+
uv run python -m pytest tests/ -v
276
+
uv run ruff check .
286
-
For development, you can disable HTTPS and mTLS:
281
+
For development, you can run the HTTP service directly:
289
-
export SERVER_ENABLE_MTLS=false
290
-
# Use HTTP for testing (not recommended for production)
284
+
# Set required environment variables
285
+
export SERVER_CHALLENGE_SECRET=test-secret
288
+
uv run netdata-zulip-bot
290
+
# Test webhook endpoint
291
+
curl -X POST http://localhost:8080/webhook/netdata?crc_token=test123
297
-
1. **Certificate Issues**
298
-
- For automated certs: Ensure port 80 is accessible for ACME challenges
299
-
- Domain must point to your server's IP address
300
-
- Check `SERVER_CERT_EMAIL` is set for auto-cert mode
301
-
- Use `SERVER_CERT_STAGING=true` for testing to avoid rate limits
298
+
1. **Configuration Issues**
299
+
- Ensure `SERVER_CHALLENGE_SECRET` is set (required for Netdata webhook verification)
300
+
- Verify `.zuliprc` file contains all required fields
301
+
- Check that Zulip bot has permission to post to the configured stream
303
-
2. **Zulip Connection Failed**
304
-
- Verify API credentials in zuliprc
305
-
- Test connection with Zulip's API
303
+
2. **Reverse Proxy Issues**
304
+
- Ensure Caddy configuration uses correct domain name
305
+
- Verify Netdata CA certificate is properly configured
306
+
- Check that port 80 is accessible for Let's Encrypt challenges
3. **Webhook Not Receiving Data**
308
-
- Check firewall settings for port 8443
309
-
- Verify domain DNS resolution
310
-
- Check Netdata Cloud webhook configuration
309
+
- Verify Netdata Cloud webhook URL points to your reverse proxy
310
+
- Check webhook challenge secret matches configuration
311
+
- Review service logs for error messages
···
321
-
MIT License - see LICENSE file for details.
322
+
MIT License - see LICENSE file for details.