main pico / caddy / Caddyfile.pgs
Antonio Mika  ·  2026-10-25
  1{
  2	storage redis {
  3		address {$VALKEY_ADDR}
  4		password "{$VALKEY_PASSWORD}"
  5		timeout 5
  6		key_prefix "caddy"
  7	}
  8	on_demand_tls {
  9		ask http://web:3000/check
 10	}
 11	servers {
 12		metrics
 13		trusted_proxies static 0.0.0.0/0
 14	}
 15}
 16
 17# Metrics routes need ?x-authorization={$METRICS_TOKEN}. An unset token matches
 18# nothing.
 19(metrics_token) {
 20	expression `{http.request.uri.query.x-authorization} == "{$METRICS_TOKEN}" && "{$METRICS_TOKEN}" != ""`
 21}
 22
 23# Apps serve metrics on /_metrics, which only the token-checked routes reach.
 24# Scrapes stay out of the access logs so the token does too.
 25(block_app_metrics) {
 26	@appmetrics path /_metrics /_metrics/*
 27	respond @appmetrics 404
 28	@metricsroutes path /_caddy/metrics /_ssh/metrics /_web/metrics /_imgproxy/metrics /_app/metrics
 29	log_skip @metricsroutes
 30}
 31
 32# custom domains
 33:443 {
 34	import block_app_metrics
 35	reverse_proxy web:3000
 36	log {
 37		format append {
 38			server_id {$APP_DOMAIN}
 39		}
 40	}
 41	tls {$APP_EMAIL} {
 42		on_demand
 43	}
 44	encode zstd gzip
 45}
 46
 47# subdomains and root pgs domain
 48*.{$APP_DOMAIN}, {$APP_DOMAIN} {
 49	import block_app_metrics
 50	reverse_proxy web:3000
 51	log {
 52		format append {
 53			server_id {$APP_DOMAIN}
 54		}
 55	}
 56	tls {$APP_EMAIL} {
 57		dns cloudflare {$CF_API_TOKEN}
 58		resolvers 1.1.1.1
 59	}
 60
 61	encode zstd gzip
 62
 63	header {
 64		# disable FLoC tracking
 65		?Permissions-Policy interest-cohort=()
 66
 67		# enable HSTS
 68		?Strict-Transport-Security max-age=31536000;
 69
 70		# disable clients from sniffing the media type
 71		?X-Content-Type-Options nosniff
 72
 73		# clickjacking protection
 74		?X-Frame-Options DENY
 75
 76		# keep referrer data off of HTTP connections
 77		?Referrer-Policy no-referrer-when-downgrade
 78
 79		?X-XSS-Protection "1; mode=block"
 80	}
 81
 82	@caddymetrics {
 83		host {$APP_DOMAIN} *.{$APP_DOMAIN}
 84		path /_caddy/metrics
 85		import metrics_token
 86	}
 87
 88	metrics @caddymetrics {
 89		disable_openmetrics
 90	}
 91
 92	@sshmetrics {
 93		host {$APP_DOMAIN} *.{$APP_DOMAIN}
 94		path /_ssh/metrics
 95		import metrics_token
 96	}
 97
 98	handle @sshmetrics {
 99		rewrite * /metrics
100		reverse_proxy ssh:9222
101	}
102
103	@webmetrics {
104		host {$APP_DOMAIN} *.{$APP_DOMAIN}
105		path /_web/metrics
106		import metrics_token
107	}
108
109	handle @webmetrics {
110		rewrite * /_metrics
111		reverse_proxy web:3000 {
112			header_up Host {$APP_DOMAIN}
113		}
114	}
115
116	@imgproxymetrics {
117		host {$APP_DOMAIN} *.{$APP_DOMAIN}
118		path /_imgproxy/metrics
119		import metrics_token
120	}
121
122	handle @imgproxymetrics {
123		rewrite * /metrics
124		reverse_proxy imgproxy:8081
125	}
126}