在本机自托管
本指南搭建一套单主机自托管的 Chorus:一个应用容器加一个 PostgreSQL 17 容器,由
Chorus 仓库中 deploy/self-host/ 目录下的
Docker Compose 文件启动。install.sh 的本地安装流程(Chorus 0.22.2 及以后)负责准备镜像、
写入受保护的配置,并保存一个用于后续重新部署的包装脚本。你还可以为局域网添加一个自签名
HTTPS 入口,或通过你自己创建的 Cloudflare Named Tunnel 对外发布。
完整的上游参考是仓库中的 docs/SELF_HOST.zh.md(英文:docs/SELF_HOST.md)。本页将其
浓缩为大多数安装需要的步骤。
何时选择这种方式
Section titled “何时选择这种方式”| 你想要… | 使用 |
|---|---|
| 自己试用 Chorus,不用 Docker | 内置 PGlite 的 npm 包:快速开始 |
| 在自己的 Linux 或 macOS 主机上长期运行、局域网可访问、使用真正的 PostgreSQL | 本指南 |
| 围绕发布的镜像编写自己的 Compose 文件 | 使用 Docker 部署 |
| 多实例、托管的 PostgreSQL 与 Redis,或部署到 AWS | 生产环境部署 |
这是单实例部署。Redis 被刻意禁用(REDIS_URL 为空),实时更新使用内存内投递,只适用于
一个应用容器。
- 一台装有 Docker Engine 的 Linux 主机,或运行 Linux 容器的 macOS + Docker Desktop。
Docker Compose v2,且支持
up --wait。用docker version和docker compose version检查。 - Bash 3.2 或更新版本、OpenSSL(或 LibreSSL)和 curl。可选的脚本化登录检查需要
jq。 服务器不需要 Node.js、pnpm 或 AWS CLI。 - 一份包含
deploy/self-host/的 Chorus 仓库检出。 - 在 macOS 上先启动 Docker Desktop,并允许它共享检出目录以及私有配置和备份路径。
- 能访问你的镜像仓库(Tunnel 模式还需要能访问 Cloudflare)。
用 install.sh 安装
Section titled “用 install.sh 安装”在检出目录的根目录运行安装器,并选择本地目标:
bash install.sh --target local不带 --target 运行 bash install.sh 会先询问 aws 还是 local,默认仍是 AWS。在终端中,
本地安装接着会询问:
- 镜像来源:
pull(默认)下载已有的发布镜像;build用当前检出的Dockerfile(production目标)编译。 - 选择
pull时,镜像标签或摘要,例如chorusaidlc/chorus-app:vX.Y.Z。隐式标签或latest会被拒绝。build 模式默认把镜像标记为chorus-local:<project>(即chorus-local:chorus-local)。 - 普通登录的邮箱和密码,以及独立的超级管理员邮箱和密码。密码输入隐藏,且要求输入两次。
- Also enable self-signed LAN HTTPS? [y/N]。默认不启用,见下文「可选:自签名局域网 HTTPS」。
两个密码都必须是单行且至少 8 字节;由于 bcrypt 的限制,超级管理员密码最多 72 字节。你无需
自己生成 bcrypt 哈希:安装器会拉取辅助镜像 httpd:2.4-alpine,在一个无网络的一次性容器中用
htpasswd(cost 12)计算哈希,密码通过 stdin 传入,而不是作为参数。
脚本化安装时,把每个密码各写成一行,放在检出目录之外的单独文件中(目录权限 0700,
文件权限 0600)。安装器会拒绝符号链接和检出目录内的文件。以下两种形式二选一:
# 拉取已有的发布镜像bash install.sh --target local --image-source pull \ --image chorusaidlc/chorus-app:vX.Y.Z --project chorus-local \ --email owner@example.com --admin-email admin@example.com \ --password-file /absolute/private/path/login-password \ --admin-password-file /absolute/private/path/admin-password \ --port 18637 --non-interactive# 把当前检出编译为 chorus-local:chorus-localbash install.sh --target local --image-source build \ --project chorus-local --email owner@example.com --admin-email admin@example.com \ --password-file /absolute/private/path/login-password \ --admin-password-file /absolute/private/path/admin-password \ --port 18637 --non-interactive加上 --dry-run(并省略两个密码文件选项)只打印计划,不计算哈希、不调用 Docker、不写文件。
在非终端输入下,安装器从不等待回答,缺少必需值会直接失败。运行 bash install.sh --help 查看
选项摘要。
| 选项 | 等价环境变量 | 默认值 |
|---|---|---|
--target local | CHORUS_INSTALL_TARGET=local | aws |
--image-source pull|build | CHORUS_IMAGE_SOURCE | pull |
--image | CHORUS_IMAGE | pull 时必需;build 时为 chorus-local:<project> |
--project | CHORUS_LOCAL_PROJECT | chorus-local |
--port | CHORUS_PORT | 18637 |
--email、--admin-email | DEFAULT_USER、SUPER_ADMIN_EMAIL | 无 |
--password-file、--admin-password-file | DEFAULT_PASSWORD、SUPER_ADMIN_PASSWORD | 无 |
--non-interactive、--dry-run | CHORUS_INSTALL_NONINTERACTIVE=1、CHORUS_INSTALL_DRY_RUN=1 | 关闭 |
命令行选项优先于环境变量,密码文件优先于密码变量。没有任何选项接受命令行上的明文密码。
安装会创建什么
Section titled “安装会创建什么”| 路径 | 内容 |
|---|---|
~/.config/chorus-self-host/<project>/ | 新建的私有目录,权限 0700。 |
…/<project>/env | 权限 0600。镜像引用(CHORUS_IMAGE、POSTGRES_IMAGE=postgres:17-alpine)、随机的 POSTGRES_PASSWORD、DEFAULT_USER 及明文的普通 DEFAULT_PASSWORD、CHORUS_PORT、SUPER_ADMIN_EMAIL,以及仅保存 bcrypt 哈希的 SUPER_ADMIN_PASSWORD_HASH。请把它当作机密。 |
…/<project>/lan-tls/、…/<project>/lan-https.yml | 仅在选择局域网 HTTPS 时创建。 |
检出目录中的 default_deploy_local.sh | 权限 0700,不含机密的重新部署包装脚本。CHORUS_DEPLOY_CONFIG 可指定其他路径,其父目录必须已存在。 |
安装流程只用于全新安装。如果该项目的私有目录、包装脚本文件,或任何 Docker 容器、卷、网络 已经存在,安装器会拒绝并且不做任何改动;它从不轮换密码,也不复用数据库。启动失败时,新项目的 容器和配置会保留下来以便排查。
NEXTAUTH_SECRET 留空,应用会在 app-data 卷中的 /app/data/.secret 生成签名密钥。请保留
这个卷:丢失它会让所有人退出登录。
打开 Chorus 并登录
Section titled “打开 Chorus 并登录”安装完成时会打印访问地址、私有 env 文件的位置、重新部署命令,以及一条限定在该项目内的
docker compose … stop 命令。
- 在主机上:
http://localhost:18637(或你的--port)。 - 在其他局域网设备上:
http://<主机局域网 IP>:18637。请使用主机的真实地址,而不是0.0.0.0。 - 使用你设置的普通登录账号登录。
/admin面板使用独立的超级管理员账号。
内置邮箱/密码登录是引导和演示用途,不是团队 SSO。团队使用时,请在管理面板中按公司配置 OIDC, 参见运维自托管的 Chorus。局域网明文 HTTP 不会加密凭据或会话, 而且浏览器在不安全的 HTTP 源上不提供 OIDC 客户端做 PKCE 所需的 Web Crypto API,因此 OIDC 需要 HTTPS。
用保存的包装脚本重新部署
Section titled “用保存的包装脚本重新部署”只有在本地模式且包装脚本会加载全部必要覆盖文件时,才用它代替重新安装。若使用隧道模式、oidc-only.yml 或其他自定义覆盖文件,请先准备目标应用镜像,再使用完整的 Compose 调用;包装脚本会遗漏这些设置。
bash ./default_deploy_local.sh --dry-runbash ./default_deploy_local.sh包装脚本只接受 --dry-run,并用保存的项目名、私有目录和镜像来源调用
deploy/self-host/deploy-local.sh。每次运行:
- 重新编译当前检出(build 模式),或拉取保存的
CHORUS_IMAGE(pull 模式)。要把 pull 模式的 实例升级到新版本,请先修改私有 env 中的CHORUS_IMAGE。 - 仅当本地缺少 保存的
POSTGRES_IMAGE时才拉取它。这绝不是数据库大版本升级。 - 当私有目录中存在
https.yml、pg17.yml、lan-https.yml这些私有覆盖文件时自动加入,并在 存在该附加项时拉取lan-https镜像。 - 执行
docker compose … up -d --pull never --wait。它复用相同的项目、卷和凭据,从不执行down、删除卷或轮换凭据。
--dry-run 会校验保存的镜像引用并列出将使用的 Compose 文件,不调用 Docker。其他私有覆盖文件
(例如 oidc-only.yml)不会被自动发现,每次都要用显式的 Compose 命令加上它们。
手动运行 Compose 命令
Section titled “手动运行 Compose 命令”查看日志、停止或重启时,请使用与包装脚本相同的项目、env 文件和 Compose 文件。在 Bash 中:
REPO=/absolute/path/to/ChorusPROJECT=chorus-localENV_FILE="$HOME/.config/chorus-self-host/$PROJECT/env"dc() { docker compose --project-name "$PROJECT" --env-file "$ENV_FILE" \ -f "$REPO/deploy/self-host/compose.yml" \ -f "$REPO/deploy/self-host/compose.local.yml" "$@"}dc psdc logs --tail 100 app db如果你的安装使用了 lan-https.yml 等私有覆盖文件,请在 "$@" 之前追加
-f "$HOME/.config/chorus-self-host/$PROJECT/lan-https.yml"(及其他覆盖文件)。用
dc config --quiet 校验配置,不要运行未脱敏的 docker compose config,它会打印密码。
可选:自签名局域网 HTTPS
Section titled “可选:自签名局域网 HTTPS”HTTPS 是可选的,密码登录并不需要它。可以在安装时对 HTTPS 提示回答 yes 并输入客户端将使用的 主机名或 IPv4 地址,或者使用选项启用:
bash install.sh --target local --image-source build --https-host 192.0.2.10把示例地址换成主机真实的局域网 IP,或一个已经解析到该主机的 DNS 名称。--https-port 可修改默认
端口 18638(必须与 HTTP 端口不同)。--https 会开启主机名提示;非交互安装需要 --https-host
或 CHORUS_HTTPS_HOST。--no-https 会覆盖环境变量中的选择。IPv6 字面量、通配符名称和 URL
都会被拒绝。
它暴露了什么。 安装会添加一个 lan-https Nginx 服务,与应用和数据库在同一次 Compose up
中启动。它监听 0.0.0.0:18638,并在内部 Compose 网络上转发到 http://app:8637。它会把响应
Cookie 标记为 Secure,保留转发头和 WebSocket 升级头,并关闭代理缓冲以便 Server-Sent Events
流式传输。原有的 HTTP 监听仍然可用,Cloudflare Tunnel 的源站仍是内部 HTTP。安装不会修改 DNS、
路由器或防火墙规则,请把两个端口都限制在可信网络内。
TLS 材料存放在哪里。 安装会生成一个有效期 30 天、SAN 中包含所选主机的 RSA 自签名证书,保存为
私有目录中的 lan-tls/server.crt 和 lan-tls/server.key。它们的路径和 HTTPS 端口保存在私有
env 中(CHORUS_TLS_CERT_FILE、CHORUS_TLS_KEY_FILE、CHORUS_HTTPS_PORT),并且
compose.lan-https.yml 会被复制为私有的 lan-https.yml。这些文件以只读方式挂载,缺失文件会
导致启动失败。重新部署会复用它们,从不重新生成证书。
要通过该入口使用 OIDC,请在身份提供方注册精确的回调地址(例如
https://<主机局域网 IP>:18638/login/callback),并保留已有的回调。Cookie 按主机而非端口隔离,
所以同一主机上的 HTTP 和 HTTPS 共享会话;登录后请始终使用 HTTPS。
续期。 在 30 天到期前,或主机名/IP 变化后,先备份 TLS 文件,把带匹配 SAN 的新证书和私钥写入
相同路径,然后用你完整的 Compose 命令只重建代理:up -d --no-deps --force-recreate lan-https。
单纯重启 Nginx 不会加载替换后的文件。
停用。 用你完整的 Compose 命令先执行 stop lan-https,再执行 rm -f lan-https;之后再把私有
lan-https.yml 移出私有目录。该文件不存在后,包装脚本就不再包含代理。请保留证书以便回滚。
为已有安装添加。 不要重新运行安装。用 OpenSSL 在检出目录外生成证书和私钥,在私有 env 中设置
CHORUS_TLS_CERT_FILE、CHORUS_TLS_KEY_FILE 和 CHORUS_HTTPS_PORT,把
deploy/self-host/compose.lan-https.yml 复制为私有目录中的 lan-https.yml,然后运行包装脚本
(它也会重新部署应用)。
可选:Cloudflare Named Tunnel
Section titled “可选:Cloudflare Named Tunnel”要在不开放主机端口的情况下通过 HTTPS 对外发布,请用 compose.tunnel.yml 替代
compose.local.yml。不要同时使用这两种主模式;局域网 HTTPS 附加项仍可单独叠加。Tunnel 不发布
任何主机端口,TLS 在 Cloudflare 终止。
Cloudflare 账号、域名和远程管理的 Named Tunnel 都由你自己提供,Chorus 不会代为创建。在
Cloudflare 控制台中添加一个发布的应用主机名,并把其源站服务设为 http://app:8637,
而不是 localhost。
- 把连接器 token 保存到一个私有文件(例如私有目录中的
tunnel-token,在0700目录内设为0444)。不要把它放进 shell 参数或历史记录。 - 在私有 env 中,把
CHORUS_PUBLIC_URL设为外部https://源(不带结尾斜杠),把CLOUDFLARED_IMAGE设为固定版本的cloudflare/cloudflared(2025.4.0 或更新),把CLOUDFLARED_TOKEN_FILE设为 token 文件的绝对路径。 - 保留当前完整的
dc定义以便回滚。准备隧道调用方式,先验证并且只拉取连接器镜像,再停止本地栈。复用已安装的应用和数据库镜像,因此未发布到仓库的本地构建也适用。
保留数据库卷及认证覆盖文件。以下示例按需加入 pg17.yml 和 oidc-only.yml,最后应用隧道策略。不要自动带入 https.yml 或 lan-https.yml。请检查其他自定义覆盖文件,单独保留必要的非暴露配置,不要带入主机端口映射或覆盖隧道地址、Cookie 策略。
PRIVATE_DIR="$HOME/.config/chorus-self-host/$PROJECT"tunnel_dc() { local compose_files=(-f "$REPO/deploy/self-host/compose.yml") local override for override in pg17.yml oidc-only.yml; do if [ -f "$PRIVATE_DIR/$override" ]; then compose_files+=(-f "$PRIVATE_DIR/$override") fi done compose_files+=(-f "$REPO/deploy/self-host/compose.tunnel.yml") docker compose --project-name "$PROJECT" --env-file "$ENV_FILE" \ "${compose_files[@]}" "$@"}tunnel_dc config --quiet &&tunnel_dc pull cloudflared &&dc down &&tunnel_dc up -d --pull never --wait成功切换后,让后续所有 dc 命令使用隧道调用方式:
dc() { tunnel_dc "$@"; }连接器运行 tunnel --no-autoupdate run --token-file /run/secrets/tunnel_token,该覆盖文件把
NEXTAUTH_URL 设为 CHORUS_PUBLIC_URL,并设置 COOKIE_SECURE=true。保存的包装脚本始终使用
compose.local.yml,因此 tunnel 模式的栈请用上面这条显式的 dc 命令管理。要切换回来,先用
tunnel 版本的函数执行 down,再用本地版本执行 up。绝不要使用 down -v。
Cloudflare 侧:
- 对整个 Chorus 主机名绕过缓存,至少要对已认证页面、登录路由、
/api/*、/api/mcp、/api/events和/api/events/notifications绕过缓存。 - 检查 Server-Sent Events 在完整链路上是逐条到达的。
- 交互式的 Cloudflare Access 质询会把 API、MCP 和守护进程请求变成 HTML 或重定向。Chorus 的 API Key 本身无法通过 Access。
- 妥善保管 tunnel token;一旦泄露,请在 Cloudflare 中轮换。
实例:局域网 HTTPS 加独立的 Cloudflare 连接器
Section titled “实例:局域网 HTTPS 加独立的 Cloudflare 连接器”高级方案:保留局域网访问并通过独立连接器发布
一种已在单台主机上验证过的布局:局域网继续使用本地模式,同时通过 Cloudflare 发布同一个应用,而不切换到
compose.tunnel.yml。它运行四个容器:
| 容器 | 来源 | 作用 |
|---|---|---|
<project>-app-1 | compose.yml + compose.local.yml | Chorus,主机端口 18637(容器内 8637) |
<project>-db-1 | compose.yml(迁移后再加私有 pg17.yml) | PostgreSQL 17,仅内部可访问 |
<project>-lan-https-1 | 私有局域网 HTTPS 覆盖文件 | Nginx,主机端口 18638,转发到 http://app:8637 |
chorus-cloudflare | 单独的 docker run | Cloudflare 连接器,把公网主机名转发到 http://app:8637 |
安装器将 env、lan-https.yml 和 lan-tls/ 放在私有目录中。保存的 default_deploy_local.sh 默认位于仓库检出目录,除非通过 CHORUS_DEPLOY_CONFIG 指定其他位置。迁移后可通过私有 pg17.yml 选择新数据库卷。手动 dc 函数必须包含与包装脚本相同的覆盖文件。
搭建步骤:
- 按上文以本地模式安装并启用局域网 HTTPS,确认
http://<host>:18637/api/health和https://<host>:18638/api/health都正常。 - 在 Cloudflare 控制台中,把隧道的已发布主机名的源服务设为
http://app:8637。 - 发布前,在私有
lan-https.yml的app.environment中把NEXTAUTH_URL设为公网https://地址,并设置COOKIE_SECURE: "true",保留原有代理服务。若使用oidc-only.yml或其他自定义覆盖文件,请用完整的 Compose 调用重新部署;否则用包装脚本。先验证局域网 HTTPS 登录。 - 按隧道一节把连接器令牌保存到私有文件,再把连接器接入该栈的默认网络
<project>_default:
docker run -d --name chorus-cloudflare --restart unless-stopped \ --network "${PROJECT}_default" \ -v "$HOME/.config/chorus-self-host/$PROJECT/tunnel-token:/run/secrets/tunnel_token:ro" \ cloudflare/cloudflared:<pinned-version> \ tunnel --no-autoupdate run --token-file /run/secrets/tunnel_token采用这种布局前请了解其取舍:
- 连接器不归 Compose 管理。 包装脚本、
dc ps和dc down都不会管理它。执行dc down前,先运行docker stop chorus-cloudflare和docker rm chorus-cloudflare;down会删除<project>_default, 所以dc up之后要重新执行上面的docker run。只停止连接器只会让公网主机名下线,局域网访问不受影响。 - 不要把令牌放在命令行里。
--token <value>参数在docker inspect和进程列表中可见。请使用 cloudflared 2025.4.0 或更新版本的--token-file;如果令牌曾以内联方式传入,请在 Cloudflare 中轮换它。 - 主机端口仍然对外发布。 与隧道模式不同,
18637和18638仍在0.0.0.0上开放,请用能识别 Docker 的防火墙规则把它们限制在可信网络内。 - 必须使用 HTTPS 登录。 连接器绕过局域网代理,因此应用本身必须设置 Secure Cookie。上述覆盖会禁用
18637上的纯 HTTP 登录;请使用局域网 HTTPS 或公网 HTTPS 地址。 - 隧道一节中关于 Cloudflare 缓存、Server-Sent Events 和 Access 的说明同样适用。
PostgreSQL 17 与已有的 PostgreSQL 16 卷
Section titled “PostgreSQL 17 与已有的 PostgreSQL 16 卷”新安装使用 postgres:17-alpine,deploy/self-host/ 和仓库根目录的 docker-compose.yml
都是如此。
仓库提供了一个显式的离线迁移脚本 deploy/self-host/migrate-pg16-to-17.sh,完整说明见
docs/POSTGRES_UPGRADE.zh.md(英文:docs/POSTGRES_UPGRADE.md)。概括如下:
- 预先拉取
postgres:16-alpine和postgres:17-alpine;脚本本身不拉取镜像。 - 备份部署配置和应用签名材料。停止所有写入方(应用、CLI、开发服务器)以及源数据库。
对安装器管理的实例,用它完整的 Compose 命令停止
app和db;不要重新运行安装器。 - 对该项目的数据库容器执行
docker inspect找出源卷名,并把数据库角色密码(不是 Chorus 的 登录密码)写入一个权限为0600的私有文件。 - 先带
--dry-run运行脚本,再去掉它正式运行。备份目录必须尚不存在,目标名称必须未被占用:
bash deploy/self-host/migrate-pg16-to-17.sh \ --source-volume YOUR_OLD_PG16_VOLUME --target-volume chorus-pg17-migrated \ --backup-dir /absolute/private/path/pg17-backup \ --password-file /absolute/private/path/db-password --writers-stopped --dry-run脚本从不以可写方式挂载原卷。它把已停止的 PG16 集群复制到一个工作卷,从隔离的 PG16 容器导出,
恢复到一个新的 PG17 卷,并比较 public 表的行数和序列状态。无论成功还是失败,它都会保留所有卷
和备份;它只支持默认布局、使用 public schema 的单个数据库。
- 对安装器管理的实例,在私有目录中用私有
pg17.yml指向新卷,并在私有 env 中设置POSTGRES_IMAGE=postgres:17-alpine:
volumes: db-data: external: true name: chorus-pg17-migrated先用相同的应用镜像验证数据库。之后包装脚本每次运行都会包含 pg17.yml。在产生新写入之前回滚,
需要同时选回原卷和 PG16 镜像;一旦 PG17 已接受写入,切回去就会丢失这些写入。
-
dc ps显示app和db(启用时还有lan-https)处于健康状态。 -
健康检查端点报告数据库状态:
本地模式使用你选择的端口;Tunnel 模式不发布主机端口,请使用公开的 HTTPS 地址。相应设置
BASE_URL:Terminal window BASE_URL=http://localhost:18637curl --fail --silent --show-error "$BASE_URL/api/health"预期返回
status: ok和database: connected。 -
在浏览器中登录,创建一个临时项目和想法,刷新后确认数据仍在。通过 HTTPS 访问时,检查会话 Cookie 带有 Secure 和 HttpOnly。
-
用超级管理员账号登录
/admin。 -
可选:创建一个测试 Agent API Key,在客户端把
CHORUS_URL设为该地址后运行chorus mcp whoami,参见chorus 命令行工具。 -
运行
dc up -d --force-recreate app,确认你仍处于登录状态。这证明app-data中的签名密钥 得到了持久化。
数据库位于 db-data,/app/data(包括生成的签名密钥)位于 app-data。dc down 会保留这两个卷;
dc down -v 会销毁它们。在维护窗口内,停止应用、做逻辑导出、归档 app-data,并复制私有 env:
( set -euo pipefail umask 077 BACKUP_DIR="$HOME/chorus-backups/$PROJECT/$(date -u +%Y%m%dT%H%M%SZ)" mkdir -p "$BACKUP_DIR" chmod 700 "$BACKUP_DIR" dc stop app dc exec -T db pg_dump -U chorus -d chorus -Fc > "$BACKUP_DIR/database.dump" dc run --rm --no-deps -T --entrypoint tar app \ -C /app/data -czf - . > "$BACKUP_DIR/app-data.tar.gz" cp "$ENV_FILE" "$BACKUP_DIR/env" dc start app)子 Shell 会在任何一步失败时停止;不完整的目录不是有效备份。请排查并重新完成备份后再升级。如果应用仍处于停止状态,处理错误后再主动运行 dc start app。同时保留 Compose 覆盖文件和镜像版本,确保恢复时沿用原来的认证及存储配置。
保持备份目录私有(0700),发送到其他主机前先加密。请把恢复演练做在一个新的 Compose 项目
和端口上,绝不要覆盖原项目。上游指南详细介绍了恢复演练。
| 现象 | 检查 |
|---|---|
| 安装提示私有目录、脚本或项目资源已存在 | 这是已有安装。运行它的包装脚本;若要另起实例,请换一个新的 --project 和 CHORUS_DEPLOY_CONFIG。 |
| Compose 报告缺少变量 | 使用私有的绝对路径 --env-file,保持 DEFAULT_USER 和 DEFAULT_PASSWORD 非空,并只选择一种主模式。 |
| 端口被占用 | 换一个 --port 或 --https-port。不要通过删除已有卷来解决。 |
切换到 PostgreSQL 17 后 db 立即失败 | 卷里仍是 PG16 数据。保留它,并按上文迁移。 |
| 修改 env 后数据库认证失败 | 已有的卷保留旧的角色密码;修改 POSTGRES_PASSWORD 并不会改变它。 |
| HTTP 登录立即失败 | 本地模式需要 COOKIE_SECURE=false(来自 compose.local.yml);把它设为 true 的私有 https.yml 会阻止局域网 HTTP 登录。 |
| 一个月后浏览器拒绝 HTTPS 入口 | 30 天证书已过期;续期后重建 lan-https。 |
OIDC 报 redirect_uri_mismatch | 在身份提供方注册包含端口的精确 HTTPS 回调地址。 |
| 重建后用户被登出 | app-data 卷或显式的 NEXTAUTH_SECRET 发生了变化。 |
| Tunnel 健康但主机名报错 | 检查发布的主机名、http://app:8637 源站、应用健康状态以及 token 文件是否可读。 |
| CLI 从 tunnel 主机名收到 HTML | Access 质询、缓存或 Worker 规则,或 /api/mcp 地址错误。 |
排查时绝不要分享 env 文件、token、Cookie 或未脱敏的日志,也不要运行全主机范围的 Docker prune 命令。