安全
什么会离开你的网络(不会有)、开放了哪些端口、密钥存在哪里,以及值得做的加固项。
什么会离开你的网络
我们要求的,一样都没有。
授权验签是本机对着编进构建的公钥做签名校验。一个从没联过网的实例,行为和联网的完全一致。
你的记录、文档、附件和 agent 对话都留在你的基础设施上。没有可以关掉的遥测开关,因为根本没有遥测要发。
例外是你自己配置的对外连接——外部 S3 端点、SMTP 服务器、某个 LLM API 之类的 agent 服务商。那些是你的选择,每一个都是数据可能外流的地方。物理隔离的部署就是不配它们。
端口
| 端口 | 是否暴露 | 说明 |
|---|---|---|
3000/tcp | 是,这就是应用 | 前面放 TLS |
Postgres 5432 | 否 | 仅容器网络内 |
SeaweedFS 8333 | 是,对象存储 | 浏览器要直接取附件,必须可达——同样放在 TLS 后面 |
SeaweedFS 9333 | 否 | 仅容器网络内 |
对外两个端口,都应该放在同一个反向代理后面。对象存储之所以要发布,是因为产品把存储地址交给浏览器——上传走预签名 PUT、下载走跳转,跟云版访问 S3 是同一回事。它的访问控制靠签名 URL 和凭据,而不是靠「够不着」。
除此之外别再暴露任何端口——尤其是别为了「临时看一眼数据库」加 -p 5432:5432。用 docker compose exec postgres psql。
密钥存在哪里
| 密钥 | 位置 | 说明 |
|---|---|---|
| Postgres 密码 | .env(Compose)或 /data/.credentials(一体机) | 生成的,从不预置进镜像 |
| 对象存储密钥 | .env 和 seaweed-s3.json | 两个文件,必须一致——这正是 init.sh 负责的事 |
| 会话签名密钥 | BETTER_AUTH_SECRET | 泄漏等于任何人都能伪造一个已登录的会话 |
这些都是按部署单独生成的。两个客户拉同一个镜像不会共用任何密钥,我们也不知道你的。
/data/.credentials 权限是 600。init.sh 写出的 .env 同样是 600,backup.sh 也会把产出全部设成 600。如果你要搬这些文件,请保持权限。
最需要小心的是 BETTER_AUTH_SECRET。数据库密码泄漏了,攻击者还得能连到数据库;而会话密钥泄漏了,任何能访问登录页的地方都能用。只要它曾经出现在共享文档、聊天消息或 git 仓库里,就该轮换——代价是所有现存会话失效,而这正是轮换的意义。
最小权限
Compose 部署的应用容器以非 root 用户运行。一体机镜像在容器内以 root 运行,因为 supervisord 需要降权到 postgres 去跑数据库进程——应用本身仍然只能通过发布的那个端口访问。
如果你的规范禁止容器内 root,请用 Compose 部署。这是老实话;今天没有任何开关能让一体机变成 rootless。
值得做的加固
- 在代理层做 TLS,并把
APP_URL设成https://地址。会话 cookie 跟着APP_URL走,所以这条是安全设置,不只是外观问题。 - 在防火墙上限制谁能访问 3000 端口,只放行代理。
- 备份
.env和/data/.credentials到与生产同等防护级别的地方,不能更低。 - 把
SYSTEM_ADMIN_EMAIL设成真实且有人看的邮箱,别留默认值。 - 一旦怀疑
BETTER_AUTH_SECRET外泄就轮换,并接受所有人会被登出。
审计
Premium 会保留记录和文档的变更历史,系统管理后台可以导出审计日志。这覆盖的是「谁在 Busabase 里改了什么」,不覆盖主机层面的访问——如果有人能 docker exec 进容器,他就绕过了这里描述的所有控制,所以请把「宿主机的 shell 权限」当成真正的信任边界。