Reverse Proxy Setup
How to configure a reverse proxy (Nginx, Caddy, Apache, Traefik) for Wiretastix with TLS.
Running Wiretastix behind a reverse proxy is the recommended production deployment pattern. A reverse proxy provides TLS termination, load balancing capabilities, enhanced security, and centralized certificate management.
Why Use a Reverse Proxy?
Essential Benefits
TLS/HTTPS Termination
- OIDC providers require HTTPS for authentication callbacks
- Protects sensitive data in transit (credentials, API tokens)
- Modern browsers require HTTPS for many features
- Centralized certificate management
Security
- Hide internal service details
- Additional firewall layer
- Rate limiting and DDoS protection
- Request filtering and validation
Operational Flexibility
- Easy certificate renewal (Let’s Encrypt)
- Load balancing for high availability
- Centralized logging and monitoring
- Zero-downtime updates
Additional Features
- Custom headers and CORS handling
- Compression (gzip, brotli)
- Caching for static assets
- URL rewriting and redirects
Architecture Overview
Client (Browser/CLI)
↓ HTTPS (443)
Reverse Proxy (Nginx/Caddy/Apache/Traefik)
↓ HTTP (8085) - internal network
Wiretastix Web UI
Client (WireGuard)
↓ UDP (51820) - direct
Wiretastix Daemon
Important: Only HTTP/HTTPS traffic goes through the proxy. WireGuard VPN traffic (UDP port 51820) goes directly to Wiretastix.
Prerequisites
Before configuring a reverse proxy:
- Domain Name: A domain pointing to your server (e.g.,
vpn.example.com) - DNS Configuration: A record pointing to your server’s public IP
- Firewall: Ports 80 and 443 open for the reverse proxy
- Wiretastix Running: Daemon running and accessible on port 8085
Wiretastix Configuration
Configure Wiretastix to work behind a proxy:
Edit /etc/wiretastix/wiretastix.yaml:
webserver:
# Bind to localhost only - proxy will forward
binding: 127.0.0.1:8085
# Base path (usually /)
base: /
# Disable ACME if proxy handles TLS
acme-host: []
# Assets and templates
html-assets: /usr/lib/wiretastix/html
html-templates: /usr/lib/wiretastix/templates
# API server - also localhost only
apiserver:
binding: 127.0.0.1:8095
base: /wiretastix/api/v1/
# OIDC redirect URL must match public URL
oidc:
redirect-url: https://vpn.example.com/callback
# ... other OIDC settings
Important: Set binding to 127.0.0.1 to prevent direct external access, forcing all traffic through the proxy.
Restart Wiretastix:
sudo systemctl restart wiretastix
Option 1: Nginx (Recommended)
Nginx is a high-performance reverse proxy, widely used and well-documented.
Installation
Debian/Ubuntu:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx
Rocky Linux/AlmaLinux:
sudo dnf install nginx certbot python3-certbot-nginx
Configuration
Create Nginx configuration file:
sudo nano /etc/nginx/sites-available/wiretastix
Add the following configuration:
# Upstream definition
upstream wiretastix_web {
server 127.0.0.1:8085;
keepalive 32;
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name vpn.example.com;
# Allow Let's Encrypt verification
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# Redirect everything else to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name vpn.example.com;
# SSL certificates (will be configured by certbot)
ssl_certificate /etc/letsencrypt/live/vpn.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vpn.example.com/privkey.pem;
# SSL configuration - modern and secure
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Logs
access_log /var/log/nginx/wiretastix-access.log;
error_log /var/log/nginx/wiretastix-error.log;
# Proxy to Wiretastix
location / {
proxy_pass http://wiretastix_web;
proxy_http_version 1.1;
# Preserve original request information
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# WebSocket support (if needed)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}
# Optional: Separate location for API if needed
location /wiretastix/api/ {
proxy_pass http://127.0.0.1:8095;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# API might have larger payloads
client_max_body_size 10M;
}
}
Enable the site:
# Create symlink
sudo ln -s /etc/nginx/sites-available/wiretastix /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# If test passes, reload Nginx
sudo systemctl reload nginx
Obtain SSL Certificate
Using Let’s Encrypt with Certbot:
# Obtain certificate
sudo certbot --nginx -d vpn.example.com
# Follow prompts and choose options:
# - Enter email address
# - Agree to terms
# - Choose to redirect HTTP to HTTPS (recommended)
Certbot will automatically:
- Obtain the certificate
- Update Nginx configuration
- Set up automatic renewal
Test automatic renewal:
sudo certbot renew --dry-run
Verify Configuration
Test the setup:
# Check Nginx is running
sudo systemctl status nginx
# Test HTTPS access
curl -I https://vpn.example.com
# Check certificate
echo | openssl s_client -connect vpn.example.com:443 -servername vpn.example.com 2>/dev/null | openssl x509 -noout -dates
Option 2: Caddy (Easiest)
Caddy provides automatic HTTPS with Let’s Encrypt built-in, making it the simplest option.
Installation
Debian/Ubuntu:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
Or download binary:
curl -OL "https://github.com/caddyserver/caddy/releases/download/v2.7.5/caddy_2.7.5_linux_amd64.tar.gz"
tar xzf caddy_2.7.5_linux_amd64.tar.gz
sudo mv caddy /usr/local/bin/
Configuration
Create or edit /etc/caddy/Caddyfile:
# Wiretastix proxy with automatic HTTPS
vpn.example.com {
# Automatic HTTPS (Let's Encrypt)
# Caddy handles this automatically!
# Reverse proxy to Wiretastix
reverse_proxy localhost:8085 {
# Preserve original request info
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
}
# Security headers
header {
# Enable HSTS
Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Prevent clickjacking
X-Frame-Options "SAMEORIGIN"
# Prevent MIME sniffing
X-Content-Type-Options "nosniff"
# XSS protection
X-XSS-Protection "1; mode=block"
}
# Logging
log {
output file /var/log/caddy/wiretastix-access.log
format json
}
}
# Optional: API endpoint on subdomain
api.vpn.example.com {
reverse_proxy localhost:8095
}
Start Caddy:
# Test configuration
sudo caddy validate --config /etc/caddy/Caddyfile
# Start Caddy
sudo systemctl enable caddy
sudo systemctl start caddy
# Check status
sudo systemctl status caddy
That’s it! Caddy automatically:
- Obtains Let’s Encrypt certificates
- Configures HTTPS
- Handles renewal
- Redirects HTTP to HTTPS
Verify Configuration
# Check Caddy status
sudo systemctl status caddy
# View logs
sudo journalctl -u caddy -f
# Test HTTPS
curl -I https://vpn.example.com
Option 3: Apache (httpd)
Apache is a mature, feature-rich web server widely used in enterprise environments.
Installation
Debian/Ubuntu:
sudo apt update
sudo apt install apache2 certbot python3-certbot-apache
sudo a2enmod ssl proxy proxy_http headers rewrite
Rocky Linux/AlmaLinux:
sudo dnf install httpd mod_ssl certbot python3-certbot-apache
Configuration
Create Apache configuration:
sudo nano /etc/apache2/sites-available/wiretastix.conf
# Or on Rocky/Alma: /etc/httpd/conf.d/wiretastix.conf
Add configuration:
# Redirect HTTP to HTTPS
<VirtualHost *:80>
ServerName vpn.example.com
# Allow Let's Encrypt
Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/
<Directory "/var/www/html/.well-known/acme-challenge/">
Options None
AllowOverride None
Require all granted
</Directory>
# Redirect to HTTPS
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
# HTTPS VirtualHost
<VirtualHost *:443>
ServerName vpn.example.com
# SSL Configuration (will be set by certbot)
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/vpn.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/vpn.example.com/privkey.pem
# Modern SSL configuration
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# Security headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# Logs
ErrorLog ${APACHE_LOG_DIR}/wiretastix-error.log
CustomLog ${APACHE_LOG_DIR}/wiretastix-access.log combined
# Proxy configuration
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8085/
ProxyPassReverse / http://127.0.0.1:8085/
# Pass headers
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
</VirtualHost>
Enable and start:
# Debian/Ubuntu
sudo a2ensite wiretastix
sudo apache2ctl configtest
sudo systemctl reload apache2
# Rocky/Alma
sudo httpd -t
sudo systemctl reload httpd
Obtain SSL Certificate
# Debian/Ubuntu
sudo certbot --apache -d vpn.example.com
# Rocky/Alma
sudo certbot --apache -d vpn.example.com
Option 4: Traefik (Docker-Native)
Traefik is ideal for Docker deployments with automatic service discovery.
Docker Compose Configuration
Create or modify docker-compose.yml:
version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
command:
# API and dashboard
- "--api.dashboard=true"
- "--api.insecure=false"
# Docker provider
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# Entrypoints
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# HTTPS redirect
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
# Let's Encrypt
- "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
# Logging
- "--log.level=INFO"
- "--accesslog=true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
labels:
# Dashboard access (optional)
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.vpn.example.com`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
wiretastix:
image: wiretastix:latest
container_name: wiretastix-daemon
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
- SYS_MODULE
volumes:
- ./config/wiretastix.yaml:/etc/wiretastix/wiretastix.yaml:ro
- ./config/nftables.conf:/etc/nftables.conf:ro
- ./data:/data
- /lib/modules:/lib/modules:ro
labels:
# Enable Traefik
- "traefik.enable=true"
# HTTP router
- "traefik.http.routers.wiretastix.rule=Host(`vpn.example.com`)"
- "traefik.http.routers.wiretastix.entrypoints=websecure"
- "traefik.http.routers.wiretastix.tls.certresolver=letsencrypt"
# Service
- "traefik.http.services.wiretastix.loadbalancer.server.port=8085"
postgres:
image: postgres:16-alpine
# ... postgres config ...
Create letsencrypt directory:
mkdir -p letsencrypt
chmod 600 letsencrypt
Start services:
docker compose up -d
Traefik automatically:
- Discovers Wiretastix service
- Obtains Let’s Encrypt certificate
- Routes traffic to Wiretastix
- Handles HTTPS and redirects
Advanced Configurations
Rate Limiting (Nginx)
Protect against brute force attacks:
# Add to http block
http {
# Define rate limit zone
limit_req_zone $binary_remote_addr zone=wiretastix_login:10m rate=5r/m;
# ... rest of http config
}
# In server block
server {
# ... other config
# Apply rate limit to login/auth endpoints
location /callback {
limit_req zone=wiretastix_login burst=3 nodelay;
proxy_pass http://wiretastix_web;
# ... other proxy settings
}
}
IP Whitelisting (Nginx)
Restrict API access to specific IPs:
# In server block
location /wiretastix/api/ {
# Allow specific IPs
allow 10.0.0.0/8;
allow 192.168.1.0/24;
deny all;
proxy_pass http://127.0.0.1:8095;
# ... other proxy settings
}
Custom Headers (Caddy)
Add custom headers for security or debugging:
vpn.example.com {
reverse_proxy localhost:8085
header {
# Custom header
X-Proxy-By "Caddy"
# CORS (if needed)
Access-Control-Allow-Origin "https://example.com"
# CSP
Content-Security-Policy "default-src 'self'"
}
}
Load Balancing (Nginx)
For high availability setups:
upstream wiretastix_cluster {
least_conn;
server 127.0.0.1:8085 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8086 max_fails=3 fail_timeout=30s backup;
keepalive 32;
}
server {
# ... SSL config
location / {
proxy_pass http://wiretastix_cluster;
# ... proxy settings
}
}
Testing the Setup
Verify HTTPS
# Test HTTPS access
curl -I https://vpn.example.com
# Check certificate
echo | openssl s_client -connect vpn.example.com:443 -servername vpn.example.com 2>/dev/null | openssl x509 -noout -text
# Test SSL Labs (optional)
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=vpn.example.com
Verify Headers
# Check security headers are present
curl -I https://vpn.example.com | grep -E "(Strict-Transport-Security|X-Frame-Options|X-Content-Type)"
Test OIDC Flow
- Open browser to
https://vpn.example.com - Should redirect to OIDC provider
- After authentication, should return to Wiretastix
- Check browser console for any errors
Verify Internal Access Blocked
# This should fail (timeout or connection refused)
curl http://your-server-ip:8085
# Only accessible via proxy
curl https://vpn.example.com # This should work
Troubleshooting
502 Bad Gateway
Cause: Proxy can’t reach Wiretastix
Solutions:
- Check Wiretastix is running:
systemctl status wiretastix - Verify binding: Wiretastix should listen on 127.0.0.1:8085
- Check firewall doesn’t block localhost communication
- Review proxy logs for connection errors
SSL Certificate Errors
Cause: Certificate issues
Solutions:
- Check certificate files exist and are readable
- Verify domain DNS points to your server
- Ensure ports 80 and 443 are accessible from internet
- For Let’s Encrypt, check rate limits
- Review certbot logs:
sudo journalctl -u certbot -f
OIDC Callback Fails
Cause: Redirect URL mismatch
Solutions:
- Ensure
oidc.redirect-urlin Wiretastix matches public URL - Must be
https://vpn.example.com/callback, nothttp://or IP - Update OIDC provider with correct callback URL
- Check proxy forwards Host header correctly
Headers Not Passed
Cause: Missing proxy headers
Solutions:
- Verify
proxy_set_header(Nginx) or equivalent in config - Especially important:
X-Forwarded-ProtoandHost - Check Wiretastix logs for received headers
- Test with curl:
curl -H "X-Forwarded-Proto: https" http://localhost:8085
Security Best Practices
- Always use HTTPS: Never expose Wiretastix over HTTP in production
- Keep certificates updated: Enable automatic renewal (certbot, Caddy)
- Use strong ciphers: Disable old protocols (SSLv3, TLSv1.0, TLSv1.1)
- Enable HSTS: Force browsers to always use HTTPS
- Implement rate limiting: Protect against brute force
- Monitor logs: Watch for suspicious access patterns
- Restrict API access: Use IP whitelisting if possible
- Regular updates: Keep proxy software updated
- Secure proxy server: Harden the proxy OS and configuration
- Backup certificates: Include in backup procedures
Performance Optimization
Enable Compression (Nginx)
# In http block
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
HTTP/2 and HTTP/3
# Nginx
listen 443 ssl http2;
listen 443 quic reuseport; # HTTP/3
# Caddy (automatic HTTP/2, HTTP/3)
vpn.example.com {
# HTTP/2 and HTTP/3 enabled by default
}
Connection Pooling
upstream wiretastix_web {
server 127.0.0.1:8085;
keepalive 32; # Maintain 32 keepalive connections
keepalive_requests 100;
keepalive_timeout 60s;
}
Monitoring
Nginx Status
# Add to server block
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
Access: curl http://localhost/nginx_status
Log Analysis
# Nginx access log
sudo tail -f /var/log/nginx/wiretastix-access.log
# Caddy logs
sudo journalctl -u caddy -f
# Apache logs
sudo tail -f /var/log/apache2/wiretastix-access.log
Related Documentation
- Installation Guides - Wiretastix installation methods
- OIDC Configuration - OIDC provider setup
- Security Hardening - Security best practices
- Backup and Recovery - Include proxy configs in backups
Additional Resources
- Nginx Documentation
- Caddy Documentation
- Apache Documentation
- Traefik Documentation
- Let’s Encrypt
- SSL Labs - Test your SSL configuration