Docker + Caddy

使用 Docker Swarm 和自动 HTTPS 的 Caddy 反向代理,在单台 Linux VPS 上自托管完整 Carbon 栈。

在单台 Linux VPS 上以单节点 Docker Swarm 运行 Carbon。栈包含 ERP、MES、Supabase、Redis 和 Inngest,前置 Caddy TLS 反向代理。只有 80 和 443 端口对外开放;其他服务使用私有覆盖网络。敏感值使用 Docker Swarm 密钥。

部署文件位于 contrib/deploying/simple-docker-caddy。使用 deploy.sh 管理部署生命周期。

TIP

不想自己运维?

Carbon Cloud 管理基础设施、备份、升级和可用性。只有当 Carbon 必须运行在你控制的设施上时才自托管。

运行哪些服务

服务作用
caddy反向代理 + 自动 HTTPS。唯一发布端口(80/443)的服务。
erp、mesCarbon 应用,从仓库构建。通过 erp.<域名> 和 mes.<域名> 访问。
postgresSupabase Postgres,首次启动时调优(pg_stat_statements、连接限制)。
gotrue、postgrest、realtime、storage、meta、kongSupabase 数据平面,由 Kong 在 api.<域名> 前置。
studioSupabase Studio(数据库管理),默认仅内部访问。
edge-runtimeSupabase Edge Functions。
redis缓存、限流、会话状态。
inngest两个应用的后台任务。

前置条件

要求详情
VPSUbuntu 22.04+,运行栈需 ≥ 4 GB 内存。在主机上构建镜像需要 约 8 GB。请增加 swap 或在别处构建。
Docker带 Compose 插件的 Docker Engine。
OpenSSLdeploy.sh 使用 openssl 生成密钥和 Supabase JWT 密钥(通常已安装)。
DNS指向该 VPS 的 ERP、MES 和 Supabase 主机 A/AAAA 记录(Let's Encrypt 需要)。
仓库在 VPS 上检出的 Carbon 仓库(默认 /opt/carbon)。

安装

加固主机(推荐)

为 SSH 和 80/443 端口配置防火墙、fail2ban、swap 和自动安全更新。

bash
cd /opt/carbon/contrib/deploying/simple-docker-caddy
sudo ./scripts/harden.sh

初始化

启动 Swarm、生成 Docker 密钥,并从模板创建 .env。

bash
./deploy.sh init

配置

编辑 .env:设置 CARBON_REPO、你的 *_HOST / *_URL 主机名、ACME_EMAIL 和 SMTP 设置。

bash
$EDITOR .env

设置运维密钥

init 会为部署创建占位值。请替换为生产密钥。Resend 密钥为空时 ERP 不会启动。

bash
./deploy.sh secret resend_api_key re_xxxxxxxx
./deploy.sh secret smtp_password 'your-smtp-password'

部署

构建镜像、部署栈、等待数据库并应用迁移。

bash
./deploy.sh up

验证

bash
./deploy.sh status
curl -fsS https://$ERP_HOST/health   # -> 200
curl -fsS https://$MES_HOST/health   # -> 200
NOTE

首次启动会应用所有迁移。schema 就绪前应用可能反复重启。用 ./deploy.sh logs erp 监控进度。

密钥如何工作

Swarm 把密钥挂载到 /run/secrets/,而镜像读取环境变量。入口脚本在启动服务前把每个 __SECRET_NAME__ 占位符替换为对应密钥文件的内容。

yaml
PGRST_DB_URI: postgres://authenticator:__POSTGRES_PASSWORD__@postgres:5432/postgres
GOTRUE_JWT_SECRET: __JWT_SECRET__

deploy.sh init 会生成 postgres_password、session_secret、Inngest 密钥以及 Supabase 三件套(jwt_secret、anon_key、service_role_key)。resend_api_key 和 smtp_password 由你提供。

HEADS UP

inngest_signing_key 必须是纯十六进制。自托管 Inngest 服务器拒绝 signkey- 前缀。init 会正确生成。

运维

任务命令
状态./deploy.sh status
跟踪日志./deploy.sh logs <服务>(例如 erp、caddy)
更新到新版本git pull && ./deploy.sh build && ./deploy.sh deploy && ./deploy.sh migrate
备份./scripts/backup.sh(Postgres 转储 + 存储归档)
停止./deploy.sh down(加 --volumes 同时清空数据)

数据库管理。 Studio 默认仅内部访问。通过 SSH 访问数据库:

bash
docker exec -it $(docker ps -qf name=carbon_postgres.1) psql -U postgres

.1 可避免同时匹配 carbon_postgrest。也可以设置 STUDIO_HOST 并取消 Caddyfile 中 studio 块的注释,把 Studio 暴露在 HTTP 基本认证之后。

数据库事件。 Postgres 会把事件(Webhook、工作流和搜索背后的队列,部件嵌入,生产订单通知)直接投递到 Inngest,URL 由 ./deploy.sh migrate 在 erp 服务运行后写入数据库。如果 migrate 警告无法连接,请在栈启动后再次运行。轮换 inngest_event_key 后也要再次运行 ./deploy.sh migrate。

轮换密钥。 Swarm 密钥在使用期间不可变,因此请先停止栈:

bash
./deploy.sh down
./deploy.sh secret <name> 'new-value'
./deploy.sh up
HEADS UP

为 backup.sh 设置定时任务,把输出复制到异地,并启用云厂商卷快照。只存放在 VPS 上的备份无法防止主机丢失。

生产检查清单

  • 主机已加固(harden.sh):防火墙仅限 SSH + 80/443、fail2ban、swap。
  • HTTPS 正常签发——查看 ./deploy.sh logs caddy。
  • 设置了真实的 resend_api_key 和可用的 SMTP(Auth 发送邀请和魔法链接需要 SMTP)。
  • Postgres 调优与机器规格匹配(.env 中的 PG_* 值)。
  • 备份已定时并异地存放。
  • Studio 未公开暴露(或位于基本认证之后)。

完整配置面参见环境变量,AWS 方案参见 AWS + SST。