1+ events {
2+ worker_connections 1024 ;
3+ }
4+
5+ http {
6+ include /etc/nginx/mime.types ;
7+ default_type application/octet-stream ;
8+
9+ # Logging
10+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
11+ '$status $body_bytes_sent "$http_referer" '
12+ '"$http_user_agent" "$http_x_forwarded_for"' ;
13+
14+ access_log /var/log/nginx/access.log main;
15+ error_log /var/log/nginx/error.log;
16+
17+ # Gzip compression
18+ gzip on;
19+ gzip_vary on;
20+ gzip_min_length 1024 ;
21+ gzip_comp_level 6;
22+ gzip_types
23+ text/plain
24+ text/css
25+ text/xml
26+ text/javascript
27+ application/json
28+ application/javascript
29+ application/xml+rss
30+ application/atom+xml
31+ image/svg+xml;
32+
33+ # Rate limiting
34+ limit_req_zone $binary_remote_addr zone =api:10m rate=10r /s;
35+
36+ # Upstream for LCP server
37+ upstream lcp_server {
38+ server server :8989 ;
39+ keepalive 32 ;
40+ }
41+
42+ # Upstream for Dashboard service
43+ upstream lcp_dashboard {
44+ server dashboard:8080 ;
45+ keepalive 16 ;
46+ }
47+
48+ # HTTP configuration
49+ server {
50+ listen 80 ;
51+ server_name _;
52+
53+ # Security headers
54+ add_header X-Frame-Options "SAMEORIGIN" always;
55+ add_header X-Content-Type-Options "nosniff" always;
56+ add_header X-XSS-Protection "1; mode=block" always;
57+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
58+
59+ # Client max body size for file uploads
60+ client_max_body_size 100M ;
61+
62+ # Proxy settings
63+ proxy_http_version 1.1;
64+ proxy_set_header Connection "" ;
65+ proxy_set_header Host $host ;
66+ proxy_set_header X-Real-IP $remote_addr ;
67+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
68+ proxy_set_header X-Forwarded-Proto $scheme ;
69+
70+ # Health check endpoint
71+ location /health {
72+ access_log off;
73+ proxy_pass http ://lcp_server/health;
74+ proxy_connect_timeout 5s ;
75+ proxy_read_timeout 10s ;
76+ }
77+
78+ # Group 1: Public / High Traffic (Status, Register, Renew, Return)
79+ # These endpoints are frequently accessed by devices
80+ location ~ ^/( status |register|renew|return ) / {
81+ limit_req zone =api burst=50 nodelay;
82+ proxy_pass http ://lcp_server;
83+ proxy_connect_timeout 30s ;
84+ proxy_read_timeout 60s ;
85+ proxy_send_timeout 60s ;
86+ }
87+
88+ # Group 2: LCP Server API (Publications, LicenseInfo, Licenses, Revoke, Dashdata)
89+ # These endpoints are protected by Basic Auth, for use by LCP integrators,
90+ # or (dashdata) protected by JWT, for use by the dashboard UI.
91+ location ~ ^/( publications|licenseinfo|licenses|revoke|dashdata)( ?:/|$) {
92+ limit_req zone =api burst=20 nodelay;
93+ proxy_pass http ://lcp_server;
94+ proxy_connect_timeout 30s ;
95+ proxy_read_timeout 120s ;
96+ proxy_send_timeout 60s ;
97+ }
98+
99+ # Group 3: Resources (Static files)
100+ # Large files, high burst allowed for parallel downloads
101+ location /resources/ {
102+ limit_req zone =api burst=100 nodelay;
103+ proxy_pass http ://lcp_server/resources/;
104+ proxy_connect_timeout 30s ;
105+ proxy_read_timeout 300s ; # Longer timeout for large files
106+ proxy_send_timeout 300s ;
107+ }
108+
109+ # Group 4: Dashboard UI
110+ # Used by human admins via web interface
111+ # Access to the root and specific paths
112+ location ~ ^/( $|login|dashboard|assets) {
113+ limit_req zone =api burst=20 nodelay;
114+ proxy_pass http ://lcp_dashboard;
115+ proxy_connect_timeout 30s ;
116+ proxy_read_timeout 60s ;
117+ proxy_send_timeout 60s ;
118+ # So the dashboard receives correct IP information
119+ proxy_set_header Host $host ;
120+ proxy_set_header X-Real-IP $remote_addr ;
121+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
122+ proxy_set_header X-Forwarded-Proto $scheme ;
123+ }
124+
125+ # Group 4.1: Dashboard public assets
126+ location ~ ^/( favicon.ico|placeholder.svg|cleanup-localstorage.js) $ {
127+ limit_req zone =api burst=20 nodelay;
128+ proxy_pass http ://lcp_dashboard;
129+ proxy_connect_timeout 30s ;
130+ proxy_read_timeout 60s ;
131+ proxy_send_timeout 60s ;
132+ }
133+
134+ # Default proxy for all other requests (fallback)
135+ location / {
136+ return 404 ;
137+ access_log off;
138+ }
139+
140+ # Error pages
141+ error_page 502 503 504 /50x .html;
142+ location = /50x .html {
143+ root /usr/share/nginx/html;
144+ }
145+ }
146+ }
0 commit comments