Appwrite:开源全栈 BaaS,Firebase 之外的第三条路
Appwrite:开源全栈 BaaS,Firebase 之外的第三条路
当你在构建一个新的 Web 或移动应用时,总会面临一个重复性的工作:从零搭建用户认证、数据库 CRUD、文件存储、消息推送……这些基础设施每次都要重新来过,耗费大量时间。Firebase 解决了这个痛点,但它是 Google 的闭源服务,数据掌握在别人手中,定价也随时可能变化。Supabase 虽然是开源替代品,但它以 PostgreSQL 为核心,更偏向关系型数据库场景。
Appwrite 则走了另一条路:它是一个完全开源的Backend-as-a-Service(BaaS),提供文档数据库、身份认证、文件存储、云函数、实时订阅等全套后端服务,通过 REST API 和官方 SDK 供前端直接调用。本文带你在自己的服务器上完整部署 Appwrite 1.5.7,并演示从创建项目到前端集成的全流程。
Appwrite vs Supabase vs Firebase
| 对比项 | Appwrite | Supabase | Firebase |
|---|---|---|---|
| 数据库类型 | 文档型(自研) | PostgreSQL(关系型) | Firestore(文档型) |
| 开源 | 完全开源 | 开源 | 闭源 |
| 自托管 | 支持 | 支持 | 不支持 |
| 实时订阅 | 支持 | 支持 | 支持 |
| 云函数 | 支持(多语言) | 支持(Deno/TypeScript) | 支持(Node.js 为主) |
| 适用场景 | 全栈应用、移动 App | 数据密集型、复杂查询 | 快速原型 |
如果你的应用更像文档存储(类似 MongoDB 的使用方式),或者需要一个覆盖前端开发所有需求的一站式方案,Appwrite 是比 Supabase 更自然的选择。
服务器配置
Appwrite 内部运行了多个 worker 进程(处理函数执行、邮件发送、文件处理等),对内存有一定要求。推荐使用2 核 4GB 机型作为开发/测试环境,生产环境建议升级到4 核 8GB。
推荐使用雨云服务器 rainyun-com来部署 Appwrite,注册填2026off可领取5 折券。雨云支持按需扩容,非常适合从小规模起步、逐步增长的项目。
环境要求:
- 操作系统:Ubuntu 22.04 LTS
- CPU:2 核及以上
- 内存:4GB 及以上(生产环境 8GB+)
- 磁盘:40GB 及以上(文件存储)
- 开放端口:80、443
安装 Docker 和 Docker Compose
sudoaptupdate&&sudoaptupgrade-ycurl-fsSLhttps://get.docker.com|sudoshsudousermod-aGdocker$USERnewgrpdocker# 验证安装docker--versiondockercompose versionDocker Compose 部署 Appwrite
Appwrite 官方提供了一个交互式安装脚本,通过单条 Docker 命令拉起安装程序,自动生成完整的docker-compose.yml配置:
dockerrun-it--rm\--volume/var/run/docker.sock:/var/run/docker.sock\--volume"$(pwd)"/appwrite:/usr/src/code/appwrite:rw\--entrypoint="install"\appwrite/appwrite:1.5.7安装程序会以交互方式询问以下配置:
? Choose your server HTTP port: 80 ? Choose your server HTTPS port: 443 ? Enter your Appwrite hostname: appwrite.yourdomain.com ? Enter a secret API key: (自动生成,直接回车即可) ? Enter your Appwrite database password: (设置一个强密码) ? Enter your Appwrite Redis password: (设置一个强密码)回答完成后,安装程序会自动生成appwrite/docker-compose.yml和.env文件,并启动所有容器。
Appwrite 内部服务架构
appwrite # 主 API 服务(PHP + Swoole) appwrite-worker-audits # 审计日志 worker appwrite-worker-databases # 数据库操作 worker appwrite-worker-deletes # 数据删除 worker appwrite-worker-functions # 云函数执行 worker appwrite-worker-mails # 邮件发送 worker appwrite-worker-messaging # 消息推送 worker appwrite-worker-migrations # 数据迁移 worker appwrite-worker-webhooks # Webhook worker appwrite-traefik # 反向代理(内置) appwrite-mariadb # 主数据库 appwrite-redis # 缓存 + 队列 appwrite-influxdb # 指标存储 appwrite-telegraf # 指标采集Caddy 反代配置
Appwrite 默认使用内置的 Traefik 处理 HTTPS,如果你希望统一用 Caddy 管理域名,需要修改.env文件关闭 Traefik 的 80/443 绑定,再配置 Caddy 代理到 Appwrite 内部端口。
安装 Caddy:
sudoaptinstall-ydebian-keyring debian-archive-keyring apt-transport-httpscurl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/gpg.key'|sudogpg--dearmor-o/usr/share/keyrings/caddy-stable-archive-keyring.gpgcurl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt'|sudotee/etc/apt/sources.list.d/caddy-stable.listsudoaptupdate&&sudoaptinstallcaddy修改appwrite/.env,将端口改为非 80/443(如 8080/8443),并在/etc/caddy/Caddyfile中添加:
appwrite.yourdomain.com { reverse_proxy localhost:8080 }重载 Caddy:
sudosystemctl reload caddy初始设置:创建账号与项目
访问https://appwrite.yourdomain.com,首次打开会进入注册页面,创建管理员账号后进入控制台。
创建项目
- 点击Create project
- 输入项目名称(如
my-todo-app) - 记录Project ID(后续 SDK 初始化需要)
创建数据库与集合(Collection)
Appwrite 的数据库使用文档模型:数据库(Database)→ 集合(Collection,类似表)→ 文档(Document,类似行)。
在控制台进入Databases→Create database→ 命名为main。
然后创建集合todos,添加以下属性(Attributes):
| 属性名 | 类型 | 必填 |
|---|---|---|
| title | String(255) | 是 |
| completed | Boolean | 是 |
| userId | String(255) | 是 |
在Settings → Permissions中配置权限规则(如允许已登录用户读写自己的文档)。
前端集成:Web SDK 示例
安装 SDK
npminstallappwrite初始化 SDK
// lib/appwrite.jsimport{Client,Databases,Account,Storage,ID,Query}from'appwrite';constclient=newClient().setEndpoint('https://appwrite.yourdomain.com/v1').setProject('YOUR_PROJECT_ID');exportconstaccount=newAccount(client);exportconstdatabases=newDatabases(client);exportconststorage=newStorage(client);export{ID,Query};用户注册与登录
import{account,ID}from'./lib/appwrite';// 注册新用户asyncfunctionregister(email,password,name){try{constuser=awaitaccount.create(ID.unique(),email,password,name);// 注册成功后自动登录awaitaccount.createEmailPasswordSession(email,password);returnuser;}catch(error){console.error('注册失败:',error.message);}}// 登录asyncfunctionlogin(email,password){try{constsession=awaitaccount.createEmailPasswordSession(email,password);returnsession;}catch(error){console.error('登录失败:',error.message);}}// 获取当前用户信息asyncfunctiongetCurrentUser(){try{returnawaitaccount.get();}catch{returnnull;}}// 登出asyncfunctionlogout(){awaitaccount.deleteSession('current');}数据库 CRUD 操作
import{databases,ID,Query}from'./lib/appwrite';constDATABASE_ID='main';constCOLLECTION_ID='todos';// 创建文档asyncfunctioncreateTodo(title,userId){returnawaitdatabases.createDocument(DATABASE_ID,COLLECTION_ID,ID.unique(),{title,completed:false,userId});}// 查询当前用户的所有 TodoasyncfunctionlistTodos(userId){constresponse=awaitdatabases.listDocuments(DATABASE_ID,COLLECTION_ID,[Query.equal('userId',userId),Query.orderDesc('$createdAt')]);returnresponse.documents;}// 更新文档asyncfunctioncompleteTodo(documentId){returnawaitdatabases.updateDocument(DATABASE_ID,COLLECTION_ID,documentId,{completed:true});}// 删除文档asyncfunctiondeleteTodo(documentId){returnawaitdatabases.deleteDocument(DATABASE_ID,COLLECTION_ID,documentId);}文件存储(Storage)
创建存储桶
在控制台进入Storage→Create bucket,命名为avatars,配置允许的文件类型(如image/*)和最大文件大小。
上传与获取文件
import{storage,ID}from'./lib/appwrite';constBUCKET_ID='avatars';// 上传文件(浏览器 File 对象)asyncfunctionuploadAvatar(file){constresponse=awaitstorage.createFile(BUCKET_ID,ID.unique(),file);returnresponse.$id;}// 获取文件预览 URLfunctiongetAvatarUrl(fileId){returnstorage.getFilePreview(BUCKET_ID,fileId,200,200);}// 下载文件functiongetAvatarDownload(fileId){returnstorage.getFileDownload(BUCKET_ID,fileId);}云函数(Functions)
Appwrite Functions 支持 Node.js、Python、PHP、Ruby、Dart 等多种运行时。
创建一个 Node.js 函数
在控制台进入Functions→Create function,选择Node.js 18.0运行时。
函数代码示例(src/index.js):
import{Client,Databases}from'node-appwrite';exportdefaultasync({req,res,log,error})=>{constclient=newClient().setEndpoint(process.env.APPWRITE_FUNCTION_API_ENDPOINT).setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID).setKey(req.headers['x-appwrite-key']??'');constdatabases=newDatabases(client);// 执行业务逻辑constbody=JSON.parse(req.body||'{}');log(`Processing request for user:${body.userId}`);returnres.json({success:true,message:'Function executed!'});};触发函数
import{Functions}from'appwrite';constfunctions=newFunctions(client);constexecution=awaitfunctions.createExecution('YOUR_FUNCTION_ID',JSON.stringify({userId:'user123'}),false// async: false 表示同步等待结果);console.log(execution.responseBody);实时订阅(Realtime)
import{Client}from'appwrite';constclient=newClient().setEndpoint('https://appwrite.yourdomain.com/v1').setProject('YOUR_PROJECT_ID');// 订阅集合变化constunsubscribe=client.subscribe(`databases.main.collections.todos.documents`,(response)=>{if(response.events.includes('databases.*.collections.*.documents.*.create')){console.log('新文档创建:',response.payload);}if(response.events.includes('databases.*.collections.*.documents.*.update')){console.log('文档更新:',response.payload);}});// 取消订阅// unsubscribe();功能使用:OAuth 登录配置
Appwrite 支持 30+ 种 OAuth 提供商(GitHub、Google、Discord 等)。以 GitHub 为例:
- 在 GitHub 创建 OAuth App,回调 URL 设为
https://appwrite.yourdomain.com/v1/account/sessions/oauth2/callback/github/YOUR_PROJECT_ID - 在 Appwrite 控制台 →Auth→Settings→ 启用 GitHub,填入 Client ID 和 Client Secret
- 前端代码:
account.createOAuth2Session('github','https://yourapp.com/dashboard',// 成功回调'https://yourapp.com/login'// 失败回调);结语
Appwrite 将原本需要数周才能搭建的后端基础设施压缩成了几小时的工作——一次部署,获得认证、数据库、存储、函数、实时功能的全套解决方案。对于独立开发者和小团队来说,这是快速验证产品想法、减少重复造轮子的利器。
