gabriel / musehub public
nginx-cf.conf
138 lines 5.7 KB
Raw
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 121 days ago
1 # /etc/nginx/sites-available/musehub
2 #
3 # Cloudflare Origin Certificate configuration.
4 # Cloudflare terminates SSL at the edge. This nginx instance accepts HTTPS
5 # connections using a Cloudflare Origin Certificate.
6 #
7 # SSL mode in Cloudflare dashboard MUST be set to "Full (Strict)".
8 # No Certbot or Let's Encrypt required — the Origin Certificate is valid for 15 years.
9 #
10 # IP restriction is enforced at the EC2 security group level (inbound port 443
11 # restricted to Cloudflare IP ranges). Do not duplicate that logic here —
12 # the real_ip module replaces $remote_addr with the true client IP before
13 # allow/deny runs, which would incorrectly block legitimate Cloudflare traffic.
14 #
15 # To generate the Origin Certificate:
16 # Cloudflare Dashboard → <domain> → SSL/TLS → Origin Server → Create Certificate
17 # Choose "Generate private key and CSR with Cloudflare" → RSA (2048) → 15 years
18 # Save certificate → /etc/ssl/cloudflare/origin.pem
19 # Save private key → /etc/ssl/cloudflare/origin.key
20 # chmod 640 /etc/ssl/cloudflare/origin.key
21
22 # Restore the real client IP from the Cloudflare connecting-IP header.
23 # Without this, every request appears to come from a Cloudflare edge node.
24 # Cloudflare IP ranges: https://www.cloudflare.com/ips/
25 real_ip_header CF-Connecting-IP;
26 real_ip_recursive on;
27
28 # Cloudflare IPv4 ranges
29 set_real_ip_from 173.245.48.0/20;
30 set_real_ip_from 103.21.244.0/22;
31 set_real_ip_from 103.22.200.0/22;
32 set_real_ip_from 103.31.4.0/22;
33 set_real_ip_from 141.101.64.0/18;
34 set_real_ip_from 108.162.192.0/18;
35 set_real_ip_from 190.93.240.0/20;
36 set_real_ip_from 188.114.96.0/20;
37 set_real_ip_from 197.234.240.0/22;
38 set_real_ip_from 198.41.128.0/17;
39 set_real_ip_from 162.158.0.0/15;
40 set_real_ip_from 104.16.0.0/13;
41 set_real_ip_from 104.24.0.0/14;
42 set_real_ip_from 172.64.0.0/13;
43 set_real_ip_from 131.0.72.0/22;
44
45 # Cloudflare IPv6 ranges
46 set_real_ip_from 2400:cb00::/32;
47 set_real_ip_from 2606:4700::/32;
48 set_real_ip_from 2803:f800::/32;
49 set_real_ip_from 2405:b500::/32;
50 set_real_ip_from 2405:8100::/32;
51 set_real_ip_from 2a06:98c0::/29;
52 set_real_ip_from 2c0f:f248::/32;
53
54 # Blue-green upstream: deploy.sh rewrites /etc/nginx/musehub-active-port
55 # and runs `nginx -s reload` to switch slots atomically.
56 upstream musehub_backend {
57 include /etc/nginx/musehub-active-port;
58 }
59
60 # Redirect all plain-HTTP traffic to HTTPS — 301 (permanent, cacheable).
61 # In prod, Cloudflare enforces HTTPS at the edge, so this only fires for
62 # traffic that bypasses Cloudflare (e.g., direct-to-origin access during
63 # ops or monitoring). Belt-and-suspenders.
64 server {
65 listen 80;
66 listen [::]:80;
67 server_name DOMAIN_PLACEHOLDER;
68 return 301 https://$host$request_uri;
69 }
70
71 server {
72 listen 443 ssl http2;
73 listen [::]:443 ssl http2;
74 server_name DOMAIN_PLACEHOLDER;
75
76 ssl_certificate /etc/ssl/cloudflare/origin.pem;
77 ssl_certificate_key /etc/ssl/cloudflare/origin.key;
78
79 # Enforce TLS 1.2 minimum — disable TLS 1.0 and TLS 1.1 (both deprecated).
80 # TLS 1.3 is preferred; 1.2 retained for compatibility with older clients.
81 ssl_protocols TLSv1.2 TLSv1.3;
82 ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256;
83 ssl_prefer_server_ciphers off; # TLS 1.3 ignores this; keep off for 1.2 forward secrecy
84
85 client_max_body_size 500m;
86
87 gzip on;
88 gzip_comp_level 5;
89 gzip_vary on;
90 gzip_types text/plain text/css text/javascript application/javascript
91 application/json application/x-msgpack
92 application/x-muse-mpack application/x-muse-wire;
93
94 # Push endpoints — plain HTTPS POST, no gRPC.
95 # /push/stream — MWP pack upload (Content-Type: application/x-muse-wire).
96 # /push/objects — presigned URL requests.
97 # /push — legacy path.
98 # Buffering disabled: large packs must stream directly to hypercorn without
99 # nginx buffering the request body in memory/disk first.
100 # client_max_body_size 0: no body size cap — repos can be arbitrarily large.
101 location ~ ^/[^/]+/[^/]+/push(/stream|/objects)?$ {
102 proxy_pass http://musehub_backend;
103 proxy_http_version 1.1;
104 proxy_set_header Host $host;
105 proxy_set_header X-Real-IP $remote_addr;
106 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
107 proxy_set_header X-Forwarded-Proto $scheme;
108 proxy_read_timeout 300s;
109 proxy_send_timeout 300s;
110 proxy_request_buffering off;
111 proxy_buffering off;
112 client_max_body_size 0;
113 }
114
115 # Fetch endpoints — standard HTTP/1.1 proxy.
116 # /fetch is Phase 1 (commits + snapshots metadata).
117 # /fetch/objects is Phase 2 (raw object bytes for checkout).
118 location ~ ^/[^/]+/[^/]+/fetch(/objects)?$ {
119 proxy_pass http://musehub_backend;
120 proxy_http_version 1.1;
121 proxy_set_header Host $host;
122 proxy_set_header X-Real-IP $remote_addr;
123 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
124 proxy_set_header X-Forwarded-Proto $scheme;
125 proxy_read_timeout 300s;
126 }
127
128 # Proxy all other traffic to the MuseHub hypercorn container
129 location / {
130 proxy_pass http://musehub_backend;
131 proxy_http_version 1.1;
132 proxy_set_header Host $host;
133 proxy_set_header X-Real-IP $remote_addr;
134 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
135 proxy_set_header X-Forwarded-Proto $scheme;
136 proxy_read_timeout 60s;
137 }
138 }
File History 1 commit
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 121 days ago