darcsweb - Caddyfile

[root] / Caddyfile
# Caddy reverse proxy for DarcsWeb
#
# Caddy automatically provisions and renews TLS certificates via ACME (Let's
# Encrypt) and enables HSTS by default.  This configuration adds additional
# security hardening on top.
#
# Usage:
#   caddy run --config Caddyfile
#
# Or via the bundled docker-compose.yml:
#   docker compose up -d
#
# Note: the `rate_limit` directive below requires the caddy-ratelimit
# module. The stock `caddy:2-alpine` image does not include it -- either
# build a custom image (`FROM caddy:builder` then `xcaddy build --with
# github.com/mholt/caddy-ratelimit`), use a prebuilt image that bundles
# the module, or remove the `rate_limit { ... }` block to run with the
# stock image.

darcs.example.com {
	# Rate limiting: 10 requests/s per client IP, burst of 20
	rate_limit {
		zone darcsweb {
			key    {remote_host}
			events 10
			window 1s
		}
	}

	# Security headers (layered with application-level headers)
	header {
		# Prevent MIME type sniffing
		X-Content-Type-Options "nosniff"
		# Prevent clickjacking
		X-Frame-Options "DENY"
		# Control referrer information
		Referrer-Policy "strict-origin-when-cross-origin"
		# Restrict browser APIs
		Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"
		# Prevent search engine indexing
		X-Robots-Tag "noindex, nofollow"
		# Remove server identification
		-Server
	}

	# Reverse proxy to darcsweb backend
	reverse_proxy darcsweb:3000 {
		# Timeouts to prevent slow-loris and idle connections
		transport http {
			dial_timeout      5s
			response_header_timeout 30s
		}

		# Pass client info to backend
		header_up X-Real-IP {remote_host}
		header_up X-Forwarded-Proto {scheme}
	}

	# Limit request body size (read-only app, no uploads expected)
	request_body {
		max_size 4KB
	}

	# Access log
	log {
		output file /var/log/caddy/darcsweb.log {
			roll_size 10MiB
			roll_keep 5
		}
	}
}