# SoundGame — 公网部署 线上地址: 个人简历站 首页「深入了解」与页脚有入口。本机 Nginx 同时托管这两个站点:根域名仍是简历站,游戏走独立子域名,互不覆盖。 ## 方案摘要 公网**只托管静态文件**,不启动 `web/server/server.js`。 原因:用户系统是家庭局域网玩具级认证(PIN 明文、token 永不过期、无速率限制), 见 `web/server/README.md`。游戏本身不依赖 API——未登录时设置和进度写在浏览器 `localStorage`。大厅在 `https://*.xiangsilian.com` 下会隐藏登录面板 (`web/index.html` 里的 `PUBLIC_STATIC`)。本地 `./web/serve.sh` 仍显示登录。 ``` 手机浏览器 │ HTTPS ▼ Nginx 80/443 ├── xiangsilian.com → /var/www/xiangsilian (简历站,已有) └── game.xiangsilian.com → /var/www/soundgame (本游戏) ``` 证书是同一张 Let’s Encrypt(SAN:`xiangsilian.com`、`www`、`game`),webroot 验证目录 `/var/www/letsencrypt`。`certbot.timer` 负责续期。 ## 本机路径 | 用途 | 路径 | |---|---| | 源码 | `/home/ubuntu/SoundGame/web/` | | 线上静态根 | `/var/www/soundgame/`(`www-data` 可读;家目录 `750`,Nginx 读不了源码目录) | | Nginx 站点 | `/etc/nginx/sites-available/soundgame.conf` → `sites-enabled/` | | 简历站静态根 | `/var/www/xiangsilian/` | | 简历站源码 | `/home/ubuntu/xiangsilian/` | 未发布:`harness/`、`*/gen/`、`*/test/`、`server/`、`template/`,以及 `*.py` / `*.md` / `*.sh`。Android 工程、`tools/`、研究文档也不在线上。 ## 更新游戏文件 源码有改动后,在本机执行: ```bash sudo rsync -a --delete \ --exclude harness/ --exclude gen/ --exclude test/ \ --exclude server/ --exclude template/ \ --exclude '*.py' --exclude '*.md' --exclude '*.sh' \ /home/ubuntu/SoundGame/web/ /var/www/soundgame/ sudo chown -R www-data:www-data /var/www/soundgame ``` 静态文件即时生效,不必 reload Nginx。改了 `soundgame.conf` 才需要: ```bash sudo nginx -t && sudo systemctl reload nginx ``` ## 从零再搭一遍(本服务器已完成,仅作记录) 前置:DNSPod 增加 A 记录 `game` → 本机公网 IP(当前 `118.89.233.55`)。 `xiangsilian.com` / `www` 的 Nginx + 证书应已存在。 1. 按上一节 rsync 到 `/var/www/soundgame`。 2. 先写 **仅 HTTP** 的 `server_name game.xiangsilian.com`,包含 `location /.well-known/acme-challenge/`(`root /var/www/letsencrypt`), `nginx -t` 后 reload。此时还没有该主机名的证书,不能先开 443。 3. 扩证书(会改同一张 live 证书,现站 HTTPS 不停): ```bash sudo certbot certonly --webroot -w /var/www/letsencrypt \ -d xiangsilian.com -d www.xiangsilian.com -d game.xiangsilian.com \ --expand --non-interactive --agree-tos ``` 扩完后确认 `/etc/letsencrypt/renewal/xiangsilian.com.conf` 的 `[[webroot_map]]` 含三个域名(certbot 有时只留下新加的那条,缺了续期会掉名)。 4. 换成完整配置(HTTP 301 → HTTPS,443 指 `/var/www/soundgame`),reload。 当前线上配置见下一节。 ## Nginx 配置(`/etc/nginx/sites-available/soundgame.conf`) ```nginx # game.xiangsilian.com — SoundGame HTML5 static site server { listen 80; listen [::]:80; server_name game.xiangsilian.com; location /.well-known/acme-challenge/ { root /var/www/letsencrypt; } location / { return 301 https://game.xiangsilian.com$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name game.xiangsilian.com; ssl_certificate /etc/letsencrypt/live/xiangsilian.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/xiangsilian.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; root /var/www/soundgame; index index.html; add_header X-Content-Type-Options nosniff; add_header Referrer-Policy strict-origin-when-cross-origin; location ~ /\. { deny all; } location / { try_files $uri $uri/ =404; } location ~* \.(ogg|m4a|mp3|wav|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 7d; add_header Cache-Control "public"; add_header X-Content-Type-Options nosniff; access_log off; } location ~* \.(js|css)$ { expires 1d; add_header Cache-Control "public"; add_header X-Content-Type-Options nosniff; } } ``` 音频走 Nginx 原生 Range(`Accept-Ranges`),不要反代到 Node。系统 `mime.types` 已有 `audio/ogg` 与 `audio/x-m4a`。 ## 以后若要开放用户系统 不要把 `server.js` 绑到 `0.0.0.0`。至少做到:监听 `127.0.0.1`、Nginx 只反代 `/api/`、加 `limit_req`、PIN 改哈希、token 设过期。在此之前保持静态-only。 ## 冒烟 ```bash curl -sI https://game.xiangsilian.com/ # 200 curl -sI http://game.xiangsilian.com/ # 301 → https curl -sI https://game.xiangsilian.com/rpg/ # 200 curl -sI https://game.xiangsilian.com/api/login # 404 curl -sI -H 'Range: bytes=0-1023' \ https://game.xiangsilian.com/rpg/audio/bgm/boss.ogg # 206 curl -sI https://xiangsilian.com/ # 200,简历站仍在 ``` 真机:手机浏览器打开大厅 → 点进一款游戏 → 「轻触开始」后应出声(建议耳机)。 iOS 用 m4a,Android 用 ogg。