10. 配置模板与检查清单
本章把常用配置和命令集中在一起。模板用于复查,第一次操作仍应阅读前面章节的解释。
1. 生产环境变量模板
文件:server/.env
NODE_ENV=production
HOST=127.0.0.1
PORT=3000
CLIENT_ORIGIN=https://airport.cxhair.cn
LOG_LEVEL=info
DB_HOST=127.0.0.1
DB_PORT=3306
DB_NAME=airportdb_training
DB_USER=airport_app
DB_PASSWORD=<强随机密码>
DB_POOL_MAX=10
DB_HEALTH_TIMEOUT_MS=2000
设置权限:
chmod 600 server/.env
git check-ignore -v server/.env
2. PM2 模板
文件:ecosystem.config.cjs
module.exports = {
apps: [
{
name: "airport-api",
cwd: "/var/www/airport-operations-explorer/server",
script: "dist/server.js",
interpreter: "node",
instances: 1,
exec_mode: "fork",
env: {
NODE_ENV: "production",
HOST: "127.0.0.1",
PORT: "3000"
},
autorestart: true,
max_memory_restart: "750M",
kill_timeout: 10000,
listen_timeout: 10000,
time: true
}
]
};
启动:
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup
3. Nginx 模板
文件:/etc/nginx/sites-available/airport.cxhair.cn
server {
listen 80;
listen [::]:80;
server_name airport.cxhair.cn;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name airport.cxhair.cn;
root /var/www/airport-operations-explorer/client/dist;
index index.html;
ssl_certificate /etc/letsencrypt/live/cxhair.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cxhair.cn/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
access_log /var/log/nginx/airport.access.log;
error_log /var/log/nginx/airport.error.log;
location /api/ {
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;
proxy_set_header X-Request-ID $request_id;
proxy_connect_timeout 5s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
location = /health {
proxy_pass http://127.0.0.1:3000/health;
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;
proxy_set_header X-Request-ID $request_id;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
}
location /assets/ {
try_files $uri =404;
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
}
}
启用和应用:
sudo ln -s /etc/nginx/sites-available/airport.cxhair.cn \
/etc/nginx/sites-enabled/airport.cxhair.cn
sudo nginx -t
sudo systemctl reload nginx
如果使用独立子域名证书,修改证书目录。如果 Nginx 版本不支持 http2 on;,按第 6 章改用旧版 listen 参数。
4. Certbot 命令
查看当前证书:
sudo certbot certificates
把 airport.cxhair.cn 加入名为 cxhair.cn 的现有证书:
sudo certbot --nginx \
--cert-name cxhair.cn \
-d cxhair.cn \
-d airport.cxhair.cn
如果原证书还有其他域名,必须全部保留在 -d 列表中。
单独签发:
sudo certbot --nginx -d airport.cxhair.cn
测试续期:
sudo certbot renew --dry-run
5. MySQL 只读账号模板
CREATE USER 'airport_app'@'127.0.0.1'
IDENTIFIED BY '<强随机密码>';
GRANT SELECT
ON airportdb_training.*
TO 'airport_app'@'127.0.0.1';
SHOW GRANTS FOR 'airport_app'@'127.0.0.1';
不要添加 INSERT、UPDATE、DELETE、CREATE、ALTER 或 DROP。
6. 第一次上线检查清单
服务器
- [ ] Node.js ≥ 22.20.0
- [ ] Git、Nginx、MySQL、MySQL Shell、PM2 已安装
- [ ] 京东云安全组只开放预期端口
- [ ] 3000 与 3306 不对公网开放
- [ ] 磁盘空间足够
数据库
- [ ]
airport-db.zip来源和校验值已记录 - [ ] 14 张表与关键结构已验证
- [ ] 日期、坐标、金额类型已抽样确认
- [ ]
airport_app只有SELECT - [ ] 后端
/health显示数据库 up
域名和证书
- [ ] A 记录指向正确公网 IP
- [ ] 证书 SAN 包含
airport.cxhair.cn - [ ] 原
cxhair.cn仍正常 - [ ]
certbot renew --dry-run成功
应用
- [ ]
server/.env权限为 600 且被 Git 忽略 - [ ]
npm ci成功 - [ ]
npm run check成功 - [ ]
server/dist/server.js存在 - [ ]
client/dist/index.html存在 - [ ] PM2 状态 online
- [ ]
pm2 save和pm2 startup已完成
Nginx
- [ ]
nginx -t成功 - [ ] HTTP 跳转 HTTPS
- [ ] 首页与 SPA 路由正常
- [ ]
/health正确代理 - [ ]
/api保留预期路径 - [ ] 静态资源缓存头正确
7. 日常更新检查清单
- [ ] 本地测试通过并已推送 commit
- [ ] 已记录服务器旧 commit 或当前 release
- [ ] 服务器 Git 工作区没有未知修改
- [ ] 已检查新环境变量和配置变化
- [ ]
npm ci成功 - [ ]
npm run check成功 - [ ] 按影响范围重启 PM2 或 reload Nginx
- [ ] 内部
/health通过 - [ ] 公网
/health通过 - [ ] 浏览器关键链路通过
- [ ] PM2 和 Nginx 日志无持续异常
8. 回滚检查清单
- [ ] 已确认上一个稳定 commit 或 release 的绝对路径
- [ ] 已判断故障位于代码、Nginx、环境变量还是数据库
- [ ] 已恢复对应版本和配置
- [ ] 后端重新构建并启动
- [ ]
nginx -t通过后才 reload - [ ] 内部与公网健康检查通过
- [ ] 业务冒烟测试通过
- [ ] 已记录故障原因和临时处理
9. 命令速查
项目
npm ci
npm run typecheck
npm test
npm run build
npm run check
PM2
pm2 status
pm2 logs airport-api
pm2 describe airport-api
pm2 restart airport-api
pm2 save
Nginx
sudo nginx -t
sudo systemctl reload nginx
systemctl status nginx --no-pager
sudo tail -f /var/log/nginx/airport.error.log
MySQL
systemctl status mysql --no-pager
mysql -h 127.0.0.1 -u airport_app -p airportdb_training
sudo mysql -e "SHOW FULL PROCESSLIST;"
HTTP 和 TLS
curl -i http://127.0.0.1:3000/health
curl -i https://airport.cxhair.cn/health
sudo certbot certificates
sudo certbot renew --dry-run
10. 术语速查
| 术语 | 含义 |
|---|---|
| A 记录 | 把域名指向 IPv4 地址 |
| SAN | 一张证书实际覆盖的域名列表 |
| HTTP-01 | CA 通过公网 HTTP 路径验证域名控制权 |
| 反向代理 | Nginx 接收客户端请求,再转发给内部 Express |
| SPA fallback | 找不到静态路径时返回 index.html 交给前端路由 |
| fork 模式 | PM2 运行单个独立 Node.js 进程 |
| 优雅关闭 | 停止接收新请求,完成清理后退出 |
| dump | 用于恢复数据库结构和数据的导出结果 |
| 连接池 | 重用有限数量的数据库连接 |
| 执行计划 | MySQL 执行 SQL 时选择的访问和连接方式 |
返回系列入口:AirportDB 从导入到上线