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:

1
curl http://<your-domain>/functions/v1/hello

这会返回 "Hello from Edge Functions!"

🌐 This returns "Hello from Edge Functions!".

创建一个新函数 #

🌐 Create a new function

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

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

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

index.ts 中添加以下代码:

🌐 Add the following code to index.ts:

1
Deno.serve(async (req: Request) => {
2
const { name } = await req.json()
3
const message = `Hello, ${name}!`
4
5
return new Response(JSON.stringify({ message }), {
6
headers: { 'Content-Type': 'application/json' },
7
})
8
})

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

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

1
sh run.sh restart functions

步骤 3:调用你的函数 #

🌐 Step 3: Invoke your function

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

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

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

1
{ "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:

1
MY_CUSTOM_VAR=some-value

docker-compose.ymlfunctions 服务中添加 env_fileenv_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
1
functions:
2
env_file:
3
- .env.functions
4
environment:
5
JWT_SECRET: ${JWT_SECRET}
6
SUPABASE_URL: http://kong:8000

重启功能服务:

🌐 Restart the functions service:

1
sh run.sh recreate functions

使用内联环境变量 #

🌐 Using inline environment variables

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

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

docker-compose.yml
1
functions:
2
environment:
3
# Custom variables
4
MY_CUSTOM_VAR: ${MY_CUSTOM_VAR}
5
# Required variables
6
JWT_SECRET: ${JWT_SECRET}
7
SUPABASE_URL: http://kong:8000

然后在你的主 .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:

1
const customVar = Deno.env.get('MY_CUSTOM_VAR')

从函数调用 Supabase 服务 #

🌐 Calling Supabase services from functions

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

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

变量目的
SUPABASE_URLhttp://kong: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/supabase-js 查询表的示例函数:

🌐 Here's an example function that queries a table using @supabase/supabase-js:

1
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
2
3
Deno.serve(async () => {
4
const supabase = createClient(
5
Deno.env.get('SUPABASE_URL')!,
6
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
7
)
8
9
const { data, error } = await supabase.from('todos').select('*')
10
11
return new Response(JSON.stringify({ data, error }), {
12
headers: { 'Content-Type': 'application/json' },
13
})
14
})

内部 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:

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

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

🌐 Then restart the functions service on the remote host:

1
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

400 “请求中缺少函数名称” #

🌐 400 "missing function name in request"

请求的 URL 必须在 /functions/v1/ 之后包含函数名称。例如,/functions/v1/hello

🌐 The request URL must include the function name after /functions/v1/. For example, /functions/v1/hello.

调用时出现500错误 #

🌐 500 error on invocation

检查函数服务日志:

🌐 Check the functions service logs:

1
docker compose logs functions

常见原因:函数代码里的语法错误、无效的导入,或者缺少依赖。

🌐 Common causes: syntax errors in your function code, invalid imports, or missing dependencies.

401 “无效的 JWT” #

🌐 401 "invalid JWT"

  • 检查一下 FUNCTIONS_VERIFY_JWT 是否符合你的意图(truefalse)在 .env
  • 如果启用了验证,确保你传递了有效的令牌:Authorization: Bearer <anon_key or service_role_key>

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

🌐 Changes to function code not reflected after editing

重启功能服务:

🌐 Restart the functions service:

1
sh run.sh restart functions

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

🌐 Custom env vars not available in functions

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

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

🌐 Use the following command to recreate the container:

1
sh run.sh recreate functions

内存或超时错误 #

🌐 Memory or timeout errors

默认的限制是每次函数调用 150 MB 内存和 60 秒超时。这些设置在 volumes/functions/main/index.ts 中。要调整它们,编辑 memoryLimitMbworkerTimeoutMs 的值,然后重启函数服务。

🌐 The default limits are 150 MB memory and 60 seconds timeout per function invocation. These are set in volumes/functions/main/index.ts. To adjust them, edit the memoryLimitMb and workerTimeoutMs values and restart the functions service.