Supabase v1.26.08 配置参数详解

Supabase v1.26.08 自托管配置参数详解:以实际部署的 .env 为底本逐类讲解密钥体系(POSTGRES_PASSWORD/JWT_SECRET/ANON_KEY/SERVICE_ROLE_KEY 的 JWT 结构实测解码)、URL 与端口、连接池、认证行为、存储、REST API 参数,并实测 Kong 网关声明式路由的鉴权规则与 PGRST_DB_MAX_ROWS 修改闭环(10 行→5 行→回退),附生产配置模板与常见问题。

Supabase2026/10/19

Supabase v1.26.08 配置参数详解

目标:讲清 Supabase v1.26.08 自托管栈的配置体系——以实际部署的 .env 关键项为底本逐类讲解取值、作用与消费方,实测验证 Kong 网关路由的鉴权规则与 PGRST_DB_MAX_ROWS 修改闭环,并给出生产配置模板。全部实测在部署环境(部署目录 /opt/data/quzuo/supabase-v1.26.08/docker,11 个服务 healthy)真实执行、回显逐字照抄;部署过程见《Supabase Docker Compose 部署指南》,组件背景见《Supabase v1.26.08 介绍与选型指南》。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64);部署形态:官方自托管编排部署(部署过程详见《Supabase Docker Compose 部署指南》)
  • 配置版本:Supabase v1.26.08(组件版本清单见《Supabase v1.26.08 介绍与选型指南》二、2.2 节)
  • 配置文件位置(实测):
    • .env:部署目录 /opt/data/quzuo/supabase-v1.26.08/docker/.env,全栈集中配置入口(约 380 行,含注释)
    • volumes/api/kong.yml:API 网关声明式路由(消费方/ACL/路由/插件)
    • volumes/pooler/pooler.exs:连接池租户定义
    • docker-compose.yml:编排文件(组件私有环境变量与挂载)
  • 服务入口(实测监听):Studio :8100、网关 :8101(HTTP)/:8443(HTTPS)、池化 :5433(会话)/:6543(事务)
  • 演示凭据:控制台 admin / q1w2e3r4;数据库口令 q1w2e3r4(实验环境演示值,生产必须重新生成,见六、6.1 节)
  • 服务器地址:192.168.146.128(.env 中三个 URL 键的实测取值均指向它)

二、前置条件

阅读与操作本文前应满足:

三、参数查看与修改方式

3.1 参数查看

(1)查看配置文件内容(.env 为 KEY=VALUE 行格式,# 为注释):

cd /opt/data/quzuo/supabase-v1.26.08/docker
grep -E '^(POSTGRES_PASSWORD|JWT_SECRET|SITE_URL|PGRST_DB_MAX_ROWS)=' .env

实测回显:

POSTGRES_PASSWORD=q1w2e3r4
JWT_SECRET=Tp5n55aRTXPaBF+hAs0/Xoydu/ExMmSXqWcutGRQ
SITE_URL=http://192.168.146.128:8101
PGRST_DB_MAX_ROWS=1000

(2)验证运行时生效值:配置的最终裁决是「实际行为」。本文统一用两类手段验证生效值:

  • HTTP 行为验证:带 apikey 请求网关各端点,用响应状态码与 JSON 判定(见五、5.8/5.9 节实测);
  • 数据库直连验证:经池化端口用 psql 连接,用户名带租户标识(postgres.<POOLER_TENANT_ID>),实测:
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 5433 -U postgres.your-tenant-id -d postgres -tAc "select version();"

实测回显(节选):

 PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 15.2.0, 64-bit

3.2 参数修改与生效验证闭环(PGRST_DB_MAX_ROWS 全流程实测)

修改任何 .env 参数都遵循同一闭环:改文件 → 重启受影响服务 → 行为验证 → 必要时回退。以 PGRST_DB_MAX_ROWS(REST 单请求最大返回行数)为例做完整实测。

第一步:准备可观测数据——建一张 10 行的演示表并授予匿名读取(经池化端口执行):

PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 5433 -U postgres.your-tenant-id -d postgres \
  -c "create table if not exists public.doc_demo(id int primary key, note text);" \
  -c "insert into public.doc_demo select g, 'row-'||g from generate_series(1,10) g on conflict (id) do nothing;" \
  -c "grant select on public.doc_demo to anon, authenticated;"

实测回显:

CREATE TABLE
INSERT 0 10
GRANT

第二步:取基线(默认 PGRST_DB_MAX_ROWS=1000,应返回全部 10 行):

ANON=$(grep '^ANON_KEY=' .env | cut -d= -f2)
curl -s "http://127.0.0.1:8101/rest/v1/doc_demo?select=id&order=id" -H "apikey: $ANON"

实测回显:

[{"id":1},
 {"id":2},
 {"id":3},
 {"id":4},
 {"id":5},
 {"id":6},
 {"id":7},
 {"id":8},
 {"id":9},
 {"id":10}]

第三步:修改参数并重启——把 .env 中 PGRST_DB_MAX_ROWS=1000 改为 5,然后重启 rest 服务,使其按新变量重建(重启与重建命令见《Supabase Docker Compose 部署指南》十、常用运维命令;实测重建过程中服务经历了 Recreate → Recreated → Started 三阶段,完成后状态即恢复 healthy)。

第四步:行为验证(应只返回 5 行,且响应头给出截断范围):

curl -s "http://127.0.0.1:8101/rest/v1/doc_demo?select=id&order=id" -H "apikey: $ANON"
curl -s -D- -o /dev/null "http://127.0.0.1:8101/rest/v1/doc_demo?select=id" -H "apikey: $ANON" | grep -iE '^(HTTP|content-range)'

实测回显:

[{"id":1},
 {"id":2},
 {"id":3},
 {"id":4},
 {"id":5}]
HTTP/1.1 200 OK
Content-Range: 0-4/*

第五步:回退并复核——改回 PGRST_DB_MAX_ROWS=1000,再次重启 rest 后验证恢复 10 行:

[{"id":1},{"id":2},{"id":3},{"id":4},{"id":5},{"id":6},{"id":7},{"id":8},{"id":9},{"id":10}]

实测期间服务状态始终 healthy(Up 12 seconds (healthy))。

💡 说明:任何「改配置不生效」的排查都先走这套闭环——先确认文件确实改了(3.1 节 grep),再确认服务确实按新变量重建(部署指南 11.2 节:restart 不重读 .env,必须 up -d),最后用行为验证裁决。

四、参数总览

.env 全部有效键按类别汇总如下(实测环境取值,密钥为实验演示值;默认 列为官方 .env.example 示例值):

类别键实测值(演示)作用
数据库POSTGRES_PASSWORDq1w2e3r4数据库口令(全栈共用连接凭据)
数据库POSTGRES_HOST / POSTGRES_DBdb / postgres栈内数据库地址与库名
数据库POSTGRES_PORT5433池化会话端口(宿主侧)
密钥JWT_SECRETTp5n55aRTXPaBF+hAs0/Xoydu/ExMmSXqWcutGRQHS256 签名密钥
密钥ANON_KEY(JWT,见 5.1 解码)匿名角色 API Key
密钥SERVICE_ROLE_KEY(JWT,见 5.1 解码)service_role API Key
密钥SUPABASE_PUBLISHABLE_KEY / SUPABASE_SECRET_KEY / JWT_KEYS / JWT_JWKS(空)新版不透明 Key 与 ES256 JWK 体系
密钥SECRET_KEY_BASE / REALTIME_DB_ENC_KEY / VAULT_ENC_KEY / PG_META_CRYPTO_KEY见《Supabase Docker Compose 部署指南》6.1 节各组件加密密钥
控制台DASHBOARD_USERNAME / DASHBOARD_PASSWORDadmin / q1w2e3r4控制台凭据
控制台STUDIO_DEFAULT_ORGANIZATION / STUDIO_DEFAULT_PROJECTDefault Organization / Default Project默认组织/项目名
控制台OPENAI_API_KEYsk-proj-xxxxxxxxAI 助手(占位值即未启用)
URLSUPABASE_PUBLIC_URLhttp://192.168.146.128:8101对外服务地址
URLAPI_EXTERNAL_URLhttp://192.168.146.128:8101/auth/v1认证外部地址
URLSITE_URL / ADDITIONAL_REDIRECT_URLShttp://192.168.146.128:8101 /(空)重定向主站与白名单
池化POOLER_DEFAULT_POOL_SIZE / POOLER_MAX_CLIENT_CONN / POOLER_DB_POOL_SIZE / POOLER_TENANT_ID20 / 100 / 5 / your-tenant-id连接池容量与租户
池化POOLER_PROXY_PORT_TRANSACTION6543事务池化端口
认证JWT_EXPIRY3600JWT 有效期(秒)
认证DISABLE_SIGNUPfalse注册开关
认证ENABLE_EMAIL_SIGNUP / ENABLE_EMAIL_AUTOCONFIRMtrue / true邮箱注册与自动确认
认证SMTP_HOST / SMTP_PORT / SMTP_ADMIN_EMAILsupabase-mail / 2500 / admin@example.com自定义 SMTP
认证ENABLE_ANONYMOUS_USERS / ENABLE_PHONE_SIGNUPfalse / true匿名用户/手机号注册
存储GLOBAL_S3_BUCKET / REGION / STORAGE_TENANT_IDstub / stub / stub存储桶与租户占位
存储S3_PROTOCOL_ACCESS_KEY_ID / SECRET见《Supabase Docker Compose 部署指南》6.1 节S3 协议端点凭据
存储IMGPROXY_AUTO_WEBPtrue图片自动 WebP
函数FUNCTIONS_VERIFY_JWTfalse边缘函数 JWT 校验开关
RESTPGRST_DB_SCHEMASpublic,graphql_public暴露的数据库模式
RESTPGRST_DB_MAX_ROWS / PGRST_DB_EXTRA_SEARCH_PATH1000 / public行数上限/附加 search_path
网关KONG_HTTP_PORT / KONG_HTTPS_PORT8101 / 8443网关宿主端口

五、核心参数分类详解

5.1 密钥体系:POSTGRES_PASSWORD、JWT_SECRET 与两把 API Key

POSTGRES_PASSWORD 是全栈的「根凭据」:认证(GoTrue)、REST(PostgREST,authenticator 角色)、实时、存储、元数据、连接池、边缘函数共 7 个组件都用 postgres://<用户>:${POSTGRES_PASSWORD}@db:5433/postgres 形态连库(编排文件实查)。修改它等于改数据库口令,需用官方 utils/db-passwd.sh 同步滚动,不能只改 .env(否则所有组件断连)。

JWT_SECRET 是 HS256 对称签名密钥:认证服务用它签发用户 JWT,其余组件用它校验。API Key 本质是「预先用 JWT_SECRET 签好的、永不过期角色 JWT」——对 ANON_KEY 做实测解码:

echo "$ANON" | cut -d. -f1 | tr '_-' '/+' | base64 -d   # Header
echo "$ANON" | cut -d. -f2 | tr '_-' '/+' | base64 -d   # Payload

实测回显:

{"alg":"HS256","typ":"JWT"}
{"role":"anon","iss":"supabase","iat":1792370387,"exp":1950050387}

结构化解读(实测解码时间):

role= anon | iss= supabase | iat= 2026-10-19T08:39:47 | exp= 2031-10-18T08:39:47

SERVICE_ROLE_KEY 同构,payload 为 {"role":"service_role","iss":"supabase","iat":1792370387,"exp":1950050387}(实测解码)。三者的工程含义:

  • anon:匿名角色,受行级安全约束,可暴露给前端;
  • service_role:绕过行级安全的超级角色,只能存在服务端,泄露等于库裸奔;
  • JWT 密钥与 API Key 必须成对管理——换 JWT_SECRET 而不重签两把 Key,全部请求立即 401。

⚠️ 注意:.env 另有 SUPABASE_PUBLISHABLE_KEY/SUPABASE_SECRET_KEY/JWT_KEYS/JWT_JWKS 四键(新版不透明 API Key 与 ES256 非对称体系),实测环境留空即走 HS256 旧体系;新旧体系切换属密钥轮换操作,见 5.10 节。

5.2 URL 类:SUPABASE_PUBLIC_URL、API_EXTERNAL_URL、SITE_URL

三键共同决定「外部世界如何访问本栈」,实测取值与分工:

键实测值消费方与用途
SUPABASE_PUBLIC_URLhttp://192.168.146.128:8101控制台拼装 API 地址、存储公开 URL(STORAGE_PUBLIC_URL)
API_EXTERNAL_URLhttp://192.168.146.128:8101/auth/v1认证服务的对外基地址:OAuth 回调、SAML ACS、邮件确认/邀请/恢复链接都基于它拼接
SITE_URLhttp://192.168.146.128:8101认证成功后重定向的主站地址;ADDITIONAL_REDIRECT_URLS 补充白名单(逗号分隔,留空表示仅 SITE_URL)

验证:实测登录响应的 referer 字段即显示 http://192.168.146.128:8101(认证服务日志,见《Supabase 日常运维手册》日志章节),证明认证服务读取的正是 SITE_URL 值。

⚠️ 注意:这三键必须与「用户浏览器实际访问栈所用的地址」一致。常见事故:填了 localhost 或内网错的端口,导致 OAuth 第三方回调 404、邮件链接打不开。启用 HTTPS 反代后要同步改为 https://<域名> 并重认证服务。

5.3 数据库与连接池类

POSTGRES_HOST=db、POSTGRES_DB=postgres 为栈内约定值;对外连接只经 Supavisor 两个池化端口:

  • POSTGRES_PORT=5433(会话模式):连接即独占一个后端池连接,支持 SET/预编译语句等会话特性,适合长连接与管理工具;
  • POOLER_PROXY_PORT_TRANSACTION=6543(事务模式):每条事务结束即归还连接,吞吐高但不保留会话状态。

容量三键实测值:POOLER_DEFAULT_POOL_SIZE=20(每租户每池的后端连接数)、POOLER_MAX_CLIENT_CONN=100(客户端侧上限)、POOLER_DB_POOL_SIZE=5(池化服务自身元数据库连接)。租户标识 POOLER_TENANT_ID=your-tenant-id 决定连接用户名格式——实测缺租户被拒:

PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -p 5433 -U postgres -d postgres -c 'select 1;'

实测回显(原始报错):

psql: 错误: 连接到"127.0.0.1"上的服务器,端口5433失败:FATAL:  (ENOIDENTIFIER) no tenant identifier provided (external_id or sni_hostname required)

正确用户名 postgres.your-tenant-id 连接成功(实测回显 session-ok|postgres|postgres,见三、3.1 节)。

5.4 控制台类

DASHBOARD_USERNAME=admin、DASHBOARD_PASSWORD=q1w2e3r4 并非普通环境变量——它们被网关的声明式配置注入为 basic-auth 凭据(volumes/api/kong.yml 的 basicauth_credentials 段,消费方名 DASHBOARD)。实测经网关访问控制台不带凭据返回 401、带 admin:q1w2e3r4 返回 307(进控制台),完整回显见《Supabase Docker Compose 部署指南》十一、11.5 节。STUDIO_DEFAULT_ORGANIZATION/STUDIO_DEFAULT_PROJECT 决定控制台默认组织与项目名(实测 307 跳转目标 /project/default 即默认项目页)。

5.5 认证行为类

键实测值行为与验证
JWT_EXPIRY3600用户 JWT 有效期;实测登录响应 expires_in= 3600(见下)
DISABLE_SIGNUPfalse置 true 后 /auth/v1/signup 拒绝新注册
ENABLE_EMAIL_SIGNUPtrue允许邮箱注册
ENABLE_EMAIL_AUTOCONFIRMtrue免验证邮件直接确认(无 SMTP 时的关键开关)
ENABLE_ANONYMOUS_USERSfalse匿名登录关闭
ENABLE_PHONE_SIGNUP / ENABLE_PHONE_AUTOCONFIRMtrue / true手机号注册自动确认(无短信服务商时仅登记流程可用)
SMTP_* 五键supabase-mail:2500指向可选邮件组件;未部署该组件时发信类功能(邀请/恢复)不可外发

实测登录验证(正确口令):

curl -s -X POST "http://127.0.0.1:8101/auth/v1/token?grant_type=password" \
  -H "apikey: $ANON" -H 'Content-Type: application/json' \
  -d '{"email":"admin@example.com","password":"q1w2e3r4"}' \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print('token_type=',d.get('token_type'),'| expires_in=',d.get('expires_in'),'| role=',d.get('user',{}).get('role'))"

实测回显:

token_type= bearer | expires_in= 3600 | user.email= admin@example.com | role= authenticated

错误口令的原始报错(实测):{"code":400,"error_code":"invalid_credentials","msg":"Invalid login credentials"}(HTTP 400);重复注册(实测):{"code":422,"error_code":"user_already_exists","msg":"User already registered"}(HTTP 422)。

5.6 存储类

STORAGE_BACKEND=file(编排内固定)时对象落盘 volumes/storage/,GLOBAL_S3_BUCKET=stub、REGION=stub、STORAGE_TENANT_ID=stub 三个 stub 值为官方默认占位(file 后端下不参与实际路由,保留默认即可)。改用 S3/MinIO 后端需叠加官方 docker-compose.s3.yml 并配置 GLOBAL_S3_ENDPOINT、AWS_ACCESS_KEY_ID 等键。S3_PROTOCOL_ACCESS_KEY_ID/SECRET(实测 64 位十六进制)是 v1.26.x 新增的 S3 协议端点凭据,可用 S3 SDK 直连存储。IMGPROXY_AUTO_WEBP=true 使浏览器支持时图片自动转 WebP(imgproxy 消费)。

5.7 边缘函数类

FUNCTIONS_VERIFY_JWT=false:全局控制边缘函数是否校验请求 JWT。生产建议置 true(函数内可再对个别函数放行);置 false 仅适合公开 demo。函数源码挂载自 volumes/functions/,依赖缓存在命名数据卷 deno-cache。

5.8 REST API 类(PGRST_*)

  • PGRST_DB_SCHEMAS=public,graphql_public:暴露哪些模式为 REST 根;业务表建在 public,GraphQL 端点走 graphql_public;
  • PGRST_DB_MAX_ROWS=1000:单请求最大返回行数,超出部分用分页(Range 头)取;修改闭环实测见三、3.2 节(10 行→5 行→回退 10 行,响应头 Content-Range: 0-4/*);
  • PGRST_DB_EXTRA_SEARCH_PATH=public:请求级 search_path 附加模式。

网关层相关实测(判定「问题在网关还是 REST」的依据):

curl -s -w '\nhttp=%{http_code}\n' "http://127.0.0.1:8101/rest/v1/" -H "apikey: $ANON" | tail -2

实测回显:

}
http=403

即:/rest/v1/ 根路径(OpenAPI 描述)按官方路由配置仅允许 admin 组(service_role)访问,anon 访问返回 403 是设计行为而非故障;查数据走具体表路径 /rest/v1/<表名>。

5.9 Kong 网关路由详解(volumes/api/kong.yml)

网关是全栈唯一入口,其声明式配置 volumes/api/kong.yml(环境变量替换后生效)由四段组成:

(1)消费方与凭据(实测配置结构):

消费方凭据ACL 组
anonkey-auth:$SUPABASE_ANON_KEY、$SUPABASE_PUBLISHABLE_KEYanon
service_rolekey-auth:$SUPABASE_SERVICE_KEY、$SUPABASE_SECRET_KEYadmin
DASHBOARDbasic-auth:$DASHBOARD_USERNAME/$DASHBOARD_PASSWORD—

(2)路由与鉴权矩阵(实测整理):

路径前缀后端API Key 校验允许角色备注
/rest/v1/(根)rest:3000是仅 adminOpenAPI 描述,anon 403
/rest/v1/*rest:3000是admin、anon数据 API 主通道
/graphql/v1rest:3000/rpc/graphql是admin、anon注入 Content-Profile: graphql_public
/auth/v1/(通用)auth:9999是admin、anon登录/注册等
/auth/v1/verify、/callback、/authorize、/.well-known/jwks.json、/sso/saml/*auth:9999否—回调与发现端点必须免鉴权(OAuth/邮件链接直达)
/realtime/v1/(WebSocket)realtime:4000/socket是(转 x-api-key/apikey)admin、anonWS 通道
/realtime/v1/api/openapi、/api/tenants—封禁—request-termination 403 "Access is forbidden."
/storage/v1/*storage:5000否(转 Authorization)—兼容 S3 签名请求(无 apikey 头)
/functions/v1/*functions:9000否(函数自行校验)—读超时 150s
/pg/meta:8080是仅 admin控制台专用管理通道
/api/mcp、/mcpstudio:3000/api/mcp封禁—默认 403(如需本地开启按配置内注释操作)
/*(其余)studio:3000basic-auth(DASHBOARD)—控制台页面

(3)实测判定速查:

实测请求实测结果判定
GET /kong/status(无凭据/anon key 均试)均 401 {"message":"Unauthorized","request_id":"..."}非公开探活端点,探活改用 /auth/v1/health
GET /auth/v1/health + anon key200 {"version":"v2.189.0","name":"GoTrue",...}认证服务健康
GET /storage/v1/status(免 key)200存储健康
GET /rest/v1/doc_demo + 错误 apikey wrong-key-123401Key 无效(key-auth 拒绝)
GET /rest/v1/no_such_table + anon key404 {"code":"PGRST205",...,"message":"Could not find the table 'public.no_such_table' in the schema cache"}网关已放行、REST 层查无此表

(4)修改方式:编辑 volumes/api/kong.yml 后重启 kong(该配置每次启动时经 kong-entrypoint.sh 做变量替换后加载);新增对外路由时必须同步考虑 key-auth 与 ACL 组,避免把管理端点暴露到 anon 组。

5.10 密钥生成与轮换工具(utils/)

官方 utils/ 目录提供六个配置运维脚本(实测清单):

add-new-auth-keys.sh
db-passwd.sh
generate-keys.sh
reassign-owner.sh
rotate-new-api-keys.sh
upgrade-pg17.sh
  • generate-keys.sh:一键生成全量密钥(实测输出样例见《Supabase Docker Compose 部署指南》四、4.2 节),--update-env 直接写回 .env;
  • add-new-auth-keys.sh:叠加 ES256 非对称密钥体系(前置 .env 存在,实测空目录执行报 Error: .env file not found. Run generate-keys.sh first.);
  • db-passwd.sh:数据库口令轮换(同步更新数据库角色与全部组件连接串);
  • rotate-new-api-keys.sh:不透明 API Key 轮换;reassign-owner.sh:对象所有权批量变更;upgrade-pg17.sh:PostgreSQL 15 → 17 大版本原地升级。

六、生产配置模板

适用场景:内网/单机团队 SaaS 后端,8GB 内存、SSD 磁盘、日活千级。以下为 .env 生产化要点模板(密钥一律用 utils/generate-keys.sh 现生成,本表只给策略不给实值):

# —— 密钥:全部现生成,禁止沿用任何文档示例值 ——
# sh utils/generate-keys.sh --update-env   # 一次性写入全量密钥
POSTGRES_PASSWORD=<generate-keys 生成>
JWT_SECRET=<generate-keys 生成,≥32 字符>
ANON_KEY=<generate-keys 生成>
SERVICE_ROLE_KEY=<generate-keys 生成;仅服务端保存>
DASHBOARD_USERNAME=admin
DASHBOARD_PASSWORD=<强口令>

# —— URL:改为真实对外地址(域名 + HTTPS) ——
SUPABASE_PUBLIC_URL=https://supabase.example.com
API_EXTERNAL_URL=https://supabase.example.com/auth/v1
SITE_URL=https://app.example.com

# —— 连接池:8GB 内存建议起步值 ——
POOLER_DEFAULT_POOL_SIZE=20
POOLER_MAX_CLIENT_CONN=200
POOLER_DB_POOL_SIZE=5

# —— 认证:生产收紧 ——
JWT_EXPIRY=3600
DISABLE_SIGNUP=false            # 邀请制上线后置 true
ENABLE_EMAIL_AUTOCONFIRM=false  # 配置真实 SMTP 后关闭自动确认
SMTP_HOST=<真实 SMTP 主机>
SMTP_PORT=587
SMTP_ADMIN_EMAIL=admin@example.com
SMTP_SENDER_NAME=no-reply

# —— REST / 函数 ——
PGRST_DB_MAX_ROWS=1000
FUNCTIONS_VERIFY_JWT=true

模板要点:① 三键 URL 与真实域名一致并启用 TLS(官方提供 Caddy/Nginx 反代叠加编排);② SERVICE_ROLE_KEY 的分发范围写进发布规范;③ 无 SMTP 场景保持 ENABLE_EMAIL_AUTOCONFIRM=true 否则用户无法完成注册;④ 磁盘规划上为 volumes/db/data 预留主要增量(实测部署初期 67MB,随业务线性增长)。

七、常见问题(FAQ)

Q1:改了 .env 但行为没变? 按三、3.2 节闭环排查:grep 确认文件已改 → 按新变量重建受影响服务(仅 restart 不重读 .env,实测复现与解法见《Supabase Docker Compose 部署指南》十一、11.2 节)→ 行为验证裁决。

Q2:连接池化端口报 FATAL: (ENOIDENTIFIER) no tenant identifier provided? 用户名缺租户标识。改为 postgres.<POOLER_TENANT_ID>(默认 postgres.your-tenant-id),完整报错与两种模式成功实测见 5.3 节。

Q3:带 anon key 访问 /rest/v1/ 返回 403? 设计行为:根路径(OpenAPI)仅 admin 组可见(5.8 节实测)。查数据请访问具体表路径 /rest/v1/<表名>。

Q4:新建的表经 REST 查询报 PGRST205? 实测报错原文:{"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'public.no_such_table' in the schema cache"}(404)。先确认表名/模式正确且已 grant 给 anon/authenticated;PostgREST v14 会侦测 DDL 自动重载缓存,极端情况下重建 rest 服务即可。

Q5:注册/登录的 422/400 是什么含义? 422 user_already_exists(邮箱已注册,实测原文见 5.5 节);400 invalid_credentials(口令错误)。两者均为认证服务正常业务报错,不是配置故障。

Q6:/kong/status 一直 401? 该端点非公开探活端点(有无 apikey 均 401,实测见 5.9 节判定速查表)。探活用 GET /auth/v1/health(带 anon key)或 GET /storage/v1/status(免鉴权)。

Q7:API Key 泄露了怎么办? 立即轮换:JWT_SECRET 换新后必须同步重签 ANON_KEY/SERVICE_ROLE_KEY(三者绑定,见 5.1 节),随后重启全部服务;utils/rotate-new-api-keys.sh/add-new-auth-keys.sh 用于滚动到新版密钥体系。轮换会导致存量用户会话失效,安排在低峰窗口。

八、参考链接