# 部署 ## 用 Docker(推荐) 需要一台装了 Docker(带 Compose)的机器。云服务器建议至少 2 核、4 GB 内存,构建镜像时要用到。 ```bash git clone https://github.com/KKKKhazix/AIHOT.git myhot cd myhot node scripts/init-env.ts --llm-key <你的模型 API Key> docker compose up -d --build ``` `init-env.ts` 会生成 `.env`,填好随机密钥和管理员密码,并把密码打印一次。机器上没有 Node 的话,把 `.env.example` 复制成 `.env`,自己填 `ADMIN_PASSWORD`(至少 12 位)、`SESSION_SECRET`、`IMG_PROXY_SIGN_SECRET`、`POSTGRES_PASSWORD`(各用 `openssl rand -hex 32` 生成)和 `LLM_API_KEY`。 启动后打开 `http://服务器地址:3000`,后台在 `/admin`,用管理员密码登录。第一次启动会导入示范信源,一两分钟后开始出现内容;第一次导入的一百多条资料大约半小时处理完(每条都要预筛、评分,入选的还要写标题摘要)。 `docker compose` 会起五个容器:`db`(PostgreSQL 17)、`setup`(每次启动先跑数据库迁移和种子数据,然后退出)、`api`、`worker`(抓取、模型处理、定时任务)、`web`(网页)。 ### 在中国大陆的服务器上 - 构建时 npm 走国内镜像:`docker compose build --build-arg NPM_REGISTRY=https://registry.npmmirror.com`,然后 `docker compose up -d`。 - 拉取 Docker 镜像慢,先给 Docker 配置镜像加速。 - 海外信源抓不到时,在 `.env` 里设置 `EGRESS_PROXY_URL`:抓信源、图片和模型榜数据时走这个代理,调用模型接口不走。 - 对外提供网站服务需要先完成 ICP 备案,备案号填在 `industry/site.ts` 的 `icp`。 ### 配域名和 HTTPS 先把域名解析到服务器,然后在 `.env` 里设置: ```bash SITE_URL=https://example.com SITE_DOMAIN=example.com PORT=127.0.0.1:3000 # 3000 端口只给本机的 Caddy 用,不直接对外 TRUST_PROXY=true # 访客地址从 Caddy 转来的请求头里读 ``` 再用带 HTTPS 的方式启动,Caddy 会自动申请和续期证书: ```bash docker compose --profile https up -d --build ``` 已经有 Nginx 的话,不用 Caddy,把站点反向代理到 `http://127.0.0.1:3000`,带上 `proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;`,并在 `.env` 里设 `TRUST_PROXY=true`。`SITE_URL` 一定要写成读者实际访问的地址:生成的链接、RSS、分享图和 MCP 都用它。 MCP 默认接受 `SITE_URL` 的主机以及 `localhost`、`127.0.0.1`、`[::1]`。额外主机用 `MCP_ALLOWED_HOSTS` 配置,以逗号分隔,例如 `extra.example:8443,[2001:db8::1]`。主机名不区分大小写,IPv6 必须加方括号;可带 0–65535 的十进制端口,匹配时忽略端口。包含路径、用户信息或非法端口的配置不会生效。`127.1` 等别名需要明确列入;此配置只影响 Host 校验,不扩大浏览器 Origin 许可。 ### 更新 先按下节备份数据库。构建完成后停止旧服务,再运行迁移和新版服务: ```bash git pull docker compose build docker compose stop api worker web docker compose run --rm setup && docker compose up -d ``` 迁移成功后再启动服务;迁移失败时先查看错误,不要继续启动。使用 HTTPS 配置的站点继续保留 `--profile https`。 这次更新会修复仍引用已撤回内容的历史事件文字:先把旧文字存入后台审计,再按仍可公开的报道回退显示,不会在迁移中调用模型。旧 API 和 worker 必须在迁移前停止,避免旧任务把失效文字写回;正常关闭 worker 会等待正在处理的任务退出。非 Docker 部署也按“备份、构建、停止 API/worker/web、迁移、启动”的顺序更新。 ### 管理员会话与配置变更 会话绑定迁移排在 `0041`。此前已试用会话绑定迁移的数据库可直接升级,已有列和绑定会被保留,无需手动修改迁移记录。 会话绑定登录方式、登录时的管理员凭据或飞书身份。升级到会话绑定版本后,未绑定的旧会话需要重新登录。修改管理员密码、飞书管理员名单或会话密钥后,应重启所有 API 进程,使它们加载相同的新配置;只编辑配置文件不代表正在运行的进程已生效,混用旧代码或旧配置的进程不能提供统一撤权。 有效配置改变后,密码会话不再接受旧密码的授权,飞书会话按登录时实际取得的 union ID 或邮箱检查当前名单(两者任一仍获授权即可)。停用飞书登录应用或更换应用 ID 会使飞书会话失效;只轮换同一应用的 secret 不会使仍获授权的飞书会话退出。轮换或移除 SESSION_SECRET 会使两种会话都失效。 鉴权时确认失效的会话会被删除,恢复旧配置也不会让它复活。系统不记录全局凭据变更历史:某次配置变化若从未被进程加载,或在恢复前从未被会话检查观察到,不能据此追溯撤销会话。 ### 备份 在 `.env` 里配置 `DB_BACKUP_STORE_*`(任何 S3 兼容的对象存储),每天 04:10 自动备份到那里。一次完整备份包含同一时间戳的数据库 `.dump` 和文件 `aihot-files-*.tar.gz`:文件包保留 `uploads/` 以及仍存本地的 `feedback-screenshots/`,不包含图片缓存或本地备份目录。已经转发到飞书的图片只保留数据库中的外部引用,文件包不保存飞书上的图片。 恢复时同时取回这一对文件:使用与数据库版本兼容的 `pg_restore` 将 `.dump` 恢复到空数据库,再把文件包解压到数据目录根目录(Docker 中为 `/data`,非 Docker 使用 `AIHOT_DATA_DIR`,默认 `.data`),保留包内的子目录结构,并确保运行进程可读取这些文件。只恢复数据库不能找回仍由 `local:` 引用的反馈截图;旧备份中没有包含的文件也无法凭数据库引用恢复。 下面的手动导出只包含数据库,不包含上述附件目录: ```bash docker compose exec -T db pg_dump -U aihot aihot | gzip > myhot-$(date +%F).sql.gz ``` 数据都在三个 Docker 卷里:`db`(数据库)、`data`(上传的图片、图片缓存、本地备份)、`caddy`(证书)。`docker compose down` 不会删除它们;`docker compose down -v` 会。 ### 看日志 ```bash docker compose logs -f --tail 100 api worker web ``` 后台的“运行”页能看到每个定时任务最近的结果,“信源”页能看到每个信源的抓取状况。 ## 花多少钱 - **模型**:每条新资料至少预筛一次;可能入选的再评分两次,入选的还要写标题摘要、打标签、归组,另外还有日报和事件综述。我们用示范信源在本地试跑,第一次导入的 152 条资料一共用了大约 930 次模型调用。之后每天用多少,取决于你的信源每天更新多少条。后台“模型与评测”页能看到每一步的调用次数和输入输出 token 数。 - **付费采集**(X、公众号、Jina):按请求计费,默认不启用,填了 key 才会用。 - 所有付费服务都有每分钟、每小时、每天的调用上限(后台“设置 → 预算”),超过就暂停,不会一夜之间刷爆账单。填 0 表示立即停用这个服务。 ## 不用 Docker 需要 Node.js 24.11 以上和 PostgreSQL 16 或 17。 ```bash npm ci node scripts/init-env.ts --llm-key <你的模型 API Key> createdb myhot ``` 在 `.env` 里加上: ```bash DATABASE_URL=postgres://你的用户名@127.0.0.1:5432/myhot API_BASE_URL=http://127.0.0.1:3001 ``` 然后: ```bash node --env-file=.env scripts/migrate.ts node --env-file=.env scripts/seed.ts npm run build -w @aihot/web node --env-file=.env apps/api/src/main.ts # 接口,3001 端口 node --env-file=.env apps/worker/src/main.ts # 后台任务 cd apps/web && NODE_ENV=production node --env-file=../../.env server.ts # 网页,3000 端口 ``` 三个进程要一直运行,生产环境用 systemd 或 pm2 守护。 开发时用带热更新的方式:`npm run dev:api`、`npm run dev:worker`、`npm run dev:web`。开发时想免登录进后台,在 `.env` 里设 `DEV_AUTH_ROLE=admin`(生产环境会拒绝启动)。