Supabase配置与反向代理
自托管 Supabase 平台的完整部署与运维,涵盖 Docker 容器管理、Caddy 反向代理配置、安全认证修复和 REST API 接入。
概述
该项目是在云服务器上自托管 Supabase 全套服务的部署与运维实践。涉及13个 Docker 容器的镜像管理、Caddy 反向代理配置(包括 /pg 路径转发到 Kong 网关的关键配置)、Studio Dashboard 安全认证修复,以及 REST API 的 CRUD 接入指南。
项目还包括将所有 Supabase 容器镜像推送到 Azure Container Registry (externalacr.azurecr.io) 的镜像同步工作,生成了替换为 ACR 地址的 docker-compose.yml,并建立了自动化同步脚本 scripts/mirror_supabase_images.sh。
在安全层面,发现并修复了 Studio Dashboard 无认证访问的严重问题——根因是 Caddy 直连 Studio 绕过了 Kong 网关,而 DASHBOARD_USERNAME/PASSWORD 实际上是给 Kong 用的。最终通过在 Caddy 层添加 basic auth 解决。
关键点
- 容器版本管理:13个容器全部保持最新版 (2026.02.16),包括 Studio、Auth v2.186.0、PostgREST v14.5 等
- Caddy 反向代理关键配置:
/pg路径必须转发给 Kong (8000端口),不能用handle_path(会 strip 掉/pg前缀导致 Kong 404) - 安全修复:Studio 自身无认证功能,必须在 Caddy 层加 basic auth 保护
- RLS 全量开启:37张表全部开启 Row Level Security
- Logto 集成评估:评估了 Logto OIDC 集成方案,结论是当前场景下意义不大,记为待办
- REST API 双通道:外网 API 通过
/pg/rest/v1/访问(只需 apikey),Dashboard 通过 basic auth 保护
技术细节
Caddy 反向代理正确配置
db.dora.restry.cn {
# 1. basic auth 保护 Dashboard
basicauth /pg* {
# API 路径不需要 basic auth,通过 apikey 认证
}
# 2. /pg 路径优先匹配,转发给 Kong(保留 /pg 前缀!)
reverse_proxy /pg* supabase-kong:8000
# 3. Dashboard 受 basic auth 保护
basicauth * {
supabase $2a$14$hash...
}
reverse_proxy * supabase-studio:3000
}常见错误
- ❌ 使用
handle_path /pg/*→ 会自动去除/pg前缀,Kong 匹配不到路由 - ❌ 通用
reverse_proxy写在特殊路径前面 → Caddy 可能优先匹配通用规则 - ❌ 依赖 Studio 的
DASHBOARD_USERNAME/PASSWORD→ 这些是给 Kong 用的,Caddy 直连 Studio 时不生效
REST API CRUD
# 查询
curl 'http://localhost:8000/rest/v1/表名?select=*' \
-H "apikey: YOUR_KEY" -H "Authorization: Bearer TOKEN"
# 插入
curl -X POST 'http://localhost:8000/rest/v1/表名' \
-H "Content-Type: application/json" -d '{"name":"test"}'
# 更新
curl -X PATCH 'http://localhost:8000/rest/v1/表名?id=eq.1' \
-d '{"value": 456}'
# 删除
curl -X DELETE 'http://localhost:8000/rest/v1/表名?id=eq.1'RLS + 第三方 Auth (Logto) 方案
- 方式 A:共享 JWT_SECRET(简单但耦合)
- 方式 B:JWKS 验证(推荐,标准做法)
- RLS policy 通过
current_setting('request.jwt.claims')读取 JWT 中的 claims
时间线
- 2026-03-06: 检查 Supabase Docker 更新状态,确认已是最新版 (2026.02.16)
- 2026-03-06: 将13个容器镜像推送到 Azure Container Registry
- 2026-03-06: 生成 ACR 版本的 docker-compose.yml
- 2026-03-06: 发现并修复
/pg路径反向代理配置问题(handle_path 错误) - 2026-03-16: 发现 Studio Dashboard 无认证访问安全漏洞
- 2026-03-16: 修复认证问题:在 Caddy 层添加 basic auth
- 2026-03-16: 37张表全部开启 RLS
- 2026-03-16: 评估 Logto 集成方案,决定暂缓
相关页面
Clawline Gateway 数据库接入
以下信息来源于 gatewaybot 的 Mattermost DM 聊天记录(2026-03-18)。
接入方式
Clawline Gateway 是第一个接入自托管 Supabase 的业务应用。由于 PostgREST schema cache 未自动刷新(新建表后 /rest/v1/ 返回 404),采用 /pg/query SQL 直连端点作为替代方案。
数据表设计
采用 cl_ 前缀(用户指定 cl- 但建议用下划线避免 SQL 引号问题):
-- cl_channels
channel_id text PRIMARY KEY,
label text,
secret text,
token_param text NULL,
created_at timestamptz,
updated_at timestamptz
-- cl_channel_users
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
channel_id text REFERENCES cl_channels,
sender_id text,
chat_id text,
token text,
enabled boolean,
created_at timestamptz,
updated_at timestamptzAPI 调用方式
# 通过 /pg/query 端点执行任意 SQL
curl -s -X POST "https://db.dora.restry.cn/pg/query" \
-H "apikey: <service_role_key>" \
-H "Authorization: Bearer <service_role_key>" \
-H "Content-Type: application/json" \
-d '{"query": "SELECT * FROM cl_channels"}'经验教训
- PostgREST 新建表后需要重启容器或执行
NOTIFY pgrst, 'reload schema'才能刷新 schema cache /pg/query端点是自建实例额外暴露的,可执行任意 SQL,适合 DDL 和调试- 后续成功切换到
/pg/rest/v1端点(PostgREST 重启后生效)
/pg/query → PostgREST 迁移事件(2026-03-18)
Supabase 重启后 /pg/query endpoint 认证失效(返回 401),但标准 PostgREST /pg/rest/v1/ 用同一个 service_role key 正常工作。这一事件导致 7 层连锁问题修复:
- Gateway backend —
pg/query→ PostgREST REST API (/pg/rest/v1/) - Portal server.js — 39 条 raw SQL → 创建
run_sqlPL/pgSQL RPC 函数桥接 run_sql函数 — 用 CTE 包裹 DML (INSERT/UPDATE/DELETE RETURNING)- Sync scripts — 6 个 sync.mjs 端口从 18820 → 3019
- Slug 检测 — sync.mjs slug 检测 bug 修复
- Dashboard collector — 也依赖
/pg/query,同步迁移 - 数据表消失 — Supabase 容器重启导致表消失,需确认 PostgreSQL volume 持久化
核心教训:从一开始就不该用 /pg/query(Studio 非标准 API),应该只用 PostgREST 标准接口。
表持久化问题
Supabase 容器重启后表会消失,根因是 Docker volume 未正确持久化 PostgreSQL data。需确认 docker-compose.yml 中 /var/lib/postgresql/data 挂载到持久化 volume。
2026-04-16 更新:PostgreSQL 远程连接配置(最终方案:Docker 端口映射)
来源:giraffe(早期尝试)→ quokka(最终方案)频道 Clawline 聊天记录(2026-04-15~16)
背景
用户需要从外部远程连接 supabase-china VM 上的 PostgreSQL 数据库。VM 上 Supabase 的 PG 监听在 5432 和 6543(PgBouncer),但 Azure NSG 未放行这些端口。
演进过程
初始方案(giraffe,04-15~16 上半天)— iptables 转发:
- 问题:5432 未映射到宿主机,容器内 PG(172.18.0.15:5432)不直接可达
- 加 iptables DNAT
18543 → 172.18.0.15:5432+ DOCKER-USER ACCEPT + POSTROUTING MASQUERADE - 一度可连,但依赖手工 iptables 规则,脆弱且不干净
最终方案(quokka,04-16 13:12)— Docker 原生端口映射:
- 在
docker-compose.yml的db服务下加ports: - "18543:5432" - PG 容器内依旧监听 5432(不改
POSTGRES_PORT,避免pg_isready健康检查和 include 的 conf 出问题) docker compose up -d db重启- 删除所有之前加的 iptables DNAT / FORWARD / POSTROUTING / DOCKER-USER 规则
netfilter-persistent save清理持久化
Azure NSG 规则(tiger-hostNSG)
| 规则 | 端口 | 协议 | 方向 | 备注 |
|---|---|---|---|---|
| Allow-SSH-18822 | 8080 | TCP | Inbound | ⚠️ 名字与端口不对应(历史遗留) |
| AllowHTTP | 80 | TCP | Inbound | |
| AllowHTTPS | 443 | TCP | Inbound | |
| Allow-PG-18543 | 18543 | TCP | Inbound | PG 对外端口 ✅ |
| all18822 | 18822 | * | Inbound | SSH ✅ |
子网 NSG (basicNsgvnet-chinanorth3-4-nic01) 无额外限制。
连接信息
Host: tiger-host.chinanorth3.cloudapp.chinacloudapi.cn
Port: 18543
Database: postgres
User: postgres
连接字符串:
postgresql://postgres:***@tiger-host.chinanorth3.cloudapp.chinacloudapi.cn:18543/postgres
数据库状态(04-16 13:03 quokka 汇总)
- PostgreSQL 15.8(x86_64, GCC 13.2.0)
- 启动时间 2026-03-17 10:32 UTC(稳定运行 ~30 天)
- 活跃连接 40/100(idle 30,active 2)
- 主库
postgres(16 MB) +_supabase - 缓存命中率极高(blks_hit >> blks_read),负载很轻
- 最大表:
cron.job_run_details2.1 MB、public.registrations160 KB、auth.users152 KB - 有一个 Supabase Realtime 的
cainophilelogical replication slot 持续运行(正常) listen_addresses = *、wal_level = logical、max_connections = 100、shared_buffers = 128 MB
经验教训
- 不要改 PG 容器内部监听端口:
pg_isready和postgresql.confinclude 文件都预期 5432,改内部端口会导致 health check 长时间 unhealthy - 优先用 Docker 原生 port mapping,不用 iptables:更干净、可审计、与 compose 生命周期绑定
azchina是az的别名(切AzureChinaCloud,配置目录~/.azure-china),连接 Azure China 订阅专用——易忘记- 本机 DNS 代理劫持(fake-ip)会导致 psql 测试连接假象