feat(docker): provide verified-header proxy profiles for self-hosted clones
CI / check (push) Failing after 1m45s
CI / deploy (push) Skipped
CI / publish-container (push) Skipped

This commit is contained in:
Simo committed 2026-09-13 20:15:10 +02:00
1 parent fe34d4ac93
commit 9a2d73a6f6
6 files changed
+404

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
# Opt in through COMPOSE_FILE in the clone's .env; see docs/operations/docker-installation.md.
# The base service uses Linux host networking: bind the process, do not add ports.
services:
cms:
environment:
HOSTNAME: 127.0.0.1
PORT: "3002"
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3002/api/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
@@ -0,0 +1,43 @@
# Include at nginx http scope (for example /etc/nginx/conf.d/cms.conf).
# Mode: browsers connect directly to this nginx, on the CMS Docker host.
# Replace EVERY hotel.example and both certificate paths before nginx -t.
# Requires ngx_http_realip_module: $realip_remote_addr keeps the socket peer
# even when an unrelated global real_ip configuration rewrites $remote_addr.
server {
listen 80;
listen [::]:80;
server_name hotel.example;
if ($host != hotel.example) { return 444; }
return 308 https://hotel.example$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name hotel.example;
if ($host != hotel.example) { return 444; }
ssl_certificate /etc/letsencrypt/live/hotel.example/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hotel.example/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Studio's authenticated attachment endpoints accept at most 52 MiB.
# This ingress allowance includes multipart overhead; application caps remain.
client_max_body_size 64m;
location / {
proxy_pass http://127.0.0.1:3002;
proxy_http_version 1.1;
proxy_set_header Host hotel.example;
proxy_set_header X-Forwarded-Host hotel.example;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-For $realip_remote_addr;
proxy_set_header X-Real-IP $realip_remote_addr;
proxy_set_header CF-Connecting-IP "";
proxy_set_header X-Real-Client-IP "";
proxy_set_header Forwarded "";
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 300s;
proxy_cache off;
}
}
@@ -0,0 +1,51 @@
# ALTERNATIVE to nginx-direct.example.conf; never enable both for the same host.
# Remote edge -> TLS -> this nginx on the CMS host -> loopback CMS.
# Replace hotel.example/certificate paths and BOTH occurrences of 203.0.113.10/32.
# The example peer is reserved documentation space, so it permits no real edge.
# Requires ngx_http_realip_module. The remote edge MUST overwrite X-Forwarded-For
# with one verified client IP and enforce the public HTTPS/Host configuration.
geo $realip_remote_addr $cms_trusted_edge {
default 0;
203.0.113.10/32 1;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name hotel.example;
if ($host != hotel.example) { return 444; }
if ($cms_trusted_edge = 0) { return 403; }
ssl_certificate /etc/letsencrypt/live/hotel.example/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hotel.example/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 64m;
set_real_ip_from 203.0.113.10/32;
real_ip_header X-Forwarded-For;
real_ip_recursive off;
location / {
proxy_pass http://127.0.0.1:3002;
proxy_http_version 1.1;
proxy_set_header Host hotel.example;
proxy_set_header X-Forwarded-Host hotel.example;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header CF-Connecting-IP "";
proxy_set_header X-Real-Client-IP "";
proxy_set_header Forwarded "";
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 300s;
proxy_cache off;
}
}
# Cloudflare variant: use this same restricted-edge mode, NOT the direct mode.
# Replace the documentation peer in BOTH geo/set_real_ip_from lists with the
# current verified Cloudflare IPv4 AND IPv6 CIDRs, then change real_ip_header to
# CF-Connecting-IP. Use Full (strict) TLS and review authenticated origin pulls.
# CF-Connecting-IP is still removed before forwarding to the CMS: nginx sends
# only its normalized, trusted result in X-Forwarded-For and X-Real-IP.