-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnginx.conf
More file actions
352 lines (296 loc) · 12.4 KB
/
nginx.conf
File metadata and controls
352 lines (296 loc) · 12.4 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# prod-nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 10240;
multi_accept on;
}
http {
## Basic settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
## Log format
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time ua="$upstream_addr" us="$upstream_status" ut="$upstream_response_time"';
access_log /var/log/nginx/access.log main;
## Gzip (safe defaults)
gzip on;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
## SSL / TLS settings (placeholders - replace certs and adjust to policy)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
## Rate limiting (tweak values per traffic profile)
# Limit for API (per IP)
limit_req_zone $binary_remote_addr zone=api_req_zone:10m rate=600r/m;
# Limit for webhooks/events ingestion (use more restrictive if needed)
limit_req_zone $binary_remote_addr zone=events_req_zone:10m rate=300r/m;
## Upstreams - replace with your backends (IP:PORT or unix:/path.sock)
upstream domain_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # marketing / docs landing
keepalive 32;
}
upstream docs_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # docs.domain.com
keepalive 32;
}
upstream status_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # status.domain.com
keepalive 16;
}
upstream console_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # console.domain.com (MFA enforced upstream)
keepalive 32;
}
upstream auth_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # auth.domain.com (OAuth2/OIDC)
keepalive 32;
}
upstream api_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # api.domain.com (public API v1)
keepalive 64;
}
upstream events_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # events.domain.com (webhook delivery)
keepalive 16;
}
upstream sandbox_api_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # sandbox.api.domain.com
keepalive 32;
}
upstream sandbox_auth_backend {
server UPSTREAM_HOST:UPSTREAM_PORT; # sandbox.auth.domain.com
keepalive 16;
}
## Global proxy settings (used by all server blocks)
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
# Common headers to pass to upstream
map $http_upgrade $connection_upgrade {
default "upgrade";
'' "";
}
# Security headers (adjust CSP for your app)
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Permissions-Policy "geolocation=(), microphone=()" always;
# Minimal CSP - adapt to your assets & inline policies
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' ; style-src 'self' 'unsafe-inline'; img-src 'self' data:;" always;
## HTTP -> HTTPS redirect server
server {
listen 80;
listen [::]:80;
server_name domain.com docs.domain.com status.domain.com console.domain.com auth.domain.com api.domain.com events.domain.com sandbox.api.domain.com sandbox.auth.domain.com;
# Optionally respond to ACME challenges if using Certbot (letsencrypt)
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
try_files $uri =404;
}
# Redirect all other traffic to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
## Example HTTPS server block pattern (marketing / docs landing)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name domain.com;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # replace
# HSTS - be careful: only enable after verifying HTTPS works correctly
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Root / static handling - offload to backend or serve static
location / {
proxy_pass http://domain_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## docs.domain.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name docs.domain.com;
ssl_certificate /etc/letsencrypt/live/docs.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/docs.domain.com/privkey.pem; # replace
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
location / {
proxy_pass http://docs_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## status.domain.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name status.domain.com;
ssl_certificate /etc/letsencrypt/live/status.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/status.domain.com/privkey.pem; # replace
# Keep the status page uncached by CDNs if needed - override caching
location / {
proxy_pass http://status_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## console.domain.com (partner/admin console)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name console.domain.com;
ssl_certificate /etc/letsencrypt/live/console.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/console.domain.com/privkey.pem; # replace
# It is strongly recommended the console enforces MFA at the application or IdP layer.
# Example: if you want nginx to validate session tokens with your auth server, use auth_request.
# (Below is a commented example - implement /auth_validate endpoint on auth_backend if you want this.)
#
# location = /_auth {
# internal;
# proxy_pass http://auth_backend/validate; # your token/session validation endpoint
# proxy_pass_request_body off;
# proxy_set_header Content-Length "";
# proxy_set_header X-Original-URI $request_uri;
# }
#
# location / {
# auth_request /_auth;
# error_page 401 = @error401;
# proxy_pass http://console_backend;
# ...
# }
location / {
proxy_pass http://console_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## auth.domain.com (OAuth2 / OIDC Authorization Server)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name auth.domain.com;
ssl_certificate /etc/letsencrypt/live/auth.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/auth.domain.com/privkey.pem; # replace
location / {
proxy_pass http://auth_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# If tokens are large, consider increasing buffer sizes for headers
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
}
## api.domain.com (Public API v1) - rate-limited, tuned buffers
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.domain.com;
ssl_certificate /etc/letsencrypt/live/api.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/api.domain.com/privkey.pem; # replace
# CORS preflight passthrough for API - adapt to allowed origins (don't use '*')
location / {
limit_req zone=api_req_zone burst=100 nodelay;
proxy_pass http://api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
}
# Optional: health check path
location /health {
proxy_pass http://api_backend/health;
proxy_set_header Host $host;
}
}
## events.domain.com (webhooks / outbound delivery) - rate-limited
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name events.domain.com;
ssl_certificate /etc/letsencrypt/live/events.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/events.domain.com/privkey.pem; # replace
# If this is only used for outbound webhook delivery (no inbound clients), ensure only your systems can access it.
# Otherwise, apply rate limiting to avoid abuse.
location / {
limit_req zone=events_req_zone burst=50 nodelay;
proxy_pass http://events_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## sandbox.api.domain.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sandbox.api.domain.com;
ssl_certificate /etc/letsencrypt/live/sandbox.api.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/sandbox.api.domain.com/privkey.pem; # replace
location / {
proxy_pass http://sandbox_api_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## sandbox.auth.domain.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sandbox.auth.domain.com;
ssl_certificate /etc/letsencrypt/live/sandbox.auth.domain.com/fullchain.pem; # replace
ssl_certificate_key /etc/letsencrypt/live/sandbox.auth.domain.com/privkey.pem; # replace
location / {
proxy_pass http://sandbox_auth_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## Fallback/default server (optional)
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
return 444; # drop unknown host traffic
}
}