<p/><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/3895637-c2369f086893d8e8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>
</p><p><strong>前言</strong></p><p>关注技术前沿的我们,想必对<strong>BaaS</strong> 都不陌生。从 <strong>Firebase</strong> 横空出世,再到<strong>2014</strong>年的一声炮响。它已经给全世界开发者,带来了大量便捷的,开箱即用的开发运维环境,加上它优秀的开发体验。这让我们程序员们能够以很少的人力成本,做出功能丰富的应用。</p><p>然而出于众所周知的原因,它在我们国内是无法使用的。</p><p>于是利用这信息不对称的效果:国内一批独立的公司还有一些大厂,对 <strong>Firebase</strong> 这个产品进行"借鉴" 从而做出了自己的 <strong>XXbase</strong>。比如某里云的XXX,某讯云的XXX,还有xxCloud的XXX,等等</p><p>然而笔者在比较深度使用国内这些后,发现开发体验不佳。而且很多功能,由于服务的不完善,功能开发不出来,需要额外的服务器去部署功能容器作为辅助。这显然背离了使用 <strong>BaaS</strong> 的初衷。于是我们这批开发者将眼光投向了开源 <strong>BaaS</strong>解决方案.</p><p><strong>开源 </strong></p><p>笔者主要研究的开源 <strong>BaaS</strong> 解决方案主要有<strong>2</strong>个,一个是 <strong>supabase</strong> ,另外一个是 <strong>appwrite</strong>,当然除此之外还有 <strong>amplication</strong> 和国人的项目 <strong>laf</strong>(向优秀的开源人致敬!)</p><p>为什么选择<strong>supabase</strong> 和 <strong>appwrite</strong> 呢?因为它们功能成熟,社区稳定,私有化部署便捷,更重要的是它们背后有资本的扶持,比较商业化,不会因为一些莫名其妙的变故,突然跑路,导致项目太监。</p><p>另外在线的<strong>supabase</strong>服务,虽然在中国可用,但是部署地域只能选择韩国,日本,新加坡,印度等亚洲地区。部署后浅尝辄止地用一下看似可行。一旦深入使用,遇到那些需要对内置功能进行扩展,或者要在里面嵌入自己的后端服务的场景时,一个一个坑就会接踵而至。所以为了避免这些因为网络原因导致的<strong>issue</strong>,我们选择私有化部署。</p><p>本篇文章就来教你如何一步一步,把 <strong>supabase</strong> 部署到自己的服务器上。</p><p><strong>快速开始</strong></p><blockquote><p>本篇文章以 Linux (ubuntu 22) 服务器为基础平台,假如你是本机测试部署,记得先安装 docker 和 git</p></blockquote><p><strong>获取部署文件</strong></p><p><strong>supabase</strong> 官方为我们提供了 <strong>docker compose</strong> 私有化部署的配置目录,就在 <strong>github/supabase</strong> <strong>master</strong>分支的 <strong>docker</strong> 目录下。</p><p>让我们获取它!</p><pre># Get the code
git clone --depth 1
Go to the docker folder
cd supabase/docker
Copy the fake env vars
cp .env.example .env
Start 直接使用默认配置
docker compose up -d</pre><blockquote><p>假如因为网络原因,拉镜像太慢或者失败,记得提前配置好 <strong>dockerhub</strong> 的国内源,比如 <strong>网易源</strong>,<strong>百度源</strong>,<strong>腾讯源</strong>,<strong>阿里源</strong> 等等,具体配置方法网上一搜就有。</p></blockquote><p>然后 <strong>docker</strong> 就跑去拉镜像去了,利用这段时间我们可以先看看 <strong>docker-compose.yml</strong> 里面到底配置了哪些服务。</p><p><strong>服务明细</strong></p><p>从配置中,我们可以看到它有这些服务,以及对应的那些镜像:</p><pre>// docker-compose.ymlconst 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'
}</pre><p>不过日志服务依赖 <strong>Google Cloud</strong> 的 <strong>BigQuery</strong> 功能,看到 <strong>Google</strong> 这个关键字,你就明白在国内你是用不了的,</p><p>所以不要开启内置日志服务,应该自己处理后接入 阿里云/腾讯云 日志系统。</p><p><strong>容器启动后</strong></p><p>看到这,现在你的所有镜像应该已经下载完成,并且启动好了吧。</p><p>现在直接使用的是 <strong>.env.example</strong> 里带的默认配置,访问 <strong>http://localhost:3000</strong> 进入 <strong>Supabase Studio</strong></p><p>检测一下各项功能是否运转良好,<strong>log</strong>功能应该是<strong>500</strong>的,因为没有开启。</p><p><strong>创建一个前端app</strong></p><p>接下来我们创建一个前端app, 这里我们快速创建一个 <strong>vite</strong> 应用。</p><p>然后安装 <strong>@supabase/supabase-js</strong> 并初始化:</p><pre>import { createClient } from '@supabase/supabase-js'
// 你的服务器+端口:
// 自建服务时候,记得要新建入方向规则安全策略组哦,不然服务器默认只能被访问到 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)</pre><p>接着快速写一个使用邮箱登录页面,然后就能实现登录/注册功能了:</p><pre>const email = ''
const { error } = await supabase.auth.signInWithOtp({
email})</pre><p>然后点击按钮,你就会发现,报错了,为什么注册不了呢?原因在于我们没有配置真实的邮箱配置。</p><p><strong>注册邮箱SMTP协议</strong></p><p>首先我们找到 <strong>.env</strong> 的 <strong>Email auth</strong> 配置,发现需要配置许多的 <strong>SMTP_*</strong>配置</p><p>这里以大家都有的 <strong>QQ邮箱</strong> 为例,来把你的 <strong>QQ邮箱</strong> 作为你这个 <strong>supabase实例</strong>发送邮件的邮箱。</p><p>首先登录你的 <strong>QQ邮箱</strong>,然后右上角你的头像,点击设置:</p><p>
</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/3895637-aa705eabe630dfb9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>
</p><p>然后获取授权码,保存好:</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/3895637-47da5ea475102b90.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>
</p><p>接下来就可以这样配置环境变量:</p><pre>## 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 # 发信人</pre><p>配置好之后,<strong>docker compose up -d</strong> 重启服务</p><p>邮件登录和注册就好了,默认长这样,当然你也可以自定义邮件模板:</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/3895637-2bc5969b1acbe2ed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>Image</p><p class="image-package"><img class="uploaded-img" src="https://upload-images.jianshu.io/upload_images/3895637-db951f1937090618.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" width="auto" height="auto"/></p><p>Image</p><p>
</p><p>是不是特别简单,当然一般正式环境,我们会更换正式的企业邮箱。</p><p><strong>jwt token和kong网关配置并应用</strong></p><p>我们需要生成和配置自己的秘钥,所以我们利用加密算法生成符合要求的 <strong>JWT_SECRET</strong> 后,我们可以在 <a>api-keys#Generate JWT</a> 生成相应的 <strong>ANON_KEY</strong> 和 <strong>SERVICE_ROLE_KEY</strong>.</p><p>然后同时去修改:</p><ul><li><p><strong>.env</strong></p></li><ul><li><p><strong>ANON_KEY</strong></p></li><li><p><strong>SERVICE_ROLE_KEY</strong></p></li></ul><li><p><strong>volumes/api/kong.yml</strong></p></li><ul><li><p><strong>anon</strong></p></li><li><p><strong>service_role</strong></p></li></ul></ul><p>秘钥一定要匹配,不然会报错,然后重启容器应用即可。</p><p><strong>更改数据库密码</strong></p><p>我们之前一直使用的默认的密码,现在我们要换成自己的密码,然后更换之后,你会开心的发现服务挂了。</p><p>这是为什么呢?原因在于数据库已经用你之前的密码初始化完成了,这时候其他服务用了新的密码去连接原先的数据库自然就会挂掉,然后被不断的重启。</p><p>那怎么办?实际上也很简单:</p><p>还记得 <strong>volumes</strong> 挂载目录下有很多的脚本吗?其中有一个 <strong>volumes/db/roles.sql</strong>,里面就是把新的环境变量设置成密码的脚本</p><p><strong>docker exec -it <container_name/id> sh</strong> 然后 <strong>su postgres</strong> ,<strong>psql</strong> 执行一下搞定。</p><p>当然你也可以使用真男人喜欢用的方式:</p><pre>rm -rf docker/volumes/db/data</pre><p><strong>k8s 部署参考</strong></p><p>目前官方维护的主要是 <strong>docker compose</strong> 的部署方式,那我们要用 <strong>k8s</strong> 部署,应该怎么办呢?</p><p>社区给我们 <strong>2</strong> 种解决方案:</p><ol><li><p><a>supabase-kubernetes</a></p></li><li><p><a>kompose</a></p></li></ol><p>详情可以点击链接阅读文档</p><p><strong>尾言</strong></p><p>通过这种方式,你就可以快速在服务器上部署自己的 <strong>supabase</strong> 应用,看似很美,不过你访问 <strong>studio</strong> 的时候会发现,相比在线版本少了很多的功能。毕竟人家是商业项目,给我们用用大部分功能已经很不错了,所以接下来我们就需要自己写一套后端,来接入这套机制,从而自己去开发一些定制化的功能。</p><p>不过文章写到这也太长了,一般到这能完整的部署一套的也比较少了,就让我挖个坑下期再见吧。</p><p><strong>常见问题</strong></p><p><strong><strong>name resolution failed</strong></strong></p><p>这是由于你 <strong>kong</strong> 网关里转发的某些服务没有正常启动,报的错误,你可以 <strong>docker ps -f name=supa</strong> 看看哪些服务是异常的,并使用 <strong>docker logs</strong> 查看异常容器里的日志进行处理。</p><pre>password authentication failed for user "authenticator"\n","hint":null,"message":"Database connection error. Retrying the connection."}</pre><pre>{"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))"}</pre><p><strong><strong>Invalid authentication credentials</strong></strong></p><p>由于更改了数据库的用户密码,导致 <strong>auth</strong> 和 <strong>rest</strong> 这些服务因为数据库授权原因,挂了,一直在重启</p><p>这是由于你没有同时在 <strong>.env</strong> 和 <strong>volumes/api/kong.yml</strong> 里配置同样的 <strong>anon</strong> 和 <strong>service</strong> <strong>Key</strong>,配置好了之后重启一下容器/重启一下 <strong>kong</strong></p><p><strong>参考链接</strong></p><p><a>https://supabase.com/docs/guides/self-hosting</a></p><p><a>https://github.com/supabase-community/supabase-kubernetes</a></p><p><a>https://kubernetes.io/docs/tasks/configure-pod-container/translate-compose-kubernetes/</a></p><p><a>https://supabase.com/docs/refer</a></p><p>
</p>