Add PM2 deployment support

This commit is contained in:
lofyer
2026-08-24 17:59:49 +08:00
parent 5ff80caf7e
commit 63bbbac922
16 changed files with 450 additions and 55 deletions
+73 -2
View File
@@ -2,12 +2,23 @@
## 配置
Docker Compose 从项目根目录 `.env` 读取以下值:
Docker Compose、直接运行的 Node 服务和管理员 CLI 都会从项目根目录
`.env` 读取配置。已由 shell、PM2 或系统服务注入的同名变量优先。设置
`ENV_FILE=/path/to/file` 可改用其他配置文件;显式指定的文件不存在时,
进程会拒绝启动。
| 变量 | 说明 | 默认值 |
| --- | --- | --- |
| `NODE_ENV` | 运行环境:`development`、`test` 或 `production` | `development` |
| `HOST` | Node 服务监听地址 | `127.0.0.1` |
| `PORT` | Node 服务监听端口 | `3000` |
| `PUBLIC_ORIGIN` | production 对外 HTTPS origin | production 必填 |
| `DATA_DIRECTORY` | SQLite 与附件目录 | `./data` |
| `FEEDBACK_DOMAIN` | Caddy 申请证书并对外服务的域名 | 必填 |
| `APP_SECRET` | 会话、IP 和安装标识 digest 的主 secret,至少 32 字符 | 必填 |
| `APP_SECRET` | 会话、IP 和安装标识 digest 的主 secret,不限制长度 | 自动生成并持久化 |
| `INITIAL_ADMIN_EMAIL` | 数据库为空时创建的初始管理员邮箱 | 可选 |
| `INITIAL_ADMIN_PASSWORD` | 初始管理员密码,12–128 字符 | 可选 |
| `INITIAL_ADMIN_NAME` | 初始管理员显示名 | `Administrator` |
| `SESSION_TTL_HOURS` | 管理员会话时长 | `12` |
| `PUBLIC_RATE_LIMIT_PER_HOUR` | 单 IP 每小时公开提交上限 | `20` |
| `PUBLIC_INSTALLATION_LIMIT_PER_HOUR` | 单安装实例每小时公开提交上限 | `8` |
@@ -16,10 +27,70 @@ Docker Compose 从项目根目录 `.env` 读取以下值:
`.env` 包含 secret,不得提交到 Git 或复制到工单、聊天和日志中。建议在
密码管理器中保存一份加密副本,并在主机上执行 `chmod 600 .env`。
未设置或留空 `APP_SECRET` 时,应用会生成随机值并以权限 `0600` 保存到
`DATA_DIRECTORY/.app-secret`。后续启动会复用该文件。应将此文件与
SQLite 和附件一起备份,否则恢复后现有管理员会话将失效。
`INITIAL_ADMIN_EMAIL` 和 `INITIAL_ADMIN_PASSWORD` 必须同时设置。应用仅在
管理员表为空时创建该账号,后续重启不会同步或重置密码。确认初始账号
可登录后,应从 `.env` 删除 `INITIAL_ADMIN_PASSWORD`。
Compose 会从 `FEEDBACK_DOMAIN` 生成
`PUBLIC_ORIGIN=https://FEEDBACK_DOMAIN`。直接运行 Node 服务时,
production 环境仍必须显式提供只含 HTTPS origin 的 `PUBLIC_ORIGIN`。
## PM2 部署
没有 Docker 时,可通过 Node.js 24+ 和 PM2 启动服务。先安装依赖并准备
配置:
```sh
npm ci
npm install --global pm2
cp .env.example .env
```
复制后的示例配置可以直接以 development 模式启动,初始账号为
`admin@example.com`,示例密码仅用于首次本地运行。公网部署前必须修改
初始管理员凭据并配置 production 对外地址:
```dotenv
NODE_ENV=production
HOST=127.0.0.1
PORT=3000
PUBLIC_ORIGIN=https://feedback.example.com
DATA_DIRECTORY=./data
APP_SECRET=
INITIAL_ADMIN_EMAIL=admin@example.com
INITIAL_ADMIN_PASSWORD=replace-with-a-secure-password
INITIAL_ADMIN_NAME=Administrator
```
构建并启动:
```sh
npm run pm2:start
pm2 save
pm2 status
curl --fail "http://127.0.0.1:3000/health"
```
登录成功后删除 `.env` 中的 `INITIAL_ADMIN_PASSWORD`,再执行
`npm run pm2:reload`。数据库已有管理员时,即使保留这些变量也不会重置
账号,但不应长期把明文密码保存在主机配置中。
`ecosystem.config.cjs` 固定使用单进程 fork 模式,避免多个进程同时管理单机
SQLite 和本地附件。更新代码后执行:
```sh
npm ci
npm run pm2:reload
pm2 logs product-issue --lines 100
```
PM2 只管理 Node 进程,不提供 TLS。公网部署仍须在前方配置 Caddy、Nginx
或等效 HTTPS 反向代理,并且只让代理访问监听端口。
## 网络与 TLS
- DNS A/AAAA 记录必须指向主机。