Secure Webhook Relay
Built with Rust

SSE-based webhook relay server with signature validation, encryption support, and HTTP forwarding capabilities. Perfect for receiving webhooks on clients behind NAT/firewall.

How It Works

Simple yet powerful webhook relay architecture

GitHub Webhook Sender Server mode=server ✓ Signature validation ✓ SSE broadcasting ✓ Encryption Client mode=client ✓ SSE connection ✓ Decryption ✓ HTTP forwarding 🔒 BEHIND NAT/FIREWALL Your API Private Endpoint forward=<URL> 🔒 BEHIND NAT/FIREWALL No public IP needed POST /channel X-Hub-Signature SSE Stream event: webhook POST forward Decrypted payload 1️⃣ Webhook arrives 2️⃣ Broadcast SSE 3️⃣ Forward to API Both client and API can be behind NAT/firewall - webhooks flow via outbound SSE, no port forwarding needed

Why Webhook Relay?

Built for security, performance, and ease of deployment

🔒

Secure by Default

HMAC signature validation for GitHub, GitLab, and LINE webhooks. Optional RSA encryption for sensitive payloads.

Built with Rust

High-performance webhook relay server leveraging Rust's safety and concurrency guarantees.

📡

SSE Broadcasting

Real-time webhook delivery via Server-Sent Events with automatic channel management and cleanup.

🔄

Works Behind NAT

Client uses outbound SSE connections, allowing webhook delivery to services behind NAT/firewall without port forwarding or VPN.

🎯

Channel Isolation

Multiple isolated channels with independent secrets and encryption keys for multi-tenant deployments.

☁️

Juju Integration

Deploy with a single command using Juju charm. Production-ready with systemd integration.

Deployment Modes

Flexible architecture for any use case

SERVER MODE

Webhook Relay Server

Accept webhooks via HTTP POST and broadcast to SSE clients

  • HMAC signature validation
  • Multiple channel support (up to 10)
  • Optional RSA encryption per channel
  • Automatic channel cleanup
  • Configurable ping intervals
# Standalone deployment
PORT=3000 HOST=0.0.0.0 webhook-relay

# Juju deployment
juju deploy webhook-relay webhook-server \
  --config mode=server \
  --config port=3000 \
  --config channel0="$(uuidgen | sha1sum | awk '{print $1}')" \
  --config secret0="your-webhook-secret" \
  --config key0="$(cat public_key.pem)"
CLIENT MODE

Relay Client (relayd)

Connect to server and forward webhooks to HTTP endpoints behind NAT/firewall

  • Works behind NAT (outbound SSE only)
  • No port forwarding required
  • RSA payload decryption
  • HTTP POST forwarding
  • Automatic reconnection
  • Ping event filtering
# Standalone: Forward to HTTP endpoint
relayd "http://server:3000/channel" \
  private_key.pem \
  "http://api.example.com/webhook"

# Or use /dev/null if server doesn't encrypt
relayd "http://server:3000/channel" \
  /dev/null \
  "http://api.example.com/webhook"

# Juju: Deploy client with forwarding
juju deploy webhook-relay relayd \
  --config mode=client \
  --config url="http://webhook-server:3000/<channel>" \
  --config key="$(cat private_key.pem)" \
  --config forward="http://api.example.com/webhook"