发布于 2026-01-06 4 阅读
0

Supabase DEV 的全球展示挑战赛(由 Mux 呈现):展示你的项目!

使用 Supabase 进行自托管

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

请注意,本文仍在撰写中。如有任何建议或疑问,请在评论区留言。

相关材料:

Supabase是什么?

Supabase 是一款基于 Postgres 的开源数据库解决方案。它不仅包含 Postgres 的所有标准功能,还新增了一些强大的功能,例如实时流和 REST API。所有这些功能都由极其强大的库提供支持。

自托管的优缺点

您可能出于多种原因想要自行托管 Supabase:

  • 更多数据库空间——通过使用您自己的VPS,您可以拥有比Supabase托管平台(目前)提供的数据库大得多的数据库。

  • 完全掌控基础设施——一切尽在您的掌控之中,因此如果您需要进行更改,您可以随时进行更改。

您可能出于以下几个原因而选择让 Supabase 托管您的数据库而不是自行托管:

  • 它已经设置好了——您无需具备深厚的技术知识即可在其平台上设置 Supabase 实例。

  • 费用——他们提供免费套餐,可能足以满足您的需求。

这篇文章是写给谁看的?

本文旨在帮助那些想要自行托管 Supabase 但可能被市面上各种自行托管指南搞得晕头转向的用户。请注意,目前自行托管的方案不包含控制面板。如果您非常在意这一点,那么本指南可能不适合您。

为了更好地理解本文,强烈建议您具备以下方面的基本经验:

  • Nginx - 配置端点/代理
  • Docker - 部署和配置 Dockerfile

即使你缺乏这些技能,我也尽力解释了关键部分以及你需要更改的文件。

我们将使用 Portainer 来管理 Docker 容器。我们还将使用 Cloudflare 的服务。为此,我们将使用db.example.com作为我们的域名。稍后将在 Nginx 配置部分详细介绍。

准备工作

首先,你需要搭建一个服务器托管空间。我个人推荐 DigitalOcean,因为几乎所有操作都可以通过其网页控制面板完成。本文中提到的“Droplet”指的是一个虚拟专用服务器(VPS),它将托管我们的 Supabase 实例。

Supabase 为多个平台提供了一键部署功能,但我们不会使用这些功能,因为它们不包含完整的 Supabase 体验。

我们将改用 Docker。许多 VPS 提供商已经提供了“即用型”Docker 实例。我建议使用现成的实例,因为与手动设置 Docker 相比,这可以节省大量时间。

假设您已设置好运行 Docker 的 Droplet/VPS,那么首先要做的就是安装 Portainer。为此,请按照https://documentation.portainer.io/v2.0/deploy/ceinstalldocker/上的指南进行操作。截至撰写本文时,安装 Portainer 仅需 3 个步骤:

  1. SSH 连接到您的 VPS
  2. 跑步docker volume create portainer_data
  3. 跑步docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

接下来,您需要对 Portainer 进行一些基本配置。请在您的网络浏览器中访问 [此处插入http://<ip-of-your-vps>:9000网址] 并按照屏幕上的说明进行操作。

接下来,我们需要配置 Nginx。幸运的是,使用 Portainer 可以轻松完成这项工作。

继续操作前的可选提示:设置 2 个卷,nginx-confignginx-data,然后volumes在设置 Nginx 时使用选项卡中的这些卷。

从 Portainer 控制面板的左侧菜单中,选择“应用程序模板”,然后从列表中选择“Nginx”,然后按照说明操作。

通过 Portainer 部署

如果你之前阅读过本指南,我建议你创建一个 supabase 代码库的分支。但现在我不再推荐这样做,因为有更好、更简化的方法。

返回 Portainer 网络控制面板,从左侧菜单中选择“堆栈”,然后单击“添加堆栈”。

给你的堆栈命名,然后选择“Git 存储库”。对于存储库 URL,请输入 supabase 存储库的完整 URL(https://github.com/supabase/supabase)。

在“编写路径”字段中,输入/docker/docker-compose.yml

将 .env 文件( https://github.com/supabase/supabase/blob/master/docker/.env.example )的内容复制到一个空白文件中,并使用有效信息更新以下值:

OPERATOR_TOKEN=your-super-secret-operator-token

JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long

POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password

# some SMTP server to send your auth-mails with
SMTP_HOST=mail.example.com
SMTP_PORT=
SMTP_USER=
SMTP_PASS=
Enter fullscreen mode Exit fullscreen mode

在“环境变量”下,点击“高级模式”,然后复制并粘贴文件内容.env

最后,点击底部的“部署堆栈”。此过程可能需要几分钟才能完成。完成后,从 Portainer 菜单中点击“容器”。您可能会注意到 supabase-auth 最初并未运行。只需选中它,然后点击“启动”。之后它应该就能正常运行了。

本节的最后一步是为每个 Supabase 服务配置主机名。在 Portainers 控制面板的“容器”菜单项中,选择每个 Supabase 容器。点击页面顶部的“复制/编辑”。然后,滚动到页面底部,选择“高级容器设置”下的“网络”选项卡。在“主机名”字段中,输入服务的名称。例如,对于容器supabase-rest,将主机名设置为 `<service_name> rest`。您可以将其设置为任何名称,但我建议使其与容器相关。最后,点击“部署此容器”。系统会警告您已存在同名容器 - 点击“确定”。稍等片刻,容器将使用新主机名重新部署。对每个 Supabase 容器重复这些步骤。

这样做有助于 Nginx 连接到容器,并使其更容易在基础设施的其他部分中被识别。

关于 supabase-auth 容器,有一点非常重要:默认情况下,它DATABASE_URL会包含 ` sslmode=disable<sup>`。此值中的等号可能会导致错误。例如,如果您尝试.signUp()从 supabase-js 库调用 `<method>` 方法,则可能会收到 500 错误。原因是它会尝试连接到 `<sup>`disable而不是 `<sup>`。postgres://<db_user>:<password>@db:<db_port>/postgres?sslmode=disable

解决方法是确保sslmode=disable从 URL 中删除所有查询参数。

配置 Nginx

为了配置 Nginx 以支持 Supabase 所需的各种服务,我们需要修改 Nginx 配置。

为此,您需要通过 SSH 连接到服务器,然后cd找到存储 Nginx 配置的卷。如果您nginx-config按照上述步骤设置了卷,则该卷(通常)位于/var/lib/docker/volumes/nginx-config/_data

接下来,我们需要修改两个文件。第一个是nginx.conf……

在该http部分内,添加以下内容:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream websocket {
    server realtime:4000;
}
Enter fullscreen mode Exit fullscreen mode

我们需要修改的另一个文件是conf.d/default.conf。配置 Nginx 的方法有很多种,但为了简单起见,我们将只在一个文件中进行配置。

在 中conf.d/default.conf,将所有内容替换为以下内容:

server {
    listen 443 ssl;
    server_name db.example.com;

    # REST
    location ~ ^/rest/v1/(.*)$ {
        proxy_set_header Host $host;
        proxy_pass http://kong:8000;
        proxy_redirect off;
    }

    # AUTH
    location ~ ^/auth/v1/(.*)$ {
        proxy_set_header Host $host;
        proxy_pass http://kong:8000;
        proxy_redirect off;
    }

    # REALTIME
    location ~ ^/realtime/v1/(.*)$ {
        proxy_redirect off;
        proxy_pass http://kong:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
    }
}
Enter fullscreen mode Exit fullscreen mode

让我解释一下这里发生了什么。

首先,我们的 REST 处理程序会监听发送到/rest/v1该路径的所有请求,以及该路径之后添加的所有内容。然后,它会将这些请求路由到 Supabase Kong 服务器,该服务器默认情况下可通过内部访问http://kong:8000

同样,我们的身份验证处理程序正在监听对 的请求/auth/v1,并将它们路由到 Kong。

最后,实时订阅由路由处理/realtime/v1。同样,这条路由指向 Kong。

如果你读过本指南的最初版本,我当时建议你将请求路由到各个单独的服务。但经过进一步研究,我们发现路由到 Kong 才是更好的解决方案。

我们执行此代理的原因是,它可以确保来自 Supabase 库(例如@supabase/supabase-js)的请求能够正确地路由到堆栈中的不同服务。

Kong 将根据 URL 处理每个请求到其相应服务的路由,而 Nginx 提供了一种在单个 URL 下公开这些端点的方法。

修改完成后,保存文件,然后从 Portainer 控制面板重启 Nginx 容器。为确保一切运行正常,请选择 Nginx 容器,然后点击“查看日志”。日志应显示一切运行正常。

最后,从 Nginx 容器(在 Portainer 控制面板中),将其连接到supabase_default网络——该选项位于控制面板页面的底部。

必要的 Kong 配置

在 Portainer 中,从“卷”菜单选项创建一个新卷。给新卷命名kong-data

然后,返回“容器”,选择“supabase-kong”容器。点击顶部的“复制/编辑”。

滚动到页面底部,点击“卷”。点击“映射其他卷”。在标有“容器”的字段中输入/var/lib/kong。然后点击其右侧的“卷”按钮。

从下面的下拉菜单中选择您刚才创建的“kong-data”卷。然后单击“部署此容器”。

GoTrue / 身份验证环境变量

默认情况下,每个容器的环境变量应该都能正常工作,但 GoTrue / auth 容器可能需要一些额外的配置。

为了简单起见,这里提供一个可在 supabase-auth 容器中使用的环境配置示例 - 您可以根据需要进行编辑:

GOTRUE_OPERATOR_TOKEN=your-super-secret-operator-token
GOTRUE_JWT_DEFAULT_GROUP_NAME=authenticated

# Make sure this JWT secret matches what was configured during setup
GOTRUE_JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long

# How long should JWT tokens be valid for?
GOTRUE_JWT_EXP=3600

# Since Supabase is based on Postgres, you shouldn't need to change this
GOTRUE_DB_DRIVER=postgres

# What schema should requests be routed to?
# There should be no reason to change this
DB_NAMESPACE=auth

# Where is our auth/GoTrue located
# You shouldn't need to change these unless the ports are mapped differently
GOTRUE_API_HOST=0.0.0.0
PORT=9999

# Email settings
# You must set these if you want to be able to send emails
GOTRUE_SMTP_HOST=smtp.your-email-host.com
GOTRUE_SMTP_PORT=465
GOTRUE_SMTP_USER=your-smtp-user
GOTRUE_SMTP_PASS=your-smtp-password

# Should users be required to confirm their email address before they can log in?
# If set to false, users won't have to confirm their registration
# If set to true, users will have to click the link in their email to confirm
GOTRUE_MAILER_AUTOCONFIRM=false

# What is the 'from' address that emails are sent from?
GOTRUE_SMTP_ADMIN_EMAIL=noreply@example.com

# Remove this if you don't want debug logs
GOTRUE_LOG_LEVEL=debug

# The connection string for your database
# `@db` says we're looking for the container called 'db' on our docker network
DATABASE_URL=postgres://postgres:your-super-secret-and-long-postgres-password@db:5432/postgres

# Email templates
# Invite user - provide a URL to a HTML or Text template
GOTRUE_MAILER_TEMPLATES_INVITE=https://example.com/path/to/your/invite/template.html

# Confirm registration - provide a URL to a HTML or Text template
GOTRUE_MAILER_TEMPLATES_CONFIRMATION=https://example.com/path/to/your/confirmation/template.html

# Password recovery - provide a URL to a HTML or Text template
GOTRUE_MAILER_TEMPLATES_RECOVERY=https://example.com/path/to/your/password_reset/template.HTML

# Magic link - provide a URL to a HTML or Text template
GOTRUE_MAILER_TEMPLATES_MAGIC_LINK=https://example.com/path/to/your/magic_link/template.html

# GoTrue URLs
# These are appended after the API_EXTERNAL_URL
# You shouldn't need to change these
GOTRUE_MAILER_URLPATHS_CONFIRMATION=/auth/v1/verify
GOTRUE_MAILER_URLPATHS_INVITE=/auth/v1/verify
GOTRUE_MAILER_URLPATHS_CONFIRMATION=/auth/v1/verify
GOTRUE_MAILER_URLPATHS_RECOVERY=/auth/v1/verify

# Site URLs
# This is where the user will be redirected to after clicking a link in an email and after oAuth
GOTRUE_SITE_URL=https://example.com/redirect_to_here
GOTRUE_URI_ALLOW_LIST=https://example.com/redirect_to_here

# This is the URL where your supabase stack is accessible
# i.e. this is the endpoint URL you would pass into a `createClient()` call in the supabase-js library
API_EXTERNAL_URL=https://database.example.com/

# Set this to true if you want to prevent signing up with email and password
GOTRUE_DISABLE_SIGNUP=true

# oAuth
# If you are not using oAuth to login (e.g. Login with Facebook), you can ignore the below
# If you want to disable oAuth for a specific provider, set the `GOTRUE_EXTERNAL_<provider>_ENABLED` to false
# Github oAuth
GOTRUE_EXTERNAL_GITHUB_CLIENT_ID=your_github_client_id
GOTRUE_EXTERNAL_GITHUB_SECRET=your_github_client_secret
GOTRUE_EXTERNAL_GITHUB_ENABLED=true

# Google oAuth
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOTRUE_EXTERNAL_GOOGLE_SECRET=your-google-secret
GOTRUE_EXTERNAL_GOOGLE_ENABLED=true

# Facebook oAuth
GOTRUE_EXTERNAL_FACEBOOK_CLIENT_ID=your-facebook-client-id
GOTRUE_EXTERNAL_FACEBOOK_SECRET=your-facebook-app-secret
GOTRUE_EXTERNAL_FACEBOOK_ENABLED=true

# Add other oAuth provider details below
Enter fullscreen mode Exit fullscreen mode

最终检查

到目前为止,一切应该都运行正常。

您应该能够使用 VPS IP 地址、端口 5432 以及postgres您在环境变量中设置的用户名和 postgres 密码连接到您的 Postgres 服务器。

结语

如前所述,本文仍在完善中。我仍在研究如何配置 Supabase 堆栈以实现自托管的一些细节。文章中可能缺少一些内容——请留言告知,我会考虑添加。

自托管 Supabase 的配置绝非易事,而且仍有改进空间。希望本文能帮助您加快配置过程,助您顺利开启 Supabase 之旅。

文章来源:https://dev.to/chronsyn/self-hosting-with-supabase-1aii