-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCaddyfile
More file actions
70 lines (67 loc) · 3.17 KB
/
Copy pathCaddyfile
File metadata and controls
70 lines (67 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# GW2Analytics — Caddy reverse-proxy for self-hosted deployment.
#
# === PRODUCTION SETUP (3 steps) ===
#
# 1. Replace `{placeholder.tld}` with your real domain below.
# Example: if your domain is `gw2a.example.com`:
# - `api.{placeholder.tld}` → `api.gw2a.example.com`
# - `{placeholder.tld}` → `gw2a.example.com`
#
# 2. Ensure DNS A/AAAA records point to this server's public IP:
# api.gw2a.example.com → <server-ip>
# gw2a.example.com → <server-ip>
#
# 3. Caddy auto-obtains Let's Encrypt TLS certificates on first
# request. No manual cert setup needed — Caddy handles renewal
# automatically. Ports 80 + 443 must be reachable from the
# internet for the ACME HTTP-01 challenge.
#
# For internal/VPN-only deployments (no public DNS), use Caddy's
# `tls internal` directive instead of Let's Encrypt:
# api.internal.local { tls internal ... }
#
# Security policy (plan 008, v0.10.x hardening):
# - Strict-Transport-Security: 2-year HSTS with includeSubDomains + preload.
# Operator MUST verify HTTPS stability before any future HSTS change
# (a 2-year lock + broken HTTPS = bricked subdomain).
# - frame-ancestors 'none': clickjacking defense for the web dashboard.
# - Content-Security-Policy: 'self' + 'unsafe-inline' for styles (matches
# Next.js SSR output style tags). Future inline `<script>` injections
# require explicit relaxation — coordinate with plan 011 (Next.js
# `headers()` fallback) to keep these two layers consistent.
# - X-Content-Type-Options: nosniff (MIME-type confusion defense).
# - Referrer-Policy: strict-origin-when-cross-origin (anti-tracking for
# cross-origin + same-origin pass-through for dashboard analytics).
#
# Layered defense: this file ships the headers at the reverse-proxy layer.
# The same headers are also emitted at the Next.js application layer via
# web/next.config.ts (plan 011) — a misconfigured proxy still has the app
# layer as a safety net. KEEP THE TWO FILES SYNCHRONIZED.
(common) {
encode gzip zstd
header {
Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
}
}
api.{placeholder.tld} {
import common
# v0.10.25: cap request body size at the same 100 MiB the API
# accepts for .zevtc uploads. Caddy returns 413 before the bytes
# reach the backend, giving defense-in-depth against OOM.
# Uses ``100MiB`` (binary, 104,857,600 bytes) to match the API's
# ``MAX_UPLOAD_SIZE_BYTES`` default of ``100 * 1024 * 1024``.
# The decimal ``100MB`` (100,000,000 bytes) would be 4.85% smaller
# than the API cap and create a proxy-layer false-reject for
# valid .zevtc uploads between 100,000,000 and 104,857,600 bytes.
request_body {
max_size 100MiB
}
reverse_proxy localhost:8000
}
{placeholder.tld} {
import common
reverse_proxy localhost:3000
}