From a72920d1e0660522b84c5ace9108504bfde1b5d3 Mon Sep 17 00:00:00 2001 From: ANG-Server <96008766+ANGJustinl@users.noreply.github.com> Date: Mon, 20 Jul 2026 21:07:27 +0800 Subject: [PATCH] fix: harden backend production deployment --- .env.production.example | 3 ++- deploy/nginx/whaletown-admin-v2.conf.example | 21 +++++++++++++++ deploy/nginx/whaletownend-v2.conf.example | 28 ++++++++++++++++++++ ecosystem.config.js | 1 + src/app.service.ts | 4 ++- src/core/zulip_core/zulip.config.ts | 4 +-- 6 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 deploy/nginx/whaletown-admin-v2.conf.example create mode 100644 deploy/nginx/whaletownend-v2.conf.example diff --git a/.env.production.example b/.env.production.example index 2afa744..ac006f1 100644 --- a/.env.production.example +++ b/.env.production.example @@ -46,7 +46,8 @@ ZULIP_DEGRADED_MODE_ENABLED=true ZULIP_AUTO_RECONNECT_ENABLED=true # Realtime and generated assets -WEBSOCKET_PORT=3000 +# The native WebSocket server listens separately from the REST API. +WEBSOCKET_PORT=3001 WEBSOCKET_NAMESPACE=/game ACCOUNT_ASSET_DIR=generated/account-assets SKIN_GENERATION_OUTPUT_DIR=generated/skins diff --git a/deploy/nginx/whaletown-admin-v2.conf.example b/deploy/nginx/whaletown-admin-v2.conf.example new file mode 100644 index 0000000..d17bff0 --- /dev/null +++ b/deploy/nginx/whaletown-admin-v2.conf.example @@ -0,0 +1,21 @@ +server { + listen 80; + server_name whaletownadmin.xinghangee.icu; + + root /var/www/whale-town-end-v2/client/dist; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location = /index.html { + add_header Cache-Control "no-cache"; + } + + location ~* \.(?:js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ { + expires 7d; + add_header Cache-Control "public, max-age=604800, immutable"; + try_files $uri =404; + } +} diff --git a/deploy/nginx/whaletownend-v2.conf.example b/deploy/nginx/whaletownend-v2.conf.example new file mode 100644 index 0000000..5393e8b --- /dev/null +++ b/deploy/nginx/whaletownend-v2.conf.example @@ -0,0 +1,28 @@ +server { + listen 80; + server_name whaletownend.xinghangee.icu; + + client_max_body_size 24m; + + location /game { + proxy_pass http://127.0.0.1:3001/game; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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_read_timeout 3600s; + proxy_send_timeout 3600s; + } + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + 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; + } +} diff --git a/ecosystem.config.js b/ecosystem.config.js index 5c196ac..4618fef 100644 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -2,6 +2,7 @@ module.exports = { apps: [ { name: 'whale-town-end-v2', + cwd: __dirname, script: 'dist/main.js', instances: 1, exec_mode: 'cluster', diff --git a/src/app.service.ts b/src/app.service.ts index 8ecd62c..c8277cd 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -2,6 +2,8 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { AppStatusResponseDto } from './business/shared'; +const packageJson: { version: string } = require('../package.json'); + /** * 应用服务类 * @@ -31,7 +33,7 @@ export class AppService { return { service: 'Pixel Game Server', - version: '1.1.1', + version: packageJson.version, status: 'running', timestamp: new Date().toISOString(), uptime: Math.floor((Date.now() - this.startTime) / 1000), diff --git a/src/core/zulip_core/zulip.config.ts b/src/core/zulip_core/zulip.config.ts index a8a30c0..8808196 100644 --- a/src/core/zulip_core/zulip.config.ts +++ b/src/core/zulip_core/zulip.config.ts @@ -354,7 +354,7 @@ export function validateZulipConfig( errors.push('API Key加密密钥长度必须至少32字符'); } - if (!config.server.botApiKey) { + if (!config.server.botApiKey && !config.errorHandling.degradedModeEnabled) { errors.push('生产环境必须配置Zulip机器人API Key'); } } @@ -405,4 +405,4 @@ function isValidEmail(email: string): boolean { */ export const zulipConfig = registerAs('zulip', () => { return loadZulipConfigFromEnv(); -}); \ No newline at end of file +});