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