darcsweb - Caddyfile

[root] / Caddyfile
# Caddy reverse proxy for DarcsWeb
#
# Caddy automatically provisions and renews TLS certificates via ACME (Let's
# Encrypt) and redirects HTTP to HTTPS. It does NOT send
# Strict-Transport-Security by itself; the header block below adds it.
#
# Usage:
#   caddy run --config Caddyfile
#
# Or via the bundled docker-compose.yml:
#   docker compose up -d
#
# Rate limiting is disabled by default: `rate_limit` is a third-party
# directive that the stock `caddy:2-alpine` image does not include, and
# Caddy refuses to start with it. To enable it, build a custom image
# (`FROM caddy:builder` then `xcaddy build --with
# github.com/mholt/caddy-ratelimit`), point docker-compose.yml at it,
# uncomment the global option and the `rate_limit` block below.
#
# {
# 	order rate_limit before basic_auth
# }

darcs.example.com {
	# Rate limiting: 10 requests/s per client IP (needs the module above)
	# 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"
		# HSTS: one year, this host only (no includeSubDomains, no preload)
		Strict-Transport-Security "max-age=31536000"
		# Restrict browser APIs (same value as the application sends)
		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
		}
	}
}