AIRI 后端(AIRI Backend)本地部署与 Railway 生产部署完整指南
AIRI 后端AIRI Backend本地部署与 Railway 生产部署完整指南【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi本篇技术指南围绕 Project AIRI 的托管后端hosted backend展开全面讲解server/目录的架构布局、本地一键启动流程pnpm dev:backend Docker Compose 五服务栈、以及基于 Railway 的生产部署方式Resource API 与 Auth 双服务、Config File Path、健康检查与定向私有链接配置。读完本文你将掌握如何在本地跑起包含 PostgreSQLvchord 向量扩展、Redis、API、Auth 与 Caddy 网关的完整后端并按照服务到服务契约在 Railway 上正确配置跨服务变量与迁移归属避免常见的 JWT issuer 不匹配与迁移竞态问题。后端在仓库中的位置与总体职责AIRI 的托管后端源码集中在仓库的server/目录下。这里需要注意一个明确的边界应用仓库只承载服务源码与数据库归属生产部署拓扑生产 Caddy 路由、OpenTelemetry Collector 配置、可观测性存储、Grafana 面板存放在proj-airi/airi-railway中避免部署拓扑在应用仓库内重复维护参见 server/README.md。从仓库根目录看后端整体由以下部分组成server/apps/api资源 APIResource API承载业务域、数据库迁移与 API 运行时server/apps/auth独立的 Better Auth 与 OIDC 服务server/packages/auth-sharedAuth 归属的数据库 schema 与主体验证principal契约server/packages/server-sdk-shared托管聊天 WebSocket 的 Eventa 契约server/dev/caddy仅本地使用的公共边缘路由为共享的 Auth/API 来源服务server/docker-compose.yaml完整的本地 API Auth PostgreSQL Redis Caddy 栈。本地运行一条命令拉起完整后端从仓库根目录执行pnpm dev:backend该命令在根 package.json 中定义为dev:backend: docker compose -f server/docker-compose.yaml up --build它会读取 server/docker-compose.yaml构建并启动全部服务但只对外暴露 Caddy 网关http://localhost:6112API 与 Auth 的容器端口保持在内部网络不直接暴露给宿主机。本地栈的五个服务server/docker-compose.yaml 定义了完整的本地后端栈compose 项目名为proj-airi-backend服务镜像 / 构建来源关键配置dbghcr.io/tensorchord/vchord-postgres:pg18-v1.0.0端口127.0.0.1:5435:5432挂载./apps/api/sql/init.sql到/docker-entrypoint-initdb.d/init.sql健康检查pg_isreadyredisredis:7-alpine端口127.0.0.1:6379:6379健康检查redis-cli pingapiserver/apps/api/Dockerfile启动命令pnpm -F proj-airi/api-server start依赖 db/redis 健康后启动authserver/apps/auth/Dockerfile启动命令pnpm -F proj-airi/auth-server start依赖 api 健康后启动caddycaddy:2-alpine端口127.0.0.1:6112:3000挂载./dev/caddy/Caddyfile注意两个细节数据库使用 vchord PostgreSQL。初始化脚本 server/apps/api/sql/init.sql 的内容只有一行CREATE EXTENSION vchord CASCADE;也就是说本地数据库首次初始化时会启用vchord向量扩展——这是 AIRI 后端数据库带向量检索能力的直接证据vchord 为 pgvector 兼容的向量索引方案。API 与 Auth 通过 env_file 读取可选环境文件./apps/api/.env与./apps/api/.env.localrequired: false并以environment块注入核心变量。本地栈中 API 的AUTH_SERVER_URL与 Auth 的PUBLIC_URL均被显式设为http://localhost:6112与 Caddy 网关地址一致保证本地 JWT issuer 校验一致。本地 Caddy 路由规则server/dev/caddy/Caddyfile 是本地公共边缘的唯一入口规则清晰对应生产语义:3000 { route { internal path /internal /internal/* respond internal 404 auth path /api/auth /api/auth/* /auth /auth/* /.well-known/oauth-authorization-server/api/auth reverse_proxy auth auth:3000 reverse_proxy api:3000 } }要点/internal/*在公共边缘直接 404 拒绝保证内部 Auth→API 调用边界不暴露Auth 相关路径/api/auth/*、/auth/*以及 OAuth 授权服务器发现端点反向代理到auth:3000其余请求全部转发到api:3000。按服务单独开发的命令若需要源码级调试可以跳过 compose 而分别启动两个服务。API 侧见 server/apps/api/README.mdpnpm -F proj-airi/api-server dev pnpm -F proj-airi/api-server typecheck pnpm -F proj-airi/api-server exec vitest run pnpm -F proj-airi/api-server buildAuth 侧见 server/apps/auth/README.mdpnpm -F proj-airi/auth-server devAuth 服务从自身目录读取.env.local。PUBLIC_URL是经 Caddy 对外呈现的公共 issuer 来源RESOURCE_SERVER_URL是用于内部调用的私有资源 API 地址。两个服务的职责边界Resource APIproj-airi/api-server根据 server/apps/api/README.md其职责包括Hono 业务 API 与 WebSocket 端点角色characters、聊天chats、提供商providers、Flux、Stripe、模型路由与计费共享数据库的 PostgreSQL 迁移所有权Drizzle 在启动时读取检入checked-in的drizzle/journal 与 SQL 文件Redis 缓存、配置 KV 与跨实例 Pub/Sub通过公共 JWKS 本地校验 Auth 签发的 OIDC JWT。从源码布局看API 路由覆盖了routes/下的chat-wsv1/v2 两代 WebSocket 协议含未认证对等方与 payload 限流、openai/v1OpenAI 兼容网关含 billing、telemetry、traffic-control 中间件与 chat-completions/speech-catalog/speech-generation 操作、stripecheckout/webhook 与价格目录、characters、chats、providers、voice-packs、flux、audio-speech-ws、audio-transcription-stream等模块services/domain/下则承载计费、llm-router并发账本、配置加载、密钥轮换、错误映射、llm-tracing、provider-catalog、user-deletion 等业务域。它同时提供/readyz健康检查与 OpenTelemetry 仪表见src/otel/gauges/下的 db-pool、tts-pool、ws-online-users 等 gauge。Authproj-airi/auth-server根据 server/apps/auth/README.md其职责包括Better Auth 会话、社交登录、magic-link、密码与 OIDC 流程/api/auth/*、/auth/*与认证发现端点Auth 归属的 Redis 配置、事务邮件与认证遥测删除业务数据前通过私有网络调用资源 API。其代码刻意保持扁平主要边界为auth.tsBetter Auth 配置与身份生命周期钩子、routes.ts完整公共 Auth HTTP 面与请求认证、server.ts依赖组合、健康检查与进程生命周期、resource-api.ts唯一的 Auth→资源 API 私有边界、rate-limit.ts与otel.ts跨路由运维策略、email.ts与oidc-jwt-bearer.ts大型外部集成模块。明确不做的事产品 API、计费、模型路由、聊天或 WebSocket 业务状态导入server/apps/api的模块在正常进程启动时运行共享数据库迁移历史。Auth 的表与主体验证契约全部来自proj-airi/auth-shared共享迁移文件由 API 启动时由 Drizzle 读取——迁移所有权始终在 API 侧。Railway 生产部署API 与 Auth 是同一仓库构建出的两个独立 Railway 长期运行服务。核心约束是每个服务的 Root Directory 必须保持在仓库根目录因为两份 Dockerfile 都需要从该构建上下文复制 workspace 清单与共享包。两份 Dockerfile 的构建输入API 的 server/apps/api/Dockerfile生产用 Railway 专用版位于 server/apps/api/production/railway/Dockerfile内容一致基于node:24-alpine启用 corepack复制pnpm-lock.yaml、pnpm-workspace.yaml、package.json、tsconfig.json、patches/再复制server/apps/api、server/packages/auth-shared、server/packages/server-sdk-shared随后以--frozen-lockfile --ignore-scripts安装依赖先后构建proj-airi/server-sdk-shared与proj-airi/api-server并以非 root 用户airi运行EXPOSE 3000。Auth 的 server/apps/auth/Dockerfile 与之类似但只复制server/apps/auth与server/packages/auth-shared它不消费 server-sdk-shared安装命令带--filter proj-airi/auth-server...过滤。在 Railway 中显式配置 Config File Path由于仓库根目录下没有默认的railway.toml必须为每个服务显式指定 Config File Path服务Config File Path公共角色私有依赖Resource API/server/apps/api/railway.toml产品与资源 APIAuth issuer 与 JWKSAuth/server/apps/auth/railway.tomlBetter Auth 与 OIDC issuerResource API 的删除端点server/apps/api/railway.toml 的实际内容[build] builder DOCKERFILE dockerfilePath /server/apps/api/production/railway/Dockerfile watchPatterns [ server/apps/api/**, server/packages/auth-shared/**, server/packages/server-sdk-shared/**, package.json, pnpm-lock.yaml, pnpm-workspace.yaml, tsconfig.json, patches/** ] [deploy] startCommand pnpm -F proj-airi/api-server start healthcheckPath /readyz healthcheckTimeout 100server/apps/auth/railway.toml 与之对应dockerfilePath 为/server/apps/auth/DockerfilewatchPatterns 不包含server/packages/server-sdk-shared/**启动命令为pnpm -F proj-airi/auth-server start。每一份 config 都自持 Dockerfile、启动命令、/readyz健康检查与 watch 模式。只有当变更触及该服务本身、其复制的某个共享包、或复制的根构建输入时该服务才会触发部署——例如只修改server/apps/api/**不会让 Auth 重新构建。服务到服务的变量契约关键共享数据库、Redis 与可观测性变量应使用Railway 引用变量reference variables在两个服务间传递而不是复制敏感值。两个方向的私有链接按如下配置消费方变量值来源用途Resource APIAUTH_SERVER_URLAuth 的规范公共 issuer URLJWT issuer、audience 与公共 JWKS 身份Resource APIAUTH_SERVER_INTERNAL_URLAuth 的 Railway 私有域名私有网络内拉取 JWKS不会改变 issuer 校验AuthPUBLIC_URLAuth 的规范公共 issuer URLBetter Auth 与 OIDC issuer URL必须等于 API 的AUTH_SERVER_URLAuthRESOURCE_SERVER_URLAPI 的 Railway 私有域名删除用户业务数据前的私有调用两个最容易踩的坑issuer 必须严格一致PUBLIC_URL与AUTH_SERVER_URL必须是同一个值。否则 API 校验 JWT 的 issuer/audience 会失败。AUTH_SERVER_INTERNAL_URL只是私有 JWKS 拉取通道即便它指向私有域名也不影响 issuer 与 audience 的校验逻辑issuer 依旧取AUTH_SERVER_URL。/internal/*必须保持私有Auth 通过私有域名调用 API 的内部路径公共路由Caddy 边缘必须拒绝/internal/*且 API 服务不应有独立的公共入口参见 server/apps/api/README.md 与 Caddyfile 中respond internal 404的实现。代理信任与限流只有在直接接收 Railway 代理流量的服务上才设置RATE_LIMIT_TRUSTED_PROXYrailway。该标志会告知限流中间件server/apps/api/src/middlewares/rate-limit.ts与 Auth 的rate-limit.ts信任 Railway 代理转发从而正确解析客户端真实 IP误设会导致任意请求伪造X-Forwarded-For绕过限流。迁移归属与部署成功判据API 是共享数据库迁移的唯一 owner不要给 Auth 添加 Railway pre-deploy 迁移命令也不要让 Auth 启动时执行共享迁移。共享迁移在 API 启动时由 Drizzle 读取drizzle/journal 与 SQL 文件执行API 侧迁移文件位于 server/apps/api/drizzle/ 下包含 00000022 共 23 个 SQL 迁移及对应 snapshot。部署成功 ≠ 就绪任一个服务部署后Railway 必须从该服务的/readyz收到200。健康检查超时在 railway.toml 中配置为healthcheckTimeout 100。只有当/readyz返回 200才说明服务能连上其依赖数据库、Redis、对端服务仅凭部署完成不能证明服务可达。包边界与契约的归属AIRI 对后端包的放置有明确规则见 server/README.md前端应用保持在根apps/下定义了资源 API 协议的托管后端包可以放在server/packages/下即使前端消费其生成的契约例如 server/packages/server-sdk-shared 承载托管聊天 WebSocket 的 Eventa 契约跨运行时的服务器 SDK 与协议包仍放在根packages/下因为 Web、Electron、插件与独立服务都要消费它们server/packages/auth-shared 是 Auth 归属的数据库 schema 与主体验证契约Auth 表结构集中于此API 与 Auth 均引用它而二者互不 import 对方的应用模块见 server/apps/api/README.mdno module under server/apps/auth is imported。这种协议归服务、跨运行时归根包的划分配合 Railway 的 watchPatterns 精准控制构建触发范围让 API 与 Auth 两个服务在共享同一仓库、同一数据库的前提下仍能保持独立部署与演进。生产可观测性拓扑的去向生产环境的 Caddy 路由、OpenTelemetry Collector 配置、可观测性存储与 Grafana 面板不在本应用仓库内而统一维护在proj-airi/airi-railway以保持应用仓库 代码与契约、部署仓库 拓扑与观测的职责分离。应用仓库内只保留本地开发用的 Caddyfile 与 server/docker-compose.yaml如需扩展本地可观测性可围绕server/apps/api/src/otel/的仪表与脚本server/apps/api/src/scripts/otel/下的 http-smoke、ws-smoke、smoke自行接入。小结AIRI 后端的核心设计可以概括为三条主线本地一条命令可复现pnpm dev:backend拉起 vchord PostgreSQL Redis API Auth Caddy 完整栈且只有 Caddy 网关暴露在localhost:6112生产两服务强契约API资源域 迁移 owner与 Auth身份与 OIDC issuer共享同一数据库通过PUBLIC_URL AUTH_SERVER_URL、AUTH_SERVER_INTERNAL_URL私有 JWKS、RESOURCE_SERVER_URL私有删除回调四个变量 私有/internal/*边界完成安全互通部署粒度精细可控每份 railway.toml 自持 Dockerfile、start command、/readyz与 watchPatterns只有触及服务自身或其复制的共享包才触发部署配合部署成功需以/readyz200 为准的判据保障变更安全。如需在 Railway 上部署请严格按照Root Directory 保持仓库根目录 Config File Path 指向各自 railway.toml 定向私有链接 迁移仅由 API 执行的契约配置任何对PUBLIC_URL/AUTH_SERVER_URL的改动都需要同时同步到两个服务后一并部署验证。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考