Text · 6089 bytes Raw Blame History
1 worker_processes auto;
2 worker_rlimit_nofile 65535;
3
4 events {
5 worker_connections 4096;
6 use epoll;
7 multi_accept on;
8 }
9
10 http {
11 charset utf-8;
12 sendfile on;
13 tcp_nopush on;
14 tcp_nodelay on;
15 server_tokens off;
16 log_not_found off;
17 types_hash_max_size 4096;
18 client_max_body_size 1G;
19
20 # MIME types
21 include /etc/nginx/mime.types;
22 default_type application/octet-stream;
23
24 # Logging
25 access_log /var/log/nginx/access.log;
26 error_log /var/log/nginx/error.log warn;
27
28 # Rate limiting
29 limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
30 limit_req_zone $binary_remote_addr zone=upload:10m rate=2r/s;
31
32 # SSL Configuration
33 ssl_protocols TLSv1.2 TLSv1.3;
34 ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
35 ssl_prefer_server_ciphers off;
36 ssl_session_cache shared:SSL:10m;
37 ssl_session_timeout 1d;
38
39 # Security headers
40 add_header X-Frame-Options "SAMEORIGIN" always;
41 add_header X-Content-Type-Options "nosniff" always;
42 add_header X-XSS-Protection "1; mode=block" always;
43 add_header Referrer-Policy "no-referrer-when-downgrade" always;
44 add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
45
46 # Gzip compression
47 gzip on;
48 gzip_vary on;
49 gzip_proxied any;
50 gzip_comp_level 6;
51 gzip_types
52 text/plain
53 text/css
54 text/xml
55 text/javascript
56 application/json
57 application/javascript
58 application/xml+rss
59 application/atom+xml
60 image/svg+xml;
61
62 # Upstream backends
63 upstream web_backend {
64 least_conn;
65 server web-server:3000 max_fails=3 fail_timeout=30s;
66 keepalive 32;
67 }
68
69 upstream zephyrfs_node {
70 server zephyrfs-node:8080 max_fails=3 fail_timeout=30s;
71 keepalive 16;
72 }
73
74 # HTTP to HTTPS redirect
75 server {
76 listen 80;
77 server_name _;
78 return 301 https://$host$request_uri;
79 }
80
81 # Main HTTPS server
82 server {
83 listen 443 ssl http2;
84 server_name _;
85
86 # SSL certificates
87 ssl_certificate /etc/nginx/ssl/cert.pem;
88 ssl_certificate_key /etc/nginx/ssl/key.pem;
89
90 # Root and index
91 root /var/www/html;
92 index index.html;
93
94 # Health check endpoint
95 location /health {
96 access_log off;
97 return 200 "healthy\n";
98 add_header Content-Type text/plain;
99 }
100
101 # API proxy with rate limiting
102 location /api/ {
103 limit_req zone=api burst=20 nodelay;
104
105 proxy_pass http://web_backend;
106 proxy_http_version 1.1;
107 proxy_set_header Upgrade $http_upgrade;
108 proxy_set_header Connection "upgrade";
109 proxy_set_header Host $host;
110 proxy_set_header X-Real-IP $remote_addr;
111 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
112 proxy_set_header X-Forwarded-Proto $scheme;
113
114 # Timeouts
115 proxy_connect_timeout 60s;
116 proxy_send_timeout 60s;
117 proxy_read_timeout 60s;
118
119 # Buffer settings
120 proxy_buffering on;
121 proxy_buffer_size 4k;
122 proxy_buffers 8 4k;
123 }
124
125 # File upload endpoint with special handling
126 location /api/files/upload {
127 limit_req zone=upload burst=5 nodelay;
128
129 client_max_body_size 1G;
130 client_body_timeout 300s;
131
132 proxy_pass http://web_backend;
133 proxy_http_version 1.1;
134 proxy_set_header Host $host;
135 proxy_set_header X-Real-IP $remote_addr;
136 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
137 proxy_set_header X-Forwarded-Proto $scheme;
138
139 # Extended timeouts for large uploads
140 proxy_connect_timeout 300s;
141 proxy_send_timeout 300s;
142 proxy_read_timeout 300s;
143
144 # Disable buffering for streaming uploads
145 proxy_request_buffering off;
146 proxy_buffering off;
147 }
148
149 # WebSocket support
150 location /ws {
151 proxy_pass http://web_backend;
152 proxy_http_version 1.1;
153 proxy_set_header Upgrade $http_upgrade;
154 proxy_set_header Connection "upgrade";
155 proxy_set_header Host $host;
156 proxy_set_header X-Real-IP $remote_addr;
157 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
158 proxy_set_header X-Forwarded-Proto $scheme;
159
160 # WebSocket specific settings
161 proxy_read_timeout 86400s;
162 proxy_send_timeout 86400s;
163 }
164
165 # Direct ZephyrFS node access (internal only)
166 location /node/ {
167 internal;
168 proxy_pass http://zephyrfs_node/;
169 proxy_http_version 1.1;
170 proxy_set_header Host $host;
171 proxy_set_header X-Real-IP $remote_addr;
172 }
173
174 # Static files with caching
175 location / {
176 try_files $uri $uri/ /index.html;
177
178 # Cache static assets
179 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
180 expires 1y;
181 add_header Cache-Control "public, immutable";
182 add_header Vary "Accept-Encoding";
183 }
184
185 # Cache HTML with shorter expiry
186 location ~* \.html$ {
187 expires 1h;
188 add_header Cache-Control "public, no-cache, must-revalidate";
189 }
190 }
191
192 # Monitoring endpoints
193 location /nginx_status {
194 stub_status on;
195 access_log off;
196 allow 127.0.0.1;
197 allow 10.0.0.0/8;
198 allow 172.16.0.0/12;
199 allow 192.168.0.0/16;
200 deny all;
201 }
202
203 # Security - deny access to sensitive files
204 location ~ /\. {
205 deny all;
206 }
207
208 location ~ ~$ {
209 deny all;
210 }
211 }
212 }