Reverse Proxy Security for AI Bot Servers (Nginx & Caddy)
Secure your AI bot server with proper reverse proxy configuration. Covers Nginx and Caddy setup, X-Forwarded-For headers, rate limiting, and SSL/TLS with Let's Encrypt.
Why Reverse Proxies Create Security Issues
Reverse proxies like Nginx and Caddy sit between the internet and your application. This creates a critical security challenge: your application sees all requests as coming from localhost.
Internet → Reverse Proxy → Your Bot
(127.0.0.1)
Many applications, including OpenClaw, trust localhost connections implicitly. When every request appears to come from 127.0.0.1, this trust becomes a vulnerability.
The Localhost Trust Problem
Here's what happens without proper configuration:
- Attacker connects from
1.2.3.4 - Nginx receives the request
- Nginx forwards to
localhost:3000 - Your bot sees connection from
127.0.0.1 - Bot auto-approves because "localhost is trusted"
- Attacker has full access
The fix: Configure your reverse proxy to forward the real client IP, and configure your application to read it correctly.
Nginx Configuration for AI Bots
Basic Secure Setup
# /etc/nginx/sites-available/your-bot
# Rate limiting zone (defined at http level in nginx.conf)
# limit_req_zone $binary_remote_addr zone=botzone:10m rate=10r/s;
server {
listen 80;
server_name your-domain.com;
# Redirect all HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL Certificate (Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Modern SSL configuration
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;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
# Rate limiting
limit_req zone=botzone burst=20 nodelay;
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# CRITICAL: Forward real client IP
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 Host $host;
# WebSocket support (required for many bots)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
Adding Rate Limiting
Rate limiting prevents brute force attacks and abuse.
Add to /etc/nginx/nginx.conf (inside the http block):
http {
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=botzone:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=loginzone:10m rate=1r/s;
# Connection limiting
limit_conn_zone $binary_remote_addr zone=connzone:10m;
# ... rest of config
}
Apply in location blocks:
location / {
limit_req zone=botzone burst=20 nodelay;
limit_conn connzone 10;
# ... proxy settings
}
location /api/auth {
limit_req zone=loginzone burst=5 nodelay;
# ... proxy settings
}
Security Headers
Add these headers for additional protection:
server {
# ... other config
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Content Security Policy (adjust as needed)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
}
Caddy Configuration for AI Bots
Caddy automatically handles SSL/TLS with Let's Encrypt and has simpler configuration.
Basic Secure Setup
# /etc/caddy/Caddyfile
your-domain.com {
# Automatic HTTPS with Let's Encrypt
# Rate limiting
rate_limit {
zone dynamic {
key {remote_host}
events 10
window 1s
}
}
reverse_proxy localhost:3000 {
# Forward real IP headers
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
# Health checks
health_uri /health
health_interval 30s
# Timeouts
transport http {
dial_timeout 5s
response_header_timeout 60s
}
}
# Security headers
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
Referrer-Policy "strict-origin-when-cross-origin"
Strict-Transport-Security "max-age=63072000"
}
}
Caddy with Basic Auth
For additional protection, add HTTP Basic Auth:
your-domain.com {
basicauth /* {
admin $2a$14$... # Use `caddy hash-password` to generate
}
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
Generate password hash:
caddy hash-password
SSL/TLS with Let's Encrypt
Nginx with Certbot
# Install Certbot
sudo apt install certbot python3-certbot-nginx -y
# Obtain certificate
sudo certbot --nginx -d your-domain.com
# Auto-renewal is configured automatically
# Test renewal
sudo certbot renew --dry-run
Caddy Automatic SSL
Caddy handles SSL automatically. Just specify your domain and it provisions certificates from Let's Encrypt.
Ensure ports 80 and 443 are open:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Application Configuration
Your application must be configured to trust proxy headers.
OpenClaw Configuration
gateway:
auth:
password: "your-strong-password"
trustedProxies:
- "127.0.0.1"
- "::1"
This tells OpenClaw to:
- Require password authentication
- Trust
X-Forwarded-Forheaders from localhost only
Node.js/Express
const app = express();
// Trust first proxy
app.set('trust proxy', 1);
// Or trust specific IPs
app.set('trust proxy', ['127.0.0.1', '::1']);
Testing Your Configuration
Verify Real IP Forwarding
Create a test endpoint or check logs:
# Watch access logs for real IPs
sudo tail -f /var/log/nginx/access.log
You should see actual client IPs, not 127.0.0.1.
Test Rate Limiting
# Rapid requests to trigger rate limit
for i in {1..50}; do curl -I https://your-domain.com; done
You should see 429 (Too Many Requests) responses after the limit is hit.
Test SSL Configuration
Use SSL Labs: ssllabs.com/ssltest
Enter your domain and verify you get an A or A+ rating.
Test Security Headers
curl -I https://your-domain.com
Verify headers like X-Frame-Options, X-Content-Type-Options are present.
Complete Nginx Example for OpenClaw
# /etc/nginx/sites-available/openclaw
# Rate limiting
limit_req_zone $binary_remote_addr zone=openclaw:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=openclaw_auth:10m rate=1r/s;
server {
listen 80;
server_name bot.your-domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name bot.your-domain.com;
# SSL
ssl_certificate /etc/letsencrypt/live/bot.your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bot.your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Security headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# Logging
access_log /var/log/nginx/openclaw.access.log;
error_log /var/log/nginx/openclaw.error.log;
location / {
limit_req zone=openclaw burst=20 nodelay;
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# Forward real IP
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 Host $host;
# WebSocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 300s;
}
}
Complete Caddy Example for OpenClaw
# /etc/caddy/Caddyfile
bot.your-domain.com {
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
header {
Strict-Transport-Security "max-age=63072000"
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
}
log {
output file /var/log/caddy/openclaw.log
}
}
Security Checklist
- [ ] HTTP redirects to HTTPS
- [ ] Valid SSL certificate (A+ rating on SSL Labs)
- [ ] X-Forwarded-For headers configured
- [ ] Application trusts proxy headers from localhost only
- [ ] Rate limiting enabled
- [ ] Security headers set
- [ ] WebSocket support configured (if needed)
- [ ] Logging enabled for security monitoring
Need Professional Help?
Reverse proxy configuration is critical for security. A misconfiguration can expose your entire server.
Our Premium Setup includes:
- Proper Nginx/Caddy configuration
- SSL/TLS with Let's Encrypt
- Rate limiting and security headers
- Application-specific proxy settings
- Ongoing security updates
Contact us to get your server properly secured.
Related Guides
Need a VPS for Your Bot?
We recommend Hostinger KVM 2 VPS - reliable, fast, and perfect for AI chatbots. Get started with our recommended setup.
Get Hostinger VPSNeed Help With Setup?
Got your VPS? Let us handle the technical work. Professional setup and maintenance for OpenClaw (formerly Clawd.bot).