# DataCenterIndex edge (data node). Plain HTTP on :8300, published ONLY on the WireGuard address # 10.67.0.60 (see compose.data.yml). TLS terminates upstream on the BHS64 gateway # (Caddy: https://www.datacenterindex.io → 10.67.0.60:8300), which is the trusted proxy. { admin off auto_https off servers { trusted_proxies static 10.67.0.0/24 10.68.0.0/30 172.16.0.0/12 metrics } log { output stdout format json level INFO } } :8300 { encode zstd gzip header { -Server X-Content-Type-Options nosniff X-Frame-Options DENY Referrer-Policy strict-origin-when-cross-origin Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" defer } # Fastify API — /api/v1/* public, /api/admin/* token, /api/health, /api/metrics @api path /api/* handle @api { # metrics are for Prometheus on the docker network only @metrics path /api/metrics respond @metrics 404 reverse_proxy api:8311 { health_uri /api/ready health_interval 15s fail_duration 10s lb_try_duration 5s } } # Next hashed assets are immutable handle /_next/static/* { header Cache-Control "public, max-age=31536000, immutable" reverse_proxy web:8310 } handle /_next/image* { header Cache-Control "public, max-age=86400, stale-while-revalidate=604800" reverse_proxy web:8310 } # Everything else → Next (SSR, RSC, static files in public/) handle { reverse_proxy web:8310 { health_uri / health_interval 30s health_status 2xx fail_duration 10s lb_try_duration 5s } } handle_errors { @upstream expression {http.error.status_code} >= 502 respond @upstream "DataCenterIndex is briefly unavailable ({http.error.status_code}). Retry in a moment." {http.error.status_code} } } # Prometheus scrape target (docker network only, never published) :9180 { metrics /metrics }