Caddy Reverse Proxy¶
Caddy is a modern, easy-to-use reverse proxy with automatic HTTPS.
Why Caddy?¶
- Automatic HTTPS: Let's Encrypt integration out of the box
- Simple Configuration: Human-readable Caddyfile
- HTTP/2 & HTTP/3: Modern protocol support
- Dynamic Reloads: Config changes without restart
Basic Configuration¶
Create /etc/caddy/Caddyfile:
{
auto_https off # Disable if behind another proxy
admin off # Disable admin API (optional)
}
api.yourstore.com {
# Reverse proxy to R Commerce
reverse_proxy localhost:8080
# File upload size
request_body {
max_size 50MB
}
# 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"
-Server # Remove server header
}
# Logging
log {
output file /var/log/caddy/access.log
format json
}
# Compress responses
encode gzip zstd
}
Automatic HTTPS¶
Caddy automatically obtains and renews certificates:
api.yourstore.com {
reverse_proxy localhost:8080
# TLS is automatic, but you can customize:
tls {
protocols tls1.2 tls1.3
ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
}
}
Load Balancing¶
Multiple R Commerce instances:
api.yourstore.com {
reverse_proxy {
to 10.0.1.10:8080 10.0.1.11:8080 10.0.1.12:8080
# Load balancing policy
lb_policy least_conn
# Health checks
health_uri /health
health_interval 10s
health_timeout 5s
}
}
Load Balancing Policies¶
| Policy | Description |
|---|---|
random |
Random selection |
random_choose 2 |
Random with 2 choices |
least_conn |
Fewest active connections |
round_robin |
Even distribution |
first |
First available |
ip_hash |
Based on client IP |
uri_hash |
Based on request URI |
Rate Limiting¶
{
order rate_limit before basicauth
}
api.yourstore.com {
# Rate limit: 10 requests per second per IP
rate_limit {
zone static_example {
key static
events 10
window 1s
}
}
reverse_proxy localhost:8080
}
Or use the http.rate_limit module:
api.yourstore.com {
rate_limit {
zone ip_limit {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy localhost:8080
}
Caching¶
{
order cache before rewrite
}
api.yourstore.com {
# Cache API responses
cache {
ttl 5m
stale 1h
}
reverse_proxy localhost:8080
}
WebSocket Support¶
Caddy handles WebSockets automatically:
api.yourstore.com {
# WebSocket connections are automatically upgraded
reverse_proxy localhost:8080
# Increase timeouts for long-lived connections
timeouts {
read_body 0
read_header 30s
write 0
idle 5m
}
}
Request/Response Manipulation¶
api.yourstore.com {
# Add custom headers to upstream
reverse_proxy localhost:8080 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
# Modify response headers
header_down Server "R Commerce"
# Remove sensitive headers
header_down -X-Powered-By
}
Multiple Sites¶
# API server
api.yourstore.com {
reverse_proxy localhost:8080
}
# Admin panel
admin.yourstore.com {
reverse_proxy localhost:8081
# IP restriction
@not_allowed {
not remote_ip 10.0.0.0/8 172.16.0.0/12
}
respond @not_allowed "Forbidden" 403
}
# Static files
static.yourstore.com {
root /var/www/static
file_server
encode gzip
}
Logging¶
api.yourstore.com {
reverse_proxy localhost:8080
log {
output file /var/log/caddy/access.log {
roll_size 100MB
roll_keep 10
roll_keep_days 30
}
format json {
time_format iso8601
}
}
}
Docker Compose¶
version: '3.8'
services:
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- rcommerce
rcommerce:
image: rcommerce:latest
environment:
- RCOMMERCE_CONFIG=/etc/rcommerce/config.toml
volumes:
- ./config.toml:/etc/rcommerce/config.toml
Management Commands¶
# Validate configuration
caddy validate --config /etc/caddy/Caddyfile
# Reload configuration
caddy reload --config /etc/caddy/Caddyfile
# Start Caddy
caddy run --config /etc/caddy/Caddyfile
# Run as service
systemctl start caddy
systemctl enable caddy
Troubleshooting¶
| Issue | Solution |
|---|---|
| Certificate errors | Check DNS and firewall for ACME challenges |
| 502 errors | Verify R Commerce is running |
| Config won't load | Run caddy validate to check syntax |
| High memory | Adjust GOGC environment variable |
Migration from Nginx¶
| Nginx | Caddy |
|---|---|
proxy_pass |
reverse_proxy |
ssl_certificate |
Automatic (or tls) |
gzip on |
encode gzip |
client_max_body_size |
request_body max_size |
add_header |
header |
access_log |
log |