Skip to content
Self-Hosting

自托管功能

Run and manage Edge Functions in your self-hosted Supabase instance.

在自托管的 Supabase 设置中,Edge Functions 能开箱即用。functions 服务、API 网关路由,以及一个 hello 示例函数都已经预配置好了。

🌐 Edge Functions work out of the box in a self-hosted Supabase setup. The functions service, API gateway routing, and a hello example function are all pre-configured.

调用默认函数 #

🌐 Invoke the default function

默认的 hello 函数位于 volumes/functions/hello/index.ts。你可以在启动堆栈后立即调用它:

🌐 The default hello function is located at volumes/functions/hello/index.ts. You can invoke it immediately after starting your stack:

curl http://<your-domain>/functions/v1/hello \
--header 'apiKey: <sb_publishable/sb_secret key>'

这会返回:

🌐 This returns:

{ "message": "Hello from Edge Functions!" }

创建一个新函数 #

🌐 Create a new function

步骤 1:添加一个新的函数目录和函数代码 #

🌐 Step 1: Add a new function directory and the function code

mkdir -p volumes/functions/my-function &&
touch volumes/functions/my-function/index.ts

在 index.ts 中添加以下代码:

🌐 Add the following code to index.ts:

import { withSupabase } from '@supabase/server'
export default {
fetch: withSupabase({ auth: ['publishable', 'secret'] }, async (req) => {
const { name } = await req.json()
const message = `Hello, ${name}!`
return Response.json({ message })
}),
}

auth 选项控制谁可以调用该函数。这个例子与默认的 hello 函数匹配,并且需要在 apikey 头中提供发布或密钥 API 键。'none' 接受所有请求,而 'user' 需要有效的用户 JWT。详情请查看 Edge Functions 认证指南。

🌐 The auth option controls who can call the function. This example matches the default hello function and requires a publishable or secret API key in the apikey header. 'none' accepts every request, and 'user' requires a valid user JWT. See the Edge Functions auth guide for details.

步骤2:重启函数服务以加载新函数 #

🌐 Step 2: Restart the functions service to pick up the new function

sh run.sh restart functions

步骤 3:调用你的函数 #

🌐 Step 3: Invoke your function

curl -X POST http://<your-domain>/functions/v1/my-function \
-H 'apikey: <SUPABASE_PUBLISHABLE_KEY>' \
-H 'Content-Type: application/json' \
-d '{"name": "World"}'

你应该能看到来自 my-function 的回复:

🌐 You should be able to see the response from my-function:

{ "message": "Hello, World!" }

自定义环境变量 #

🌐 Custom environment variables

🌐 Using an env file (recommended)

对于多个变量或秘密,创建一个单独的环境文件,例如在你的 docker/ 目录下的 .env.functions:

🌐 For multiple variables or secrets, create a separate env file, e.g., .env.functions in your docker/ directory:

MY_CUSTOM_VAR=some-value

在 docker-compose.yml 的 functions 服务中添加 env_file(env_file 中的变量先加载,然后 environment 的值优先):

🌐 Add env_file to the functions service in docker-compose.yml (variables in env_file load first, then environment values take precedence):

docker-compose.yml
functions:
env_file:
- .env.functions
environment:
# ... existing variables ...

重启功能服务:

🌐 Restart the functions service:

sh run.sh recreate functions

使用内联环境变量 #

🌐 Using inline environment variables

对于一个或两个变量,你可以直接在 docker-compose.yml 的 environment 下添加它们:

🌐 For one or two variables, you can add them directly under environment in docker-compose.yml:

docker-compose.yml
functions:
environment:
# Custom variables
MY_CUSTOM_VAR: ${MY_CUSTOM_VAR}
# ... existing variables ...

然后在你的主 .env 文件中定义 MY_CUSTOM_VAR,或者直接指定这个值。

🌐 Then define MY_CUSTOM_VAR in your main .env file, or specify the value directly.

在函数中访问变量 #

🌐 Accessing variables in functions

所有容器环境变量都会被 main/index.ts 转发到函数工作器。可以这样访问它们:

🌐 All container environment variables are forwarded to the function workers by main/index.ts. Access them with:

const = ..('MY_CUSTOM_VAR')

从函数调用 Supabase 服务 #

🌐 Calling Supabase services from functions

函数服务预先配置了以下环境变量:

🌐 The functions service is pre-configured with the following environment variables:

变量值目的
SUPABASE_URLhttp://api-gw:8000内部 API 网关 URL
SUPABASE_PUBLIC_URLhttp(s)://<your-domain>从互联网访问 Supabase 的基础 URL
JWT_SECRETyour-jwt-secretJWT 的旧对称加密密钥
SUPABASE_ANON_KEYyour-anon-key客户端 API 密钥(anon 角色)
SUPABASE_SERVICE_ROLE_KEYyour-service-role-key服务器端 API 密钥(service_role 角色)
SUPABASE_DB_URLpostgresql://...Postgres 连接字符串
SUPABASE_PUBLISHABLE_KEYS{"default":"sb_publishable_...}新的可发布 API 密钥
SUPABASE_SECRET_KEYS{"default":"sb_secret_...}新的秘密 API 密钥
SUPABASE_JWKS{"keys":[{...}]}用于验证 Auth 签发的 JWT 的 JWKS

这里有一个示例函数,使用 @supabase/server 提供的管理员客户端查询表格:

🌐 Here's an example function that queries a table using the admin client provided by @supabase/server:

import { withSupabase } from '@supabase/server'
export default {
fetch: withSupabase({ auth: 'secret' }, async (_req, ctx) => {
// ctx.supabaseAdmin bypasses RLS. This function requires a secret
// API key, so only server-to-server callers can reach it.
const { data, error } = await ctx.supabaseAdmin.from('todos').select('*')
return Response.json({ data, error })
}),
}

withSupabase 会读取上述环境变量中的 SUPABASE_URL、API 密钥和 SUPABASE_JWKS。你不需要自己去连接 createClient。

内部 URL 与外部 URL #

🌐 Internal vs external URLs

这是一个关键区别,会影响你在函数中如何构建 URL:

🌐 This is a key distinction that affects how you build URLs in your functions:

  • SUPABASE_URL 包含一个内部的 Docker 网络主机名。可以在你的函数中用它向其他 Supabase 服务(Auth、Storage、通过 PostgREST 访问数据库)发起服务端调用。这就是 Supabase JS 客户端在函数内部应该使用的。
  • SUPABASE_PUBLIC_URL 是你 Supabase 实例的外部可访问 URL。如果你的函数需要构建 HTTP 客户端可以从外部访问的 URL,就使用它。

通过仪表板管理功能 #

🌐 Managing functions via dashboard

自托管工作室 挂载 与函数服务相同的 volumes/functions 目录。你可以通过 Edge Functions > Functions 界面查看有哪些可用的函数。

🌐 Self-hosted Studio mounts the same volumes/functions directory as the functions service. You can check what functions are available using Edge Functions > Functions UI.

把函数部署到远程服务器 #

🌐 Deploying functions to a remote server

要将函数部署到运行自托管 Supabase 的远程服务器,使用 scp 复制函数目录:

🌐 To deploy a function to a remote server running self-hosted Supabase, copy the function directory with scp:

scp -r ./my-function user@<your-domain>:/path/to/self-hosted/volumes/functions/

然后在远程主机上重启函数服务:

🌐 Then restart the functions service on the remote host:

ssh user@<your-domain> 'cd /path/to/self-hosted && sh run.sh restart functions'

从 Supabase 平台复制功能 #

🌐 Copying functions from Supabase platform

如果你在 Supabase 平台上已经有现有的函数,你可以下载它们并在你自己的托管实例上运行。获取函数源代码有两种方法:

🌐 If you have existing functions on Supabase platform, you can download them and run them on your self-hosted instance. There are two ways to get the function source code:

  • 仪表板 - 在仪表板中打开功能详情,然后点击 下载。
  • 本地开发 & CLI - 运行 supabase functions download <function-name> --project-ref <ref> 下载源码。

使用 scp 将函数复制到你自托管实例的 volumes/functions/<function-name>/,然后重启函数服务。

更多详情,请参见:

🌐 For more details, see:

故障排除 #

🌐 Troubleshooting

404 NOT_FOUND#

请求的 URL 必须在 /functions/v1/ 后包含函数名称。例如,/functions/v1/hello。检查 volumes/functions/hello/ 是否存在对应的目录。

🌐 The request URL must include the function name after /functions/v1/. For example, /functions/v1/hello. Check that the corresponding directory exists at volumes/functions/hello/.

函数调用错误 #

🌐 Function invocation errors

检查 sb-error-code 响应头,并查看 Edge Functions 错误代码 了解错误详情。

🌐 Inspect the sb-error-code response header and see Edge Functions error codes for details about the error.

检查函数服务日志:

🌐 Check the functions service logs:

docker compose logs functions

对于503 BOOT_ERROR,检查语法错误、无效的导入或缺失的依赖,这些都会阻止函数启动。

🌐 For 503 BOOT_ERROR, check for syntax errors, invalid imports, or missing dependencies that prevent the function from starting.

401 “无效的 JWT” #

🌐 401 "invalid JWT"

  • 检查一下 FUNCTIONS_VERIFY_JWT 是否符合你的意图(true 或 false)在 .env 中
  • 如果启用了验证,可以在 Authorization: Bearer <token> 中传递有效的 JWT(用户会话令牌或旧版 API 密钥),或者在 apikey 头中传递 sb_publishable_* 或 sb_secret_* 密钥。API 网关会将 sb_ 密钥转换为内部 JWT,然后函数服务会进行验证。
  • 验证非对称 JWT,包括已翻译的 sb_ 密钥,需要在 docker-compose.yml 的 functions 服务中设置 SUPABASE_JWKS。请参阅 新 API 密钥和非对称认证。

编辑后函数代码的更改没有反映出来 #

🌐 Changes to function code not reflected after editing

重启功能服务:

🌐 Restart the functions service:

sh run.sh restart functions

函数中不可用自定义环境变量 #

🌐 Custom env vars not available in functions

  • 确认变量在 docker-compose.yml 中已定义(在 env_file 或 environment 下)
  • 在更改配置后重新创建函数容器
  • 检查变量名是否完全匹配(区分大小写)

使用以下命令重新创建容器:

🌐 Use the following command to recreate the container:

sh run.sh recreate functions

内存或超时错误 #

🌐 Memory or timeout errors

volumes/functions/main/index.ts 的默认限制适用于每个工作线程:

🌐 The default limits in volumes/functions/main/index.ts apply to each worker:

设置默认值描述
memoryLimitMb150 MB最大内存使用量。
workerTimeoutMs400,000 毫秒工作线程最长生命周期。
requestAbsentTimeoutMs60,000 毫秒当没有待处理任务且 60 秒没有请求时,允许工作线程关闭。

要调整这些限制,请编辑 volumes/functions/main/index.ts 中的数值,然后重启功能服务。

🌐 To adjust these limits, edit the values in volumes/functions/main/index.ts and restart the functions service.

请求有一个单独的空闲超时,时间为150秒。这个参数在 docker-compose.yml 中的函数服务命令里由 --user-worker-request-idle-timeout 设置,值为 150000 毫秒。更改这个值后,需要重新创建函数容器。

🌐 Requests have a separate idle timeout of 150 seconds. This is set by --user-worker-request-idle-timeout in the functions service command in docker-compose.yml, with the value 150000 in milliseconds. Recreate the functions container after changing this value.

Envoy 网关 有单独的限制:160 秒的不活动时间和 410 秒的上游响应超时。

🌐 The Envoy gateway has separate limits of 160 seconds of inactivity and a 410-second upstream response timeout.

如果你使用可选的 Kong 网关,volumes/api/kong.yml 中的 read_timeout 会被设置为 160000 毫秒,允许函数服务的读取之间有 160 秒的空闲时间。

🌐 If you use the optional Kong gateway, read_timeout in volumes/api/kong.yml is set to 160000 milliseconds, allowing 160 seconds of inactivity between reads from the functions service.