自建Supabase:创业出海的首选数据库
Supabase 非常棒,拥有你自己的 Supabase 那就是棒上加棒!本文介绍了如何在本地/云端物理机/裸金属/虚拟机上自建企业级 Supabase。
目录
简短版本
curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty
./bootstrap # 准备 Pigsty 依赖
./configure -c app/supa # 使用 Supabase 应用模板
vi pigsty.yml # 编辑配置文件,修改域名与密码
./install.yml # 安装 Pigsty,以及各种数据库
./docker.yml # 安装 Docker 与 Docker Compose
./app.yml # 使用 Docker 拉起 Supabase 无状态部分
Supabase是什么?
Supabase 是一个 BaaS (Backend as Service),开源的 Firebase。 Supabase 对 PostgreSQL 进行了封装,并提供了身份认证,消息传递,边缘函数,对象存储,并基于 PG 数据库模式自动生成 REST API 与 GraphQL API。
Supabase 旨在为开发者提供一站式的后端解决方案,减少开发和维护后端基础设施的复杂性,使开发者专注于前端开发和用户体验。 用大白话说就是:让开发者告别绝大部分后端开发的工作,只需要懂数据库设计与前端即可快速出活!
目前,Supabase 是 PostgreSQL 生态 人气最高的开源项目,在 GitHub 上已经有高达 八万 的 Star 数。 并且和 Neon,Cloudflare 一起并称为赛博菩萨 —— 因为他们都提供了非常不错的云服务免费计划。目前,Supabase 和 Neon 已经成为许多初创企业的首选数据库 —— 用起来非常方便,起步还是免费的。
为什么要自建Supabase?
小微规模(4c8g)内的 Supabase 云服务极富性价比,人称赛博菩萨。那么 Supabase 云服务这么香,为什么要自建呢?
最直观的原因是是我们在《云数据库是智商税吗?》中提到过的:当你的规模超出云计算适用光谱,成本很容易出现爆炸式增长。 而且在当下,足够可靠的本地企业级 NVMe SSD在性价比上与云端存储有着三到四个数量级的优势,而自建能更好地利用这一点。
另一个重要的原因是功能, Supabase 云服务的功能受限 —— 出于与RDS相同的逻辑, 很多 强力PG扩展 因为多租户安全挑战与许可证的原因无法作为云服务提供。 故而尽管PG扩展是 Supabase 的一个核心特色,在云服务上也依然只有 64 个可用扩展,而 Pigsty 提供了多达 407 个开箱即用的 PG 扩展。
此外,尽管 Supabase 虽然旨在提供一个无供应商锁定的 Google Firebase 开源替代,但实际上自建高标准企业级的 Supabase 门槛并不低: Supabase 内置了一系列由他们自己开发维护的 PG 扩展插件,而这些扩展在 PGDG 官方仓库中并没有提供。 这实际上是某种隐性的供应商锁定,阻止了用户使用除了 supabase/postgres Docker 镜像之外的方式自建。
Pigsty 解决了这些问题,我们将所有 Supabase 自研与用到的 10 个缺失的扩展打成开箱即用的 RPM/DEB 包,确保它们在所有主流Linux操作系统发行版上都可用:
- pg_graphql:提供PG内的GraphQL支持 (RUST),Rust扩展,由PIGSTY提供
- pg_jsonschema:提供JSON Schema校验能力,Rust扩展,由PIGSTY提供
- wrappers:Supabase提供的外部数据源包装器捆绑包,,Rust扩展,由PIGSTY提供
- index_advisor:查询索引建议器,SQL扩展,由PIGSTY提供
- pg_net:用 SQL 进行异步非阻塞HTTP/HTTPS 请求的扩展 (supabase),C扩展,由PIGSTY提供
- vault:在 Vault 中存储加密凭证的扩展 (supabase),C扩展,由PIGSTY提供
- pgjwt:JSON Web Token API 的PG实现 (supabase),SQL扩展,由PIGSTY提供
- pgsodium:表数据加密存储 TDE,扩展,由PIGSTY提供
- supautils:用于在云环境中确保数据库集群的安全,C扩展,由PIGSTY提供
- pg_plan_filter:使用执行计划代价过滤阻止特定查询语句,C扩展,由PIGSTY提供
我们在 Supabase 自建部署中默认安装绝大多数扩展,您可以参考可用扩展列表按需启用。
同时,Pigsty 还会负责好底层 高可用 PostgreSQL 数据库集群,高可用 MinIO 对象存储集群的自动搭建,甚至是 Docker 容器底座的部署与 Nginx 域名配置与HTTPS证书签发。 最终,您可以使用 Docker Compose 拉起任意数量的无状态 Supabase 容器集群,并使用外部由 Pigsty 托管的企业级 PostgreSQL 数据库与 MinIO 对象存储,甚至连反向代理的 Nginx 等都已经为您配置准备完毕!
在这一自建部署架构中,您获得了使用不同内核的自由(PG 15-17),加装 407 个扩展的自由,扩容与伸缩 Supabase/Postgres/MinIO 的自由,免于数据库运维的自由,以及告别供应商锁定的自由。 而相比于使用 Supabase 云服务需要付出的代价,不过是准备一(几)台物理机/虚拟机 + 敲几行命令,等候十几分钟的区别。
单节点自建快速上手
让我们先从单节点 Supabase 部署开始,我们会在后面进一步介绍多节点高可用部署的方法。
首先,使用 Pigsty 标准安装流程 安装 Supabase 所需的 MinIO 与 PostgreSQL 实例;
然后额外运行 docker.yml
与 app.yml
完成剩余的工作,
拉起无状态部分的 Supabase 容器,Supabase 就可以使用了(默认端口 8000
/8433
)。
curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty
./bootstrap # 准备 Pigsty 依赖
./configure -c app/supa # 使用 Supabase 应用模板
vi pigsty.yml # 编辑配置文件,修改域名与密码
./install.yml # 安装 Pigsty,以及各种数据库
./docker.yml # 安装 Docker 与 Docker Compose
./app.yml # 使用 Docker 拉起 Supabase 无状态部分
请在部署 Supabase 前,根据您的实际情况,修改自动生成的 pigsty.yml
配置文件中的参数(主要是密码!)
如果您只是将其用于本地开发测试,可以先不管这些,我们将在后面介绍如何通过修改配置文件来定制您的 Supabase。
如果您的配置没有问题,那么大约在 10 分钟后,您就可以在本地网络通过 http://<your_ip_address>:8000
访问到 Supabase Studio 管理界面了。
默认的用户名与密码分别是: supabase
与 pigsty
。
检查清单
- 硬件/软件:准备所需的机器资源:Linux
x86_64/arm64
服务器一台,全新安装主流 Linux 操作系统 - 网络/权限:有 ssh 免密登陆权限,所用用户有免密 sudo 权限
- 确保机器有内网静态IPv4网络地址,并可以访问互联网。
- 在
configure
过程中,请输入节点的内网首要 IP 地址,或直接通过-i <primary_ip>
命令行参数指定 - 如果您的网络环境无法访问 DockerHub,请通过
docker_registry_mirrors
使用镜像站 或proxy_env
绕过防火墙。
- 在
- 确保使用了
app/supa
配置模板,并按需修改了参数- 您是否修改了所有与密码有关的配置参数?【可选】
- 您是否需要使用外部 SMTP 服务器?是否配置了
apps.<supabase>.conf
中的 SMTP 相关参数?【可选】
- DockerHub 网络访问问题
- 对于中国区域的用户,因为 DockerHub 被墙,Pigsty 默认会使用
docker.1ms.run
作为 Docker 镜像站点。你可以在docker_registry_mirrors
指定其他的 Docker 镜像站点,或者使用proxy_env
配置代理服务器直接访问 DockerHub。
- 对于中国区域的用户,因为 DockerHub 被墙,Pigsty 默认会使用
修改后的配置文件,应该如下所示:
对默认生成的配置文件进行修改
---
#==============================================================#
# File : supa.yml
# Desc : Pigsty configuration for self-hosting supabase
# Ctime : 2023-09-19
# Mtime : 2025-03-30
# Docs : https://pigsty.io/docs/app/supabase/
# License : AGPLv3 @ https://pigsty.io/docs/about/license
# Copyright : 2018-2025 Ruohang Feng / Vonng ([email protected])
#==============================================================#
# supabase is available on el8/el9/u22/u24/d12 with pg15,16,17
# To install supabase on fresh node, run:
#
# curl -fsSL https://repo.pigsty.io/get | bash
# ./bootstrap # prepare local repo & ansible
# ./configure -c app/supa # use this supabase conf template
# vi pigsty.yml # IMPORTANT: CHANGE CREDENTIALS!!
# ./install.yml # install pigsty & pgsql & minio
# ./docker.yml # install docker & docker compose
# ./app.yml # launch supabase with docker compose
all:
children:
# the supabase stateless (default username & password: supabase/pigsty)
supa:
hosts:
10.10.10.10: {}
vars:
app: supabase # specify app name (supa) to be installed (in the apps)
apps: # define all applications
supabase: # the definition of supabase app
conf: # override /opt/supabase/.env
# IMPORTANT: CHANGE JWT_SECRET AND REGENERATE CREDENTIAL ACCORDING!!!!!!!!!!!
# https://supabase.com/docs/guides/self-hosting/docker#securing-your-services
JWT_SECRET: your-super-secret-jwt-token-with-at-least-32-characters-long
ANON_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
SERVICE_ROLE_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q
DASHBOARD_USERNAME: supabase
DASHBOARD_PASSWORD: pigsty
# postgres connection string (use the correct ip and port)
POSTGRES_HOST: 10.10.10.10 # point to the local postgres node
POSTGRES_PORT: 5436 # access via the 'default' service, which always route to the primary postgres
POSTGRES_DB: postgres # the supabase underlying database
POSTGRES_PASSWORD: DBUser.Supa # password for supabase_admin and multiple supabase users
# expose supabase via domain name
SITE_URL: https://supa.pigsty # <------- Change This to your external domain name
API_EXTERNAL_URL: https://supa.pigsty # <------- Otherwise the storage api may not work!
SUPABASE_PUBLIC_URL: https://supa.pigsty # <------- DO NOT FORGET TO PUT IT IN infra_portal!
# if using s3/minio as file storage
S3_BUCKET: supa
S3_ENDPOINT: https://sss.pigsty:9000
S3_ACCESS_KEY: supabase
S3_SECRET_KEY: S3User.Supabase
S3_FORCE_PATH_STYLE: true
S3_PROTOCOL: https
S3_REGION: stub
MINIO_DOMAIN_IP: 10.10.10.10 # sss.pigsty domain name will resolve to this ip statically
# if using SMTP (optional)
#SMTP_ADMIN_EMAIL: [email protected]
#SMTP_HOST: supabase-mail
#SMTP_PORT: 2500
#SMTP_USER: fake_mail_user
#SMTP_PASS: fake_mail_password
#SMTP_SENDER_NAME: fake_sender
#ENABLE_ANONYMOUS_USERS: false
# infra cluster for proxy, monitor, alert, etc..
infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
# etcd cluster for ha postgres
etcd: { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
# minio cluster, s3 compatible object storage
minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }
# pg-meta, the underlying postgres database for supabase
pg-meta:
hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
vars:
pg_cluster: pg-meta
pg_users:
# supabase roles: anon, authenticated, dashboard_user
- { name: anon ,login: false }
- { name: authenticated ,login: false }
- { name: dashboard_user ,login: false ,replication: true ,createdb: true ,createrole: true }
- { name: service_role ,login: false ,bypassrls: true }
# supabase users: please use the same password
- { name: supabase_admin ,password: 'DBUser.Supa' ,pgbouncer: true ,inherit: true ,roles: [ dbrole_admin ] ,superuser: true ,replication: true ,createdb: true ,createrole: true ,bypassrls: true }
- { name: authenticator ,password: 'DBUser.Supa' ,pgbouncer: true ,inherit: false ,roles: [ dbrole_admin, authenticated ,anon ,service_role ] }
- { name: supabase_auth_admin ,password: 'DBUser.Supa' ,pgbouncer: true ,inherit: false ,roles: [ dbrole_admin ] ,createrole: true }
- { name: supabase_storage_admin ,password: 'DBUser.Supa' ,pgbouncer: true ,inherit: false ,roles: [ dbrole_admin, authenticated ,anon ,service_role ] ,createrole: true }
- { name: supabase_functions_admin ,password: 'DBUser.Supa' ,pgbouncer: true ,inherit: false ,roles: [ dbrole_admin ] ,createrole: true }
- { name: supabase_replication_admin ,password: 'DBUser.Supa' ,replication: true ,roles: [ dbrole_admin ]}
- { name: supabase_read_only_user ,password: 'DBUser.Supa' ,bypassrls: true ,roles: [ dbrole_readonly, pg_read_all_data ] }
pg_databases:
- name: postgres
baseline: supabase.sql
owner: supabase_admin
comment: supabase postgres database
schemas: [ extensions ,auth ,realtime ,storage ,graphql_public ,supabase_functions ,_analytics ,_realtime ]
extensions:
- { name: pgcrypto ,schema: extensions } # cryptographic functions
- { name: pg_net ,schema: extensions } # async HTTP
- { name: pgjwt ,schema: extensions } # json web token API for postgres
- { name: uuid-ossp ,schema: extensions } # generate universally unique identifiers (UUIDs)
- { name: pgsodium } # pgsodium is a modern cryptography library for Postgres.
- { name: supabase_vault } # Supabase Vault Extension
- { name: pg_graphql } # pg_graphql: GraphQL support
- { name: pg_jsonschema } # pg_jsonschema: Validate json schema
- { name: wrappers } # wrappers: FDW collections
- { name: http } # http: allows web page retrieval inside the database.
- { name: pg_cron } # pg_cron: Job scheduler for PostgreSQL
- { name: timescaledb } # timescaledb: Enables scalable inserts and complex queries for time-series data
- { name: pg_tle } # pg_tle: Trusted Language Extensions for PostgreSQL
- { name: vector } # pgvector: the vector similarity search
- { name: pgmq } # pgmq: A lightweight message queue like AWS SQS and RSMQ
# supabase required extensions
pg_libs: 'timescaledb, plpgsql, plpgsql_check, pg_cron, pg_net, pg_stat_statements, auto_explain, pg_tle, plan_filter'
pg_parameters:
cron.database_name: postgres
pgsodium.enable_event_trigger: off
pg_hba_rules: # supabase hba rules, require access from docker network
- { user: all ,db: postgres ,addr: intra ,auth: pwd ,title: 'allow supabase access from intranet' }
- { user: all ,db: postgres ,addr: 172.17.0.0/16 ,auth: pwd ,title: 'allow access from local docker network' }
node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # make a full backup every 1am
#==============================================================#
# Global Parameters
#==============================================================#
vars:
version: v3.4.0 # pigsty version string
admin_ip: 10.10.10.10 # admin node ip address
region: china # upstream mirror region: default|china|europe
pg_locale: C.UTF-8 # overwrite default C local
pg_lc_collate: C.UTF-8 # overwrite default C lc_collate
pg_lc_ctype: C.UTF-8 # overwrite default C lc_ctype
node_tune: oltp # node tuning specs: oltp,olap,tiny,crit
pg_conf: oltp.yml # pgsql tuning specs: {oltp,olap,tiny,crit}.yml
docker_enabled: true # enable docker on app group
docker_registry_mirrors: ["https://docker.1ms.run"] # use mirror in mainland china
proxy_env: # global proxy env when downloading packages & pull docker images
no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.tsinghua.edu.cn"
#http_proxy: 127.0.0.1:12345 # add your proxy env here for downloading packages or pull images
#https_proxy: 127.0.0.1:12345 # usually the proxy is format as http://user:[email protected]
#all_proxy: 127.0.0.1:12345
certbot_email: [email protected] # your email address for applying free let's encrypt ssl certs
infra_portal: # domain names and upstream servers
home : { domain: h.pigsty }
grafana : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
prometheus : { domain: p.pigsty ,endpoint: "${admin_ip}:9090" }
alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9093" }
minio : { domain: m.pigsty ,endpoint: "10.10.10.10:9001", https: true, websocket: true }
blackbox : { endpoint: "${admin_ip}:9115" }
loki : { endpoint: "${admin_ip}:3100" } # expose supa studio UI and API via nginx
supa : # nginx server config for supabase
domain: supa.pigsty # REPLACE WITH YOUR OWN DOMAIN!
endpoint: "10.10.10.10:8000" # supabase service endpoint: IP:PORT
websocket: true # add websocket support
certbot: supa.pigsty # certbot cert name, apply with `make cert`
#----------------------------------#
# Credential: CHANGE THESE PASSWORDS
#----------------------------------#
#grafana_admin_username: admin
grafana_admin_password: pigsty
#pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
#pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor
#pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
#patroni_username: postgres
patroni_password: Patroni.API
#haproxy_admin_username: admin
haproxy_admin_password: pigsty
#minio_access_key: minioadmin
minio_secret_key: minioadmin # minio root secret key, `minioadmin` by default, also change pgbackrest_repo.minio.s3_key_secret
# use minio as supabase file storage, single node single driver mode for demonstration purpose
minio_buckets: [ { name: pgsql }, { name: supa } ]
minio_users:
- { access_key: dba , secret_key: S3User.DBA, policy: consoleAdmin }
- { access_key: pgbackrest , secret_key: S3User.Backup, policy: readwrite }
- { access_key: supabase , secret_key: S3User.Supabase, policy: readwrite }
minio_endpoint: https://sss.pigsty:9000 # explicit overwrite minio endpoint with haproxy port
node_etc_hosts: ["10.10.10.10 sss.pigsty"] # domain name to access minio from all nodes (required)
# use minio as default backup repo for PostgreSQL
pgbackrest_method: minio # pgbackrest repo method: local,minio,[user-defined...]
pgbackrest_repo: # pgbackrest repo: https://pgbackrest.org/configuration.html#section-repository
local: # default pgbackrest repo with local posix fs
path: /pg/backup # local backup directory, `/pg/backup` by default
retention_full_type: count # retention full backups by count
retention_full: 2 # keep 2, at most 3 full backup when using local fs repo
minio: # optional minio repo for pgbackrest
type: s3 # minio is s3-compatible, so s3 is used
s3_endpoint: sss.pigsty # minio endpoint domain name, `sss.pigsty` by default
s3_region: us-east-1 # minio region, us-east-1 by default, useless for minio
s3_bucket: pgsql # minio bucket name, `pgsql` by default
s3_key: pgbackrest # minio user access key for pgbackrest
s3_key_secret: S3User.Backup # minio user secret key for pgbackrest <------------------ HEY, DID YOU CHANGE THIS?
s3_uri_style: path # use path style uri for minio rather than host style
path: /pgbackrest # minio backup path, default is `/pgbackrest`
storage_port: 9000 # minio port, 9000 by default
storage_ca_file: /etc/pki/ca.crt # minio ca file path, `/etc/pki/ca.crt` by default
block: y # Enable block incremental backup
bundle: y # bundle small files into a single file
bundle_limit: 20MiB # Limit for file bundles, 20MiB for object storage
bundle_size: 128MiB # Target size for file bundles, 128MiB for object storage
cipher_type: aes-256-cbc # enable AES encryption for remote backup repo
cipher_pass: pgBackRest # AES encryption password, default is 'pgBackRest' <----- HEY, DID YOU CHANGE THIS?
retention_full_type: time # retention full backup by time on minio repo
retention_full: 14 # keep full backup for last 14 days
pg_version: 17
repo_extra_packages: [pg17-core ,pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-olap ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl ]
pg_extensions: [ pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl, pg_mooncake, pg_analytics, pg_parquet ] #,pg17-olap]
...
自建关键技术决策
以下是一些自建 Supabase 会涉及到的关键技术决策,供您参考:
使用默认的单节点部署 Supabase 无法享受到 PostgreSQL / MinIO 的高可用能力。 尽管如此,单节点部署相比官方纯 Docker Compose 方案依然要有显著优势: 例如开箱即用的监控系统,自由安装扩展的能力,各个组件的扩缩容能力,以及数据库时间点恢复能力等。
如果您只有一台服务器,Pigsty 建议您直接使用外部的 S3 作为对象存储,存放 PostgreSQL 的备份,并承载 Supabase Storage 服务。 这样的部署在故障时可以提供一个最低标准的 RTO (小时级恢复时长)/ RPO (MB级数据损失)兜底容灾水平。 此外,如果您选择在云上自建,我们也建议您直接使用 S3,而非默认使用的本体 MinIO ,单纯在本地 EBS 上再套一层 MinIO 转发,除了便于开发测试外,对生产实用并没有意义。
在严肃的生产部署中,Pigsty 建议使用至少3~4个节点的部署策略,确保 MinIO 与 PostgreSQL 都使用满足企业级高可用要求的多节点部署。
在这种情况下,您需要相应准备更多节点与磁盘,并相应调整 pigsty.yml
配置清单中的集群配置,以及 supabase 集群配置中的接入信息。
部分 Supabase 的功能需要发送邮件,所以要用到 SMTP。除非单纯用于内网,否则对于严肃的生产部署,我们建议您考虑使用外部的 SMTP 服务。 自建的邮件服务器发送的邮件可能会被对方邮件服务器拒收,或者被标记为垃圾邮件。
如果您的服务直接向公网暴露,我们建议您使用 Nginx 进行反向代理,使用真正的域名与 HTTPS 证书,并通过不同的域名区分不同的多个实例。
接下来,我们会依次讨论这几个主题:
- 进阶主题:安全加固
- 高可用的 PostgreSQL 集群部署与接入
- 高可用的 MinIO 集群部署与接入
- 使用 S3 服务替代 MinIO
- 使用外部 SMTP 服务发送邮件
- 使用真实域名,证书,通过 Nginx 反向代理
进阶主题:安全加固
Pigsty基础组件
对于严肃的生产部署,我们强烈建议您修改 Pigsty 基础组件的密码。因为这些默认值是公开且众所周知的,不改密码上生产无异于裸奔:
grafana_admin_password
:pigsty
,Grafana管理员密码pg_admin_password
:DBUser.DBA
,PG超级用户密码pg_monitor_password
:DBUser.Monitor
,PG监控用户密码pg_replication_password
:DBUser.Replicator
,PG复制用户密码patroni_password
:Patroni.API
,Patroni 高可用组件密码haproxy_admin_password
:pigsty
,负载均衡器管控密码minio_access_key
:minioadmin
,MinIO 根用户名minio_secret_key
:minioadmin
,MinIO 根用户密钥- 此外,强烈建议您修改 Supabase 使用的 PostgreSQL 业务用户 密码,默认为
DBUser.Supa
以上密码为 Pigsty 组件模块的密码,强烈建议在安装部署前就设置完毕。
Supabase密钥
除了 Pigsty 组件的密码,你还需要 修改 Supabase 的密钥,包括
JWT_SECRET
:ANON_KEY
:SERVICE_ROLE_KEY
:DASHBOARD_USERNAME
: Supabase Studio Web 界面的默认用户名,默认为supabase
DASHBOARD_PASSWORD
: Supabase Studio Web 界面的默认密码,默认为pigsty
这里请您务必参照 Supabase教程:保护你的服务 里的说明:
- 生成一个长度超过 40 个字符的
JWT_SECRET
,并使用教程中的工具签发ANON_KEY
与SERVICE_ROLE_KEY
两个 JWT。 - 使用教程中提供的工具,根据
JWT_SECRET
以及过期时间等属性,生成一个ANON_KEY
JWT,这是匿名用户的身份凭据。 - 使用教程中提供的工具,根据
JWT_SECRET
以及过期时间等属性,生成一个SERVICE_ROLE_KEY
,这是权限更高服务角色的身份凭据。 - 如果您使用的 PostgreSQL 业务用户使用了不同于默认值的密码,请相应修改 `POSTGRES_PASSWORD`` 的值
- 如果您的对象存储使用了不同于默认值的密码,请相应修改
S3_ACCESS_KEY``](https://github.com/pgsty/pigsty/blob/main/conf/app/supa.yml#L57) 与 [
S3_SECRET_KEY`` 的值
Supabase 部分的凭据修改后,您可以重启 Docker Compose 容器以应用新的配置:
./app.yml -t app_config,app_launch
进阶主题:域名接入
如果你在本机或局域网内使用 Supabase,那么可以选择 IP:Port 直连 Kong 对外暴露的 HTTP 8000 端口访问 Supabase。
你可以使用一个内网静态解析的域名,但对于严肃的生产部署,我们建议您使用真域名 + HTTPS 来访问 Supabase。在这种情况下,通常您需要进行以下准备:
- 您的服务器应当有一个公网 IP 地址
- 购买域名,使用 云/DNS/CDN 供应商提供的 DNS 解析服务,将其指向安装节点的公网 IP(下位替代:本地
/etc/hosts
) - 申请证书,使用 Let’s Encrypt 等证书颁发机构签发的免费 HTTPS 证书,用于加密通信(下位替代:默认自签名证书,手工信任)
您可以 参考certbot教程 ,申请免费的 HTTPS 证书,这里我们假设您使用的自定义域名是:supa.pigsty.cc
,那么您应该这样修改 infra_portal
中的 supa
域名:
all:
vars:
infra_portal:
supa :
domain: supa.pigsty.cc # 替换为你的域名!
endpoint: "10.10.10.10:8000"
websocket: true
certbot: supa.pigsty.cc # 证书名称,通常与域名一致即可
如果域名已经解析到了您的服务器的公网 IP,那么在 Pigsty 目录中执行以下命令即可自动完整证书的申请与应用:
make cert
除了 Pigsty 组件的密码,你还需要 修改 Supabase 的域名相关配置,包括
将他们配置为你的自定义域名,例如:supa.pigsty.cc
,然后重新应用配置:
./app.yml -t app_config,app_launch
作为下位替代,您可以使用一个本地域名,来访问 Supabase。
使用本地域名时,您可以在浏览器本机的 /etc/hosts
或局域网 DNS 里来配置 supa.pigsty
的解析,将其指向安装节点的【对外】IP地址。
Pigsty 管理节点上的 Nginx 会为此域名申请自签名的证书(浏览器显示《不安全》),并将请求转发到 8000 端口的 Kong,由 Supabase 处理。
进阶主题:外部对象存储
您可以使用 S3 或 S3 兼容的服务,来作为 PGSQL 备份与 Supabase 使用的对象存储。这里我们使用一个 阿里云 OSS 对象存储作为例子。
Pigsty 提供了一个
terraform/spec/aliyun-meta-s3.tf
模板,用于在阿里云上拉起一台服务器,以及一个 OSS 存储桶。
首先,我们修改 all.children.supa.vars.apps.[supabase].conf
中 S3 相关的配置,将其指向阿里云 OSS 存储桶:
# if using s3/minio as file storage
S3_BUCKET: supa
S3_ENDPOINT: https://sss.pigsty:9000
S3_ACCESS_KEY: supabase
S3_SECRET_KEY: S3User.Supabase
S3_FORCE_PATH_STYLE: true
S3_PROTOCOL: https
S3_REGION: stub
MINIO_DOMAIN_IP: 10.10.10.10 # sss.pigsty domain name will resolve to this ip statically
同样使用以下命令重载 Supabase 配置:
./app.yml -t app_config,app_launch
您同样可以使用 S3 作为 PostgreSQL 的备份仓库,在 all.vars.pgbackrest_repo
新增一个 aliyun
备份仓库的定义:
all:
vars:
pgbackrest_method: aliyun # pgbackrest 备份方法:local,minio,[其他用户定义的仓库...],本例中将备份存储到 MinIO 上
pgbackrest_repo: # pgbackrest 备份仓库: https://pgbackrest.org/configuration.html#section-repository
aliyun: # 定义一个新的备份仓库 aliyun
type: s3 # 阿里云 oss 是 s3-兼容的对象存储
s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
s3_region: oss-cn-beijing
s3_bucket: pigsty-oss
s3_key: xxxxxxxxxxxxxx
s3_key_secret: xxxxxxxx
s3_uri_style: host
path: /pgbackrest
bundle: y
cipher_type: aes-256-cbc
cipher_pass: PG.${pg_cluster} # 设置一个与集群名称绑定的加密密码
retention_full_type: time
retention_full: 14
然后在 all.vars.pgbackrest_mehod
中指定使用 aliyun
备份仓库,重置 pgBackrest 备份:
./pgsql.yml -t pgbackrest
Pigsty 会将备份仓库切换到外部对象存储上。
进阶主题:备份策略
在 supabase 模板中,Pigsty 默认已经使用每天凌晨一点做一次全量备份的备份策略,你可以参考 备份/恢复 中的说明,来修改备份策略。
all:
children:
pg-meta:
hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
vars:
pg_cluster: pg-meta # 每天凌晨一点做个全量备份
node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]
然后执行以下命令,将 Crontab 配置应用到节点上:
./node.yml -t node_crontab
更多关于备份策略的主题,请参考 备份策略
进阶主题:使用SMTP
你可以使用 SMTP 来发送邮件,修改 supabase 应用配置,添加 SMTP 信息:
all:
children:
supa: # supa group
vars: # supa group vars
apps: # supa group app list
supabase: # the supabase app
conf: # the supabase app conf entries
SMTP_HOST: smtpdm.aliyun.com:80
SMTP_PORT: 80
SMTP_USER: [email protected]
SMTP_PASS: your_email_user_password
SMTP_SENDER_NAME: MySupabase
SMTP_ADMIN_EMAIL: [email protected]
ENABLE_ANONYMOUS_USERS: false
不要忘了使用 app.yml -t app_config,app_launch
来重载配置
进阶主题:真·高可用
经过上面的配置,您已经可以使用一个带有公网域名,HTTPS 证书,SMTP 邮件服务器,备份的 Supabase 了。
如果您的这个节点挂了,起码外部 S3 存储中保留了备份,您可以在新的节点上重新部署 Supabase,然后从备份中恢复。 这样的部署在故障时可以提供一个最低标准的 RTO (小时级恢复时长)/ RPO (MB级数据损失)兜底容灾水平 兜底。
但如果您想要达到 RTO < 30s ,零数据丢失,那么就需要用到多节点高可用集群了。多节点部署有三个维度:
- ETCD: DCS 需要使用三个节点或以上,才能容忍一个节点的故障。
- PGSQL: PGSQL 同步提交不丢数据模式,建议使用至少三个节点。
- INFRA:监控基础设施故障影响稍小,但我们建议生产环境使用三副本
- Supabase 本身也可以是多节点的副本,实现高可用
我们建议您参考 trio 与 safe 中的集群配置,将您的集群配置升级到三节点或以上。
在这种情况下,您还需要修改 PostgreSQL 与 MinIO 的接入点,使用 DNS / L2 VIP / HAProxy 等 高可用接入点