Reverse Proxy Configuration for Web Services
Configuration guides for popular reverse proxy solutions (NGINX, Caddy, Traefik) used with self-hosted web applications.
NGINX Configuration
Basic Reverse Proxy
server {
listen 443 ssl http2;
server_name vault.example.com;
# SSL configuration
ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Security headers
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
client_max_body_size 525M;
location / {
proxy_pass http://localhost:8080;
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;
}
}
# HTTP redirect
server {
listen 80;
server_name vault.example.com;
return 301 https://$server_name$request_uri;
} WebSocket Support
server {
listen 443 ssl http2;
server_name vault.example.com;
# WebSocket support for Vaultwarden
location /notifications/hub {
proxy_pass http://localhost:3012;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
location /notifications/hub/negotiate {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
} Security Hardening
# Rate limiting
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
listen 443 ssl http2;
server_name vault.example.com;
# Restrict admin panel by IP
location /admin {
allow 192.168.1.0/24;
deny all;
proxy_pass http://localhost:8080;
# ... other proxy settings
}
# Rate limit login endpoints
location /identity/connect/token {
limit_req zone=login burst=5 nodelay;
proxy_pass http://localhost:8080;
}
} Caddy Configuration
Basic Setup (Automatic HTTPS)
Caddyfile:
vault.example.com {
reverse_proxy localhost:8080 {
header_up X-Real-IP {remote_host}
}
reverse_proxy /notifications/hub localhost:3012
} Caddy handles SSL with Let’s Encrypt automatically.
Advanced Configuration
vault.example.com {
# Custom TLS
tls admin@example.com {
protocols tls1.2 tls1.3
}
# Security headers
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
}
# File upload limit
request_body {
max_size 525MB
}
# Main application
reverse_proxy localhost:8080 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
# WebSocket
reverse_proxy /notifications/hub localhost:3012
} IP Restriction
vault.example.com {
@admin {
path /admin*
not remote_ip 192.168.1.0/24
}
respond @admin 403
reverse_proxy localhost:8080
} Traefik Configuration
Docker Labels (Recommended)
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
labels:
# Enable Traefik
- "traefik.enable=true"
# Main application
- "traefik.http.routers.vaultwarden.rule=Host(`vault.example.com`)"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
# WebSocket
- "traefik.http.routers.vaultwarden-ws.rule=Host(`vault.example.com`) && Path(`/notifications/hub`)"
- "traefik.http.routers.vaultwarden-ws.entrypoints=websecure"
- "traefik.http.routers.vaultwarden-ws.tls.certresolver=letsencrypt"
- "traefik.http.services.vaultwarden-ws.loadbalancer.server.port=3012"
networks:
- traefik
networks:
traefik:
external: true Static Configuration (traefik.yml)
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web Dynamic Configuration (File Provider)
http:
routers:
vaultwarden:
rule: "Host(`vault.example.com`)"
entryPoints:
- websecure
service: vaultwarden
tls:
certResolver: letsencrypt
services:
vaultwarden:
loadBalancer:
servers:
- url: "http://localhost:8080" SSL/TLS Configuration
Let’s Encrypt with Certbot
# Install certbot
sudo apt install certbot python3-certbot-nginx
# Obtain certificate
sudo certbot --nginx -d vault.example.com
# Auto-renewal
sudo certbot renew --dry-run Manual Certificate Installation
NGINX:
ssl_certificate /etc/ssl/certs/vault.example.com.crt;
ssl_certificate_key /etc/ssl/private/vault.example.com.key;
ssl_trusted_certificate /etc/ssl/certs/ca-bundle.crt; Caddy:
vault.example.com {
tls /etc/ssl/certs/vault.crt /etc/ssl/private/vault.key
reverse_proxy localhost:8080
} Load Balancing
NGINX Upstream
upstream vaultwarden_backend {
least_conn;
server 192.168.1.10:8080 weight=1;
server 192.168.1.11:8080 weight=1;
server 192.168.1.12:8080 backup;
}
server {
listen 443 ssl http2;
server_name vault.example.com;
location / {
proxy_pass http://vaultwarden_backend;
proxy_set_header Host $host;
}
} Traefik Weighted Load Balancing
services:
vaultwarden:
labels:
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
- "traefik.http.services.vaultwarden.loadbalancer.sticky.cookie=true" Troubleshooting
NGINX Issues
Test configuration:
sudo nginx -t
sudo systemctl reload nginx View logs:
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log Caddy Issues
Check configuration:
caddy validate --config /etc/caddy/Caddyfile
caddy reload --config /etc/caddy/Caddyfile View logs:
journalctl -u caddy -f Traefik Issues
Debug mode:
log:
level: DEBUG Access logs:
accessLog:
filePath: "/var/log/traefik/access.log" Related Documentation
- Vaultwarden Self-Hosted Deployment - Vaultwarden reverse proxy setup
- Bitwarden Self-Hosted Deployment - Bitwarden proxy configuration
- SSL Certificate Management - Certificate management
- Docker Compose Configuration for Password Managers - Container networking