智慧水务管理系统 - 精河县供水工程综合管理平台

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. # ============================================================
  2. # 生产环境 Nginx 配置
  3. # 支持 HTTPS, HTTP/2, 安全 headers, 限流, WebSocket
  4. # ============================================================
  5. user nginx;
  6. worker_processes auto;
  7. worker_rlimit_nofile 65535;
  8. pid /run/nginx.pid;
  9. error_log /var/log/nginx/error.log warn;
  10. events {
  11. worker_connections 4096;
  12. multi_accept on;
  13. use epoll;
  14. }
  15. http {
  16. include /etc/nginx/mime.types;
  17. default_type application/octet-stream;
  18. # ==================== 日志格式 ====================
  19. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  20. '$status $body_bytes_sent "$http_referer" '
  21. '"$http_user_agent" "$http_x_forwarded_for" '
  22. 'rt=$request_time';
  23. log_format json escape=json '{'
  24. '"time":"$time_iso8601",'
  25. '"remote_addr":"$remote_addr",'
  26. '"request":"$request",'
  27. '"status":$status,'
  28. '"body_bytes_sent":$body_bytes_sent,'
  29. '"referer":"$http_referer",'
  30. '"user_agent":"$http_user_agent",'
  31. '"request_time":$request_time,'
  32. '"upstream_response_time":"$upstream_response_time"'
  33. '}';
  34. access_log /var/log/nginx/access.log json;
  35. # ==================== 基础优化 ====================
  36. sendfile on;
  37. tcp_nopush on;
  38. tcp_nodelay on;
  39. keepalive_timeout 65;
  40. keepalive_requests 1000;
  41. types_hash_max_size 2048;
  42. server_names_hash_bucket_size 128;
  43. client_max_body_size 50m;
  44. client_body_buffer_size 128k;
  45. # ==================== Gzip 压缩 ====================
  46. gzip on;
  47. gzip_vary on;
  48. gzip_proxied any;
  49. gzip_comp_level 6;
  50. gzip_buffers 16 8k;
  51. gzip_http_version 1.1;
  52. gzip_min_length 1024;
  53. gzip_types
  54. text/plain
  55. text/css
  56. text/xml
  57. text/javascript
  58. application/json
  59. application/javascript
  60. application/x-javascript
  61. application/xml
  62. application/xml+rss
  63. application/vnd.ms-fontobject
  64. font/opentype
  65. image/svg+xml
  66. image/x-icon;
  67. # ==================== 限流配置 ====================
  68. # 全局 API 限流: 每秒 30 个请求
  69. limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
  70. # 登录接口限流: 每分钟 10 个请求
  71. limit_req_zone $binary_remote_addr zone=login_limit:10m rate=10r/m;
  72. # WebSocket 连接数限制
  73. limit_conn_zone $binary_remote_addr zone=ws_conn_limit:10m;
  74. # ==================== 上游服务 ====================
  75. upstream gateway {
  76. server wm-gateway:8080;
  77. keepalive 32;
  78. }
  79. # ==================== HTTP → HTTPS 跳转 ====================
  80. server {
  81. listen 80;
  82. listen [::]:80;
  83. server_name _;
  84. # Let's Encrypt 验证路径
  85. location /.well-known/acme-challenge/ {
  86. root /var/www/certbot;
  87. allow all;
  88. }
  89. # 其余请求全部 301 跳转到 HTTPS
  90. location / {
  91. return 301 https://$host$request_uri;
  92. }
  93. }
  94. # ==================== HTTPS 主服务 ====================
  95. server {
  96. listen 443 ssl http2;
  97. listen [::]:443 ssl http2;
  98. server_name _;
  99. # ==================== SSL 证书 ====================
  100. # Let's Encrypt 证书路径(使用 certbot 自动生成)
  101. ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
  102. ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
  103. ssl_trusted_certificate /etc/letsencrypt/live/${DOMAIN}/chain.pem;
  104. # SSL 优化
  105. ssl_session_timeout 1d;
  106. ssl_session_cache shared:SSL:50m;
  107. ssl_session_tickets off;
  108. # SSL 协议和加密套件
  109. ssl_protocols TLSv1.2 TLSv1.3;
  110. 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:DHE-RSA-AES256-GCM-SHA384;
  111. ssl_prefer_server_ciphers off;
  112. # OCSP Stapling
  113. ssl_stapling on;
  114. ssl_stapling_verify on;
  115. resolver 8.8.8.8 8.8.4.4 valid=300s;
  116. resolver_timeout 5s;
  117. # ==================== 安全 Headers ====================
  118. add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
  119. add_header X-Frame-Options "SAMEORIGIN" always;
  120. add_header X-Content-Type-Options "nosniff" always;
  121. add_header X-XSS-Protection "1; mode=block" always;
  122. add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  123. add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
  124. add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: ws: https:; frame-ancestors 'self';" always;
  125. # 隐藏 Nginx 版本
  126. server_tokens off;
  127. # ==================== 前端静态资源 ====================
  128. root /usr/share/nginx/html;
  129. index index.html;
  130. location / {
  131. try_files $uri $uri/ /index.html;
  132. # HTML 文件不缓存(确保更新及时生效)
  133. location ~* \.html$ {
  134. expires -1;
  135. add_header Cache-Control "no-cache, no-store, must-revalidate";
  136. }
  137. }
  138. # 静态资源长期缓存(带 hash 的文件名)
  139. location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|map)$ {
  140. expires 1y;
  141. add_header Cache-Control "public, immutable";
  142. access_log off;
  143. }
  144. # ==================== API 反向代理 ====================
  145. location /api/ {
  146. limit_req zone=api_limit burst=50 nodelay;
  147. limit_req_status 429;
  148. proxy_pass http://gateway/;
  149. proxy_http_version 1.1;
  150. proxy_set_header Host $host;
  151. proxy_set_header X-Real-IP $remote_addr;
  152. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  153. proxy_set_header X-Forwarded-Proto $scheme;
  154. proxy_set_header X-Request-ID $request_id;
  155. proxy_set_header Connection "";
  156. proxy_connect_timeout 30s;
  157. proxy_send_timeout 60s;
  158. proxy_read_timeout 120s;
  159. proxy_buffering on;
  160. proxy_buffer_size 4k;
  161. proxy_buffers 8 16k;
  162. proxy_busy_buffers_size 32k;
  163. # 文件上传大小限制
  164. client_max_body_size 50m;
  165. }
  166. # 登录接口严格限流
  167. location ~* ^/api/(auth|login|oauth) {
  168. limit_req zone=login_limit burst=5 nodelay;
  169. limit_req_status 429;
  170. proxy_pass http://gateway;
  171. proxy_http_version 1.1;
  172. proxy_set_header Host $host;
  173. proxy_set_header X-Real-IP $remote_addr;
  174. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  175. proxy_set_header X-Forwarded-Proto $scheme;
  176. }
  177. # ==================== WebSocket 代理 ====================
  178. location /ws/ {
  179. limit_conn ws_conn_limit 10;
  180. proxy_pass http://gateway/ws/;
  181. proxy_http_version 1.1;
  182. proxy_set_header Upgrade $http_upgrade;
  183. proxy_set_header Connection "upgrade";
  184. proxy_set_header Host $host;
  185. proxy_set_header X-Real-IP $remote_addr;
  186. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  187. proxy_set_header X-Forwarded-Proto $scheme;
  188. proxy_connect_timeout 7d;
  189. proxy_send_timeout 7d;
  190. proxy_read_timeout 7d;
  191. }
  192. # ==================== MQTT over WebSocket ====================
  193. location /mqtt {
  194. proxy_pass http://wm-emqx:8083/mqtt;
  195. proxy_http_version 1.1;
  196. proxy_set_header Upgrade $http_upgrade;
  197. proxy_set_header Connection "upgrade";
  198. proxy_set_header Host $host;
  199. proxy_read_timeout 3600s;
  200. }
  201. # ==================== GeoServer GIS 代理 ====================
  202. location /geoserver/ {
  203. proxy_pass http://wm-geoserver:8080/geoserver/;
  204. proxy_set_header Host $host;
  205. proxy_set_header X-Real-IP $remote_addr;
  206. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  207. proxy_set_header X-Forwarded-Proto $scheme;
  208. # GIS 数据可能较大
  209. client_max_body_size 100m;
  210. proxy_read_timeout 300s;
  211. }
  212. # ==================== MinIO 对象存储代理 ====================
  213. location /minio/ {
  214. proxy_pass http://wm-minio:9000/;
  215. proxy_set_header Host $host;
  216. proxy_set_header X-Real-IP $remote_addr;
  217. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  218. proxy_set_header X-Forwarded-Proto $scheme;
  219. client_max_body_size 500m;
  220. }
  221. # ==================== 健康检查 ====================
  222. location /health {
  223. access_log off;
  224. return 200 '{"status":"UP"}';
  225. add_header Content-Type application/json;
  226. }
  227. # 禁止访问隐藏文件
  228. location ~ /\. {
  229. deny all;
  230. access_log off;
  231. log_not_found off;
  232. }
  233. # 错误页面
  234. error_page 404 /index.html;
  235. error_page 500 502 503 504 /50x.html;
  236. location = /50x.html {
  237. root /usr/share/nginx/html;
  238. internal;
  239. }
  240. }
  241. }