# Caddyfile for Eliza Kragh v. MAD Court Docket Website # This file should be placed in the Caddy configuration directory on the remote server # Replace with your actual domain docket.example.com { # Enable automatic HTTPS tls { # Use Let's Encrypt for SSL certificates # email admin@example.com } # Security headers header { # Security headers for legal document website Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" X-XSS-Protection "1; mode=block" Referrer-Policy "strict-origin-when-cross-origin" # Remove server information -Server -X-Powered-By } # Rate limiting for API endpoints rate_limit { zone api { key {remote_host} events 100 window 1m } zone auth { key {remote_host} events 10 window 1m } } # API routes with rate limiting @api path /api/* rate_limit @api api @auth path /api/auth/* rate_limit @auth auth # Reverse proxy to frontend container reverse_proxy frontend:3000 { # Health check health_uri / health_interval 30s health_timeout 10s # Load balancing (if multiple instances) lb_policy round_robin # Headers for proper forwarding header_up Host {host} 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} } # Logging for legal compliance log { output file /var/log/caddy/docket-access.log { roll_size 100mb roll_keep 10 roll_keep_for 720h } format json level INFO } # Error handling handle_errors { @5xx expression {http.error.status_code} >= 500 respond @5xx "Service temporarily unavailable" 503 @4xx expression {http.error.status_code} >= 400 && {http.error.status_code} < 500 respond @4xx "Page not found" 404 } } # Admin subdomain (optional - for enhanced security) admin.docket.example.com { tls { # email admin@example.com } # Additional security for admin interface header { Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" X-Content-Type-Options "nosniff" X-Frame-Options "DENY" X-XSS-Protection "1; mode=block" Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'" } # Stricter rate limiting for admin rate_limit { zone admin { key {remote_host} events 20 window 1m } } rate_limit admin # Only allow admin routes @admin path /admin* handle @admin { reverse_proxy frontend:3000 { header_up Host {host} header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} header_up X-Forwarded-Proto {scheme} } } # Redirect non-admin requests to main site redir https://docket.example.com{uri} permanent log { output file /var/log/caddy/admin-access.log { roll_size 50mb roll_keep 20 roll_keep_for 2160h # 90 days } format json level INFO } } # HTTP to HTTPS redirect http://docket.example.com { redir https://docket.example.com{uri} permanent } http://admin.docket.example.com { redir https://admin.docket.example.com{uri} permanent }