Beta

在自己的基础设施上运行完整的 Manyfold 栈——安装、升级、备份与运维契约。

开源版用一份 Docker Compose 文件跑起完整的栈——API、Web 工作台、管理后台。 执行环境由你自带:在自己的机器上跑 mf daemon、接入 Kubernetes 集群,或在 管理后台粘贴 sprites.dev 账号 token。

安装

git clone https://github.com/manyfold-open/manyfold.git
cd manyfold
cp .env.selfhost.example .env
# 在 .env 里填两个必填值:
#   MF_API_CRYPTO_KEY   — openssl rand -base64 32
#   MF_AUTH_SETUP_TOKEN — 首次 setup 用的一次性口令
docker compose -f docker-compose.selfhost.yml up -d --build

然后打开 http://localhost:3001/setup,输入 setup token,创建管理员账号并 选择登录方式;工作台在 http://localhost:3002。新账号落在预置的无限额 self_hosted 档位上。

警告: MF_API_CRYPTO_KEY 是长期加密主密钥,静态加密所有存储的凭据(provider key、token、登录 provider 密钥)。丢了它这些行就再也解不开,请和数据库备份放在一起保管。

跑了什么

服务镜像职责
postgrespostgres:16唯一的数据存储(没有 Redis)
api-migrateapps/api/Dockerfile 构建一次性:跑完数据库迁移即退出
apiapi-migrate 同镜像NestJS API,:2222,路径前缀 /api
webapps/web/Dockerfile 构建用户工作台,:3002
adminapps/admin/Dockerfile 构建管理后台,:3001

启动顺序与迁移

Compose 把契约写死了:api-migrate 先把迁移 journal 跑到完成,api 才启 动;web/admin 等 API 健康检查通过。迁移只进不退且幂等——重启栈不会重复 应用任何东西。你永远不需要手工执行 SQL。

健康检查

GET /api/health 返回 {"status":"ok","db":"ok",...},compose 的健康检查 探测的就是它。你自己的监控指向同一个 URL 即可。

数据与卷

所有持久数据都在 Postgres(pgdata 卷)。默认 CHAT_UPLOAD_ALLOW_DISK=true 时,聊天上传的临时字节也可能落在 API 容器磁 盘;配置 CHAT_UPLOAD_S3_* 系列变量可以把上传移到任意 S3 兼容存储(一旦运 行多个 API 容器则必须配置)。

备份与恢复

两样东西要一起备份:

docker compose -f docker-compose.selfhost.yml exec postgres \
    pg_dump -U postgres -Fc manyfold > manyfold-$(date +%Y%m%d).dump
  1. Postgres dump;
  2. 你的 MF_API_CRYPTO_KEY(没有 key 的 dump 里,凭据行是解不开的)。

恢复到新栈:先只启动 postgres,pg_restore 导入 dump,再用同一个 MF_API_CRYPTO_KEY 拉起其余服务。

升级与降级

升级 = 代码树前进并重建;新 API 启动前迁移自动应用:

git pull
docker compose -f docker-compose.selfhost.yml up -d --build

降级就是恢复备份:迁移只进不退,回退意味着 checkout 旧代码恢复升级 前的数据库 dump。

套餐与配额

一个账号的所有上限 —— 能开多少 agent、多少个 external API agent、并发沙箱、 存储、channel、automation —— 都来自 users.plan_id 指向的那一档套餐。compose 栈设置了 MF_DEFAULT_PLAN_ID=self_hosted,也就是种子里那个无限档,所以在这套栈 上创建的账号实际没有限制。

MF_DEFAULT_PLAN_ID 只在账号创建的那一刻生效,别处都不生效。在部署设置它 之前就建好的账号 —— 早于无限档的旧版本,或者从没传过这个变量的自写 compose / Kubernetes 清单 —— 会落在云端的 free 档并一直留在那里。症状是一条 提到你从没选过的套餐的配额报错:

External API limit reached (3 for Free plan)

升级后第一次启动时,API 会自动修一次:在没有 billing 模块、且 MF_DEFAULT_PLAN_ID 不是 free 的部署上,所有还停在 free 的账号会被移到该 套餐。它只跑一次,并记录在 app_settings 里,因此之后人为指定的套餐不会被覆盖。

一次性修复覆盖不到的情况 —— 修复之后新建的账号,或者需要给不同用户不同档位的 部署 —— 用 admin 控制台用户详情页的 Plan 卡片。直接查看当前归属:

docker compose -f docker-compose.selfhost.yml exec postgres \
  psql -U postgres -d manyfold -c \
  "select u.email, u.plan_id, p.max_agents_provisioned
     from users u join plans p on p.id = u.plan_id;"

想让新账号落在别的种子套餐(freehobbypluspro),在 .env 里设置 MF_SELFHOST_DEFAULT_PLAN_ID

对外服务(localhost 之外)

浏览器从别处访问这套栈时,有两件事必须改:

  • 烘焙 URL。 web 和 admin 的产物在构建期烘入 API 地址。把 MF_SELFHOST_API_URL(以及其余 MF_SELFHOST_*_URL)设成浏览器实际使用 的 URL,然后重建(up -d --build)。
  • CORS。 CORS_ORIGIN 未设置时 API 反射任意来源(localhost 下没问 题)。对外暴露 API 时,把 MF_SELFHOST_CORS_ORIGIN 设为确切的 web + admin 来源,例如 https://app.example.com,https://admin.example.com

TLS 在你的反向代理终结,再转发到三个端口;API 需要 WebSocket 转发 (daemon 连接与终端走 WS)。

邮件(SMTP)

邮件是运行时配置而不是环境变量:管理后台 → Settings → Email provider 填 SMTP host、端口和 TLS 模式,所有发信功能(注册验证、邀请)都用它。没配 provider 时,需要邮件的功能会明确提示,而不是静默失败。

删除账号

删除是管理员专属操作:管理后台 → Users → 用户详情 → Danger zone。发起删除 即刻停用账号——所有会话吊销、全部登录方式封禁、automation 暂停、keep-alive 关闭——并给用户发一封写明最终删除日期的邮件。

硬删除在宽限期(默认 30 天,MF_DELETION_GRACE_DAYS)之后执行。宽限期内管 理员可以恢复账号:登录封禁解除,但 automation 保持暂停直到手动重开。「立即 执行」在二次确认后跳过剩余等待。

到期后,后台 sweep 先拆除该用户的运行时(sandbox VM 删除、Kubernetes namespace 移除;daemon 机器是用户自己的——文件不动,只吊销 token)与 channel 平台侧注册,再删除用户行,所有用户名下的表随 ON DELETE CASCADE 一并清除。自托管跑的正是这条路径:纯 cascade 加登录闸口,没有任何计费钩 子。user_deletions 审计行(只存裸 user id,无 PII)在删除后幸存,作为持 久记录;sweep 失败会把错误记录在该行上并自动重试。

执行环境

Agent 跑在你接入的计算机上,三条路:

  • mf daemon(默认)——安装 CLI,然后在任意自有机器上 mf login --api-url https://<your-api>/api + mf setup。完整流程见 自托管部署的 CLI 与 daemon,注册细节见 本地 daemon
  • Kubernetes——在 API env 里加 kubeconfig,运行需要 gateway/cronjob 能力 的框架;集群内 exec gateway 用 apps/k8s-gateway/helm/manyfold-k8s-gateway 的 Helm chart 部署(其 README 覆盖 MF_K8S_GATEWAY_URL / MF_K8S_GATEWAY_TOKEN 的接线)。
  • sprites.dev——管理后台 → Infrastructure → Stateful sandbox accounts: 粘贴 sprites.dev 账号 token,把 coding agent 跑在租用的 VM 上;并发跟随账 号的 vendor 限额。

密钥轮换

轮换 MF_API_CRYPTO_KEY:把旧 key 移到 API_CRYPTO_KEY_V0(仅解密),新 key 设为 API_CRYPTO_KEY。在没有任何存量行仍记录 key version 0 之前保留旧 key;仓库里的 .env.example 对非 compose 部署记录了同样的流程。

这个页面有帮助吗?