符合国情的supabase私有化部署(0)
前言
关注技术前沿的我们,想必对BaaS
都不陌生。从 Firebase
横空出世,再到2014
年的一声炮响。它已经给全世界开发者,带来了大量便捷的,开箱即用的开发运维环境,加上它优秀的开发体验。这让我们程序员们能够以很少的人力成本,做出功能丰富的应用。
然而出于众所周知的原因,它在我们国内是无法使用的。
于是利用这信息不对称的效果:国内一批独立的公司还有一些大厂,对 Firebase
这个产品进行"借鉴" 从而做出了自己的 XXbase
。比如某里云的XXX,某讯云的XXX,还有xxCloud的XXX,等等
然而笔者在比较深度使用国内这些后,发现开发体验不佳。而且很多功能,由于服务的不完善,功能开发不出来,需要额外的服务器去部署功能容器作为辅助。这显然背离了使用 BaaS
的初衷。于是我们这批开发者将眼光投向了开源 BaaS
解决方案.
开源 BaaS
解决方案
笔者主要研究的开源 BaaS
解决方案主要有2
个,一个是 supabase
,另外一个是 appwrite
,当然除此之外还有 amplication
和国人的项目 laf
(向优秀的开源人致敬!)
为什么选择supabase
和 appwrite
呢?因为它们功能成熟,社区稳定,私有化部署便捷,更重要的是它们背后有资本的扶持,比较商业化,不会因为一些莫名其妙的变故,突然跑路,导致项目太监。
另外在线的supabase
服务,虽然在中国可用,但是部署地域只能选择韩国,日本,新加坡,印度等亚洲地区。部署后浅尝辄止地用一下看似可行。一旦深入使用,遇到那些需要对内置功能进行扩展,或者要在里面嵌入自己的后端服务的场景时,一个一个坑就会接踵而至。所以为了避免这些因为网络原因导致的issue
,我们选择私有化部署。
本篇文章就来教你如何一步一步,把 supabase
部署到自己的服务器上。
快速开始
本篇文章以 Linux (ubuntu 22) 服务器为基础平台,假如你是本机测试部署,记得先安装 docker 和 git
获取部署文件
supabase
官方为我们提供了 docker compose
私有化部署的配置目录,就在 github/supabase
master
分支的 docker
目录下。
让我们获取它!
# Get the code
git clone --depth 1 https://github.com/supabase/supabase
# Go to the docker folder
cd supabase/docker
# Copy the fake env vars
cp .env.example .env
# Start 直接使用默认配置
docker compose up -d
假如因为网络原因,拉镜像太慢或者失败,记得提前配置好
dockerhub
的国内源,比如网易源
,百度源
,腾讯源
,阿里源
等等,具体配置方法网上一搜就有。
然后 docker
就跑去拉镜像去了,利用这段时间我们可以先看看 docker-compose.yml
里面到底配置了哪些服务。
服务明细
从配置中,我们可以看到它有这些服务,以及对应的那些镜像:
// docker-compose.yml
const serviceMap = {
// supabase 后台管理系统
studio: 'supabase/studio',
// 大名鼎鼎的云原生网关
kong: 'kong',
// gotrue 原先是 netlify 的项目,主要用来做认证的,目前已经失去维护
// 所以 supabase 自个fork了一份,自己维护了,主要用来管理和校验 jwt token
// 除此之外台还有邮件,手机验证码的发送校验等等许多的功能
auth: 'supabase/gotrue',
// 为 postgres 生成 restful api 来进行常规的 crud 操作
rest: 'postgrest/postgrest',
// 基于 postgres 的 websocket 全双工通信服务
realtime: 'supabase/realtime',
// S3 文件存储服务,同时存储元数据进 postgres
// 个人建议。私有化部署不要用这个服务,因为这不符合国情
// 作为代替,可以使用阿里云/腾讯云的 oss/cos服务
storage: 'supabase/storage-api',
// 图片处理鉴权服务
imgproxy: 'darthsim/imgproxy',
// 为 postgres 生成一套 restful api 来对数据库进行管理,执行命令等等
meta: 'supabase/postgres-meta',
// serverless 函数计算服务,基于 Deno runtime,不是 nodejs 哦
functions: 'supabase/edge-runtime',
// postgres database,核心,强依赖,supabase很多功能依赖这个数据库,换其他的不行
db: 'supabase/postgres'
}
// 另外如果你要开启日志,你还需要同时 apply docker-compose-logging.yml
// docker-compose-logging.yml
// 相比默认额外加了2个服务
const loggingServiceMap = {
// 日志服务
// logflare 被 supabase 收购了
analytics: 'supabase/logflare',
// 高性能的数据日志收集,转化,路由和事件触发服务
// 可以把自己生成的日志转化成,其他云平台需要的格式
vector: 'timberio/vector'
}
不过日志服务依赖 Google Cloud
的 BigQuery
功能,看到 Google
这个关键字,你就明白在国内你是用不了的,
所以不要开启内置日志服务,应该自己处理后接入 阿里云/腾讯云 日志系统。
容器启动后
看到这,现在你的所有镜像应该已经下载完成,并且启动好了吧。
现在直接使用的是 .env.example
里带的默认配置,访问 http://localhost:3000
进入 Supabase Studio
检测一下各项功能是否运转良好,log
功能应该是500
的,因为没有开启。
创建一个前端app
接下来我们创建一个前端app, 这里我们快速创建一个 vite
应用。
然后安装 @supabase/supabase-js
并初始化:
import { createClient } from '@supabase/supabase-js'
// 你的服务器+端口: http://xxx.xxx.xxx.xxx:8000
// 自建服务时候,记得要新建入方向规则安全策略组哦,不然服务器默认只能被访问到 80/443/22 等等端口
// 具体怎么建,你需要看看你的服务商操作文档
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
const supabase = createClient(supabaseUrl, supabaseAnonKey)
接着快速写一个使用邮箱登录页面,然后就能实现登录/注册功能了:
const email = ''
const { error } = await supabase.auth.signInWithOtp({
email
})
然后点击按钮,你就会发现,报错了,为什么注册不了呢?原因在于我们没有配置真实的邮箱配置。
注册邮箱SMTP协议
首先我们找到 .env
的 Email auth
配置,发现需要配置许多的 SMTP_*
配置
这里以大家都有的 QQ邮箱
为例,来把你的 QQ邮箱
作为你这个 supabase实例
发送邮件的邮箱。
首先登录你的 QQ邮箱
,然后右上角你的头像,点击设置:
然后获取授权码,保存好:
接下来就可以这样配置环境变量:
## Email auth
SMTP_ADMIN_EMAIL=icebreaker99@qq.com # 你的邮箱
SMTP_HOST=smtp.qq.com # 固定的
SMTP_PORT=465 # 固定的
SMTP_USER=icebreaker99@qq.com # 你的邮箱
SMTP_PASS=xxxxx # 这里就是你刚刚获取的授权码
SMTP_SENDER_NAME=icebreaker # 发信人
配置好之后,docker compose up -d
重启服务
邮件登录和注册就好了,默认长这样,当然你也可以自定义邮件模板:
是不是特别简单,当然一般正式环境,我们会更换正式的企业邮箱。
jwt token和kong网关配置并应用
我们需要生成和配置自己的秘钥,所以我们利用加密算法生成符合要求的 JWT_SECRET
后,我们可以在 api-keys#Generate JWT 生成相应的 ANON_KEY
和 SERVICE_ROLE_KEY
.
然后同时去修改:
.env
ANON_KEY
SERVICE_ROLE_KEY
volumes/api/kong.yml
anon
service_role
秘钥一定要匹配,不然会报错,然后重启容器应用即可。
更改数据库密码
我们之前一直使用的默认的密码,现在我们要换成自己的密码,然后更换之后,你会开心的发现服务挂了。
这是为什么呢?原因在于数据库已经用你之前的密码初始化完成了,这时候其他服务用了新的密码去连接原先的数据库自然就会挂掉,然后被不断的重启。
那怎么办?实际上也很简单:
还记得 volumes
挂载目录下有很多的脚本吗?其中有一个 volumes/db/roles.sql
,里面就是把新的环境变量设置成密码的脚本
docker exec -it <container_name/id> sh
然后 su postgres
,psql
执行一下搞定。
当然你也可以使用真男人喜欢用的方式:
rm -rf docker/volumes/db/data
k8s 部署参考
目前官方维护的主要是 docker compose
的部署方式,那我们要用 k8s
部署,应该怎么办呢?
社区给我们 2
种解决方案:
详情可以点击链接阅读文档
尾言
通过这种方式,你就可以快速在服务器上部署自己的 supabase
应用,看似很美,不过你访问 studio
的时候会发现,相比在线版本少了很多的功能。毕竟人家是商业项目,给我们用用大部分功能已经很不错了,所以接下来我们就需要自己写一套后端,来接入这套机制,从而自己去开发一些定制化的功能。
不过文章写到这也太长了,一般到这能完整的部署一套的也比较少了,就让我挖个坑下期再见吧。
常见问题
name resolution failed
这是由于你 kong
网关里转发的某些服务没有正常启动,报的错误,你可以 docker ps -f name=supa
看看哪些服务是异常的,并使用 docker logs
查看异常容器里的日志进行处理。
password authentication failed for user \"authenticator\"\n","hint":null,"message":"Database connection error. Retrying the connection."}
{"level":"info","msg":"Go runtime metrics collection started"}
{"args":[0.018145916],"component":"pop","level":"info","msg":"%.4f seconds"}
{"level":"fatal","msg":"running db migrations: Migrator: problem creating schema migrations: couldn't start a new transaction: could not create new transaction: failed to connect to `host=db user=supabase_auth_admin database=postgres`: failed SASL auth (FATAL: password authentication failed for user \"supabase_auth_admin\" (SQLSTATE 28P01))"}
Invalid authentication credentials
由于更改了数据库的用户密码,导致 auth
和 rest
这些服务因为数据库授权原因,挂了,一直在重启
这是由于你没有同时在 .env
和 volumes/api/kong.yml
里配置同样的 anon
和 service
Key
,配置好了之后重启一下容器/重启一下 kong
参考链接
https://supabase.com/docs/guides/self-hosting
https://github.com/supabase-community/supabase-kubernetes
https://kubernetes.io/docs/tasks/configure-pod-container/translate-compose-kubernetes/
https://supabase.com/docs/reference/self-hosting-analytics/introduction