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 管理部署生命周期。
运行哪些服务
| 服务 | 作用 |
|---|---|
caddy | 反向代理 + 自动 HTTPS。唯一发布端口(80/443)的服务。 |
erp、mes | Carbon 应用,从仓库构建。通过 erp.<域名> 和 mes.<域名> 访问。 |
postgres | Supabase Postgres,首次启动时调优(pg_stat_statements、连接限制)。 |
gotrue、postgrest、realtime、storage、meta、kong | Supabase 数据平面,由 Kong 在 api.<域名> 前置。 |
studio | Supabase Studio(数据库管理),默认仅内部访问。 |
edge-runtime | Supabase Edge Functions。 |
redis | 缓存、限流、会话状态。 |
inngest | 两个应用的后台任务。 |
前置条件
| 要求 | 详情 |
|---|---|
| VPS | Ubuntu 22.04+,运行栈需 ≥ 4 GB 内存。在主机上构建镜像需要 约 8 GB。请增加 swap 或在别处构建。 |
| Docker | 带 Compose 插件的 Docker Engine。 |
| OpenSSL | deploy.sh 使用 openssl 生成密钥和 Supabase JWT 密钥(通常已安装)。 |
| DNS | 指向该 VPS 的 ERP、MES 和 Supabase 主机 A/AAAA 记录(Let's Encrypt 需要)。 |
| 仓库 | 在 VPS 上检出的 Carbon 仓库(默认 /opt/carbon)。 |
安装
加固主机(推荐)
为 SSH 和 80/443 端口配置防火墙、fail2ban、swap 和自动安全更新。
cd /opt/carbon/contrib/deploying/simple-docker-caddy
sudo ./scripts/harden.sh设置运维密钥
init 会为部署创建占位值。请替换为生产密钥。Resend 密钥为空时 ERP 不会启动。
./deploy.sh secret resend_api_key re_xxxxxxxx
./deploy.sh secret smtp_password 'your-smtp-password'验证
./deploy.sh status
curl -fsS https://$ERP_HOST/health # -> 200
curl -fsS https://$MES_HOST/health # -> 200首次启动会应用所有迁移。schema 就绪前应用可能反复重启。用 ./deploy.sh logs erp 监控进度。
密钥如何工作
Swarm 把密钥挂载到 /run/secrets/,而镜像读取环境变量。入口脚本在启动服务前把每个 __SECRET_NAME__ 占位符替换为对应密钥文件的内容。
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 由你提供。
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 访问数据库:
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 密钥在使用期间不可变,因此请先停止栈:
./deploy.sh down
./deploy.sh secret <name> 'new-value'
./deploy.sh 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 未公开暴露(或位于基本认证之后)。