news 2026/9/11 6:15:53

Vibe Kanban Remote 云端服务本地开发与自托管部署完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vibe Kanban Remote 云端服务本地开发与自托管部署完全指南

Vibe Kanban Remote 云端服务本地开发与自托管部署完全指南

【免费下载链接】vibe-kanbanGet 10X more out of Claude Code, Codex or any coding agent项目地址: https://gitcode.com/GitHub_Trending/vi/vibe-kanban

本篇指南围绕开源仓库 Vibe Kanban 的remotecrate(托管云端 API 与 Web 应用)展开,完整讲解如何在本机拉起remote-dbremote-serverelectric三件套,如何配置 JWT 密钥、OAuth(GitHub/Google)或自托管本地认证,如何启用 relay 隧道与本地附件存储,以及如何通过 Caddy 在本地终止 TLS 完成端到端联调。读完本文,你可以把整条云端链路(Postgres → ElectricSQL → REST API → React 前端 → 桌面客户端)跑通,并理解其底层的 ElectricSQL 同步、txid握手机制与类型生成流程。

Remote 服务是什么

remotecrate 是 Vibe Kanban 的托管云端服务端,位于 crates/remote(其主文档为 crates/remote/README.md)。它由三部分组成:

  • Axum HTTP API:对外暴露/v1/*REST 接口,负责认证、组织/项目/Issue/PR 等 CRUD、Webhook 与导出;
  • React SPA 前端packages/remote-web,由 Vite 构建后在容器内通过/srv/static兜底托管;
  • ElectricSQL 实时同步层:Postgres → ElectricSQL → 客户端按 HTTP Shape 订阅增量。

从 crates/remote/src/app.rs 的启动流程可以看到服务端启动顺序为:创建 Postgres 连接池 → 运行 SQLx 迁移 → 创建electric_sync角色并设置密码 → 同步 Electric 发布 → 初始化 JWT/OAuth 服务 → 组装路由 → 监听SERVER_LISTEN_ADDR。这个启动顺序(先跑迁移、后起 Electric)是整套系统能正常工作的关键前提。

本地环境准备:创建.env.remote

在启动前,需要在crates/remote/.env.remote中准备环境变量。README 给出的最小配置如下:

# Required VIBEKANBAN_REMOTE_JWT_SECRET=replace_with_openssl_rand_base64_48 ELECTRIC_ROLE_PASSWORD=replace_with_secure_password # Configure at least one auth option GITHUB_OAUTH_CLIENT_ID= GITHUB_OAUTH_CLIENT_SECRET= GOOGLE_OAUTH_CLIENT_ID= GOOGLE_OAUTH_CLIENT_SECRET= # Or use bootstrap local auth for self-hosting SELF_HOST_LOCAL_AUTH_EMAIL= SELF_HOST_LOCAL_AUTH_PASSWORD= # Optional PUBLIC_BASE_URL=http://localhost:3000 VITE_RELAY_API_BASE_URL=http://localhost:8082 VITE_PUBLIC_REACT_VIRTUOSO_LICENSE_KEY= LOOPS_EMAIL_API_KEY= # Loops transactional email template IDs (optional — defaults are the upstream templates). # Override these with your own Loops account template IDs if using a custom Loops account. LOOPS_INVITE_TEMPLATE_ID=cmhvy2wgs3s13z70i1pxakij9 LOOPS_REVIEW_READY_TEMPLATE_ID=cmj47k5ge16990iylued9by17 LOOPS_REVIEW_FAILED_TEMPLATE_ID=cmj49ougk1c8s0iznavijdqpo

JWT 密钥必须一次性生成,README 给出的命令是:

openssl rand -base64 48

环境变量的实际解析规则(源码级)

这些变量最终被 crates/remote/src/config.rs 中的RemoteServerConfig::from_env()消费,几个关键约束值得注意:

  • VIBEKANBAN_REMOTE_JWT_SECRET:必填。AuthConfig::from_env()会先对其做 Base64 解码校验,解码后字节长度小于 32 会直接报InvalidVar(见validate_jwt_secret)。因此不能用随意字符串,必须用openssl rand -base64 48这类命令生成。
  • 空字符串即未配置:配置解析统一遵循“空字符串当作未设置”的约定。例如GITHUB_OAUTH_CLIENT_ID为空时 GitHub OAuth 被视为禁用。Docker Compose 的${VAR:-}展开会产生空串,而std::env::var()对空串返回Ok(""),所以源码里处处用!v.is_empty()做判断,这是本仓库的一条重要约定(crates/remote/AGENTS.md 中也有专门提醒)。
  • 认证三选一:GitHub、Google、本地认证(SELF_HOST_LOCAL_AUTH_EMAIL+SELF_HOST_LOCAL_AUTH_PASSWORD)三者都未配置时,启动会失败并返回ConfigError::NoOAuthProviders。注意本地认证必须邮箱、密码成对出现,只填其一同样报MissingVar
  • ELECTRIC_ROLE_PASSWORD:会通过ensure_electric_role_password()写入 Postgres 的electric_sync角色,ElectricSQL 容器用同一密码连接数据库(docker-compose.yml 中DATABASE_URL引用了它)。
  • 可选扩展:除 README 列出的变量外,docker-compose.yml 还支持DIGEST_ENABLED(通知摘要开关,默认false)、R2_*(R2 制品存储)、REVIEW_WORKER_BASE_URLGITHUB_APP_*(GitHub App 集成)、STRIPE_*(计费,私有依赖)以及AZURE_STORAGE_*(附件存储)等,按需配置即可。

启动完整技术栈

从仓库根目录执行:

pnpm run remote:dev

该命令默认只启动核心三件套(不含 relay 与附件存储)。如需完整栈(relay + 本地附件存储):

pnpm run remote:dev:full

手动执行的等价命令(即 README 中给出的方式):

cd crates/remote docker compose --env-file .env.remote up --build

这会启动三个容器:

  • remote-db:PostgreSQL 16,wal_level=logical,监听宿主机5433端口;
  • remote-server:Axum 服务,Dockerfile 采用“Node(前端构建)→ Rust(服务编译)→ Debian slim(运行)”的多阶段构建,前端产物打进镜像的/srv/static
  • electric:ElectricSQL 1.4.13,通过逻辑复制订阅 Postgres 并把变更流以 Shape 形式经 HTTP 推给客户端。

启动后的默认端点:

  • Remote Web UI/API:http://localhost:3000
  • Postgres:postgres://remote:remote@localhost:5433/remote

可选 Profile:relay 与 attachments

Docker Compose 通过 profile 控制可选组件(定义见 docker-compose.yml):

启用 relay 支持(relayprofile),多出一个relay-server容器,即 Vibe Kanban 的隧道中继服务:

cd crates/remote docker compose --env-file .env.remote --profile relay up --build

启用后新增端点:

  • Relay API:http://localhost:8082

启用本地附件存储(attachmentsprofile),用 Azurite 模拟 Azure Blob:

cd crates/remote docker compose --env-file .env.remote --profile attachments up --build

该 profile 会启动azurite(Blob 服务,端口10000)与azurite-init(自动创建issue-attachments容器并配置 CORS)。

两者同时启用

cd crates/remote docker compose --env-file .env.remote --profile relay --profile attachments up --build

从 Compose 配置看,remote-serverdepends_onazurite-init使用了required: false,因此 attachments profile 未启用时不会阻塞启动。

本地 HTTPS:用 Caddy 终止 TLS

如需在本地以 HTTPS 联调 OAuth 回调或 relay 隧道,可以使用仓库根目录提供的 Caddyfile.example 作为反向代理。

安装 Caddy

# macOS brew install caddy # Debian/Ubuntu sudo apt install caddy

启动 Caddy

在仓库根目录另开一个终端:

caddy run --config Caddyfile.example

首次运行时 Caddy 会安装本地 CA 证书(可能提示输入密码)。通过 Caddyfile.example 的路由规则,你获得:

  • https://localhost:3001→ remote Web UI/API(反代127.0.0.1:3000
  • https://relay.localhost:3001→ relay API(反代127.0.0.1:8082,需要relayprofile)

相应地,OAuth 回调地址要更新为:

  • GitHubhttps://localhost:3001/v1/oauth/github/callback
  • Googlehttps://localhost:3001/v1/oauth/google/callback

端到端验证 relay 隧道

在另一个终端设置环境变量并启动桌面端:

export VK_SHARED_API_BASE=https://localhost:3001 export VK_SHARED_RELAY_API_BASE=https://relay.localhost:3001 pnpm run dev

快速健康检查:

curl -sk https://localhost:3001/v1/health curl -sk https://relay.localhost:3001/health

README 特别提示:如果 relay 健康检查返回的是 HTML 而非{"status":"ok"},说明 Caddy 的主机路由配置有误(两个域名没有正确分流到 8082 端口)。

让桌面端指向本地 Remote 栈

桌面/本地应用对接这套 remote 栈只需导出 API 基地址再启动:

export VK_SHARED_API_BASE=http://localhost:3000 pnpm run dev

这里用到的VK_SHARED_API_BASE会让桌面端把云端 API 指向本地 remote-server;若同时联调 relay 隧道,再叠加VK_SHARED_RELAY_API_BASE即可。

深入源码:ElectricSQL 同步与 txid 握手机制

Shape 订阅链路

Vibe Kanban 使用 ElectricSQL 作为读路径同步引擎:写走 REST API,读走“Postgres → ElectricSQL → 客户端 HTTP Shape”的订阅链路。整个链路由三个模块支撑:

  1. Shape 定义:单表订阅,可带WHERE/columns过滤,定义为常量放在 crates/remote/src/shapes.rs,由 crates/remote/src/shape_definition.rs 的define_shape!宏构造。该宏会在编译期用sqlx::query!SELECT 1 FROM <table> WHERE <where>做类型化校验,保证表名与 SQL 的合法性在编译期就被发现。
  2. Electric 代理:crates/remote/src/routes/electric_proxy.rs 中的proxy_table先校验组织/项目成员身份,再把 shape 请求转发给内部 ElectricSQL 服务。关键安全点是:tablewhere子句由服务端常量决定并拼接进转发 URL,客户端无法覆盖;客户端的params[1]等仅作为$1占位参数传入;此外只透传offsethandlelivecursorcolumns这几个白名单参数。
  3. Mutation 响应:create/update/delete 全部走 REST,返回MutationResponse<T>,内含 Postgres 事务 ID(txid,取自pg_current_xact_id())。前端拿到txid后,在 Electric 流上等到该txid出现,才丢弃乐观更新状态——省略 txid 会导致 UI 闪烁。

给新增同步表接入同步的四个步骤

  1. 写迁移:建表后执行ALTER TABLE ... REPLICA IDENTITY FULLCALL electric.electrify('table_name')(可参考迁移 crates/remote/migrations/20260114000000_electric_sync_tables.sql 中的示例);
  2. 在 crates/remote/src/shapes.rs 用define_shape!定义 shape,按 organization/project/issue 作用域参数化;
  3. 若需要新的作用域模式,在 crates/remote/src/routes/electric_proxy.rs 增加代理路由;
  4. 该表的所有 mutation 路由都返回txid

安全边界

  • ElectricSQL 仅限内部访问:所有 shape 请求必须经过 crates/remote/src/routes/electric_proxy.rs 的鉴权代理,绝不直接暴露给客户端;
  • Shape 定义由服务端控制:表、WHERE、列集合都是服务端常量,客户端无法请求任意表,从机制上杜绝越权订阅。

深入源码:MutationBuilder 与统一 CRUD 模式

所有 CRUD 路由遵循统一的MutationBuilder模式(定义见 crates/remote/src/mutation_definition.rs):

MutationBuilder::<Entity, CreatePayload, UpdatePayload>::new("entities") .list(list_handler) .get(get_handler) .create(create_handler) .update(update_handler) .delete(delete_handler) .build()

该构建器同时产出 Axum 路由与 TypeScript 类型元数据:通过HasJsonPayload<T>特征把C/U泛型参数与 handler 签名中的Json<T>载荷结构性地绑定,防止元数据与 handler 签名漂移。新增实体时遵循这一模式,然后运行pnpm run generate-types即可自动生成前端类型。

路由树的组织见 crates/remote/src/routes/mod.rs:/v1下公开路由(health、OAuth、组织成员、token、review、GitHub App、billing)与受保护路由(需require_session中间件)分开嵌套,SPA 由ServeDir/srv/static兜底;billing模块整体用#[cfg(feature = "vk-billing")]门控,自托管构建时FEATURES为空即被裁剪,业务代码中不能直接 importbillingcrate。

类型生成与共享类型约定

api-typescrate(crates/api-types)保存 remote 服务端与本地桌面端共用的类型:行类型(IssueProjectUserWorkspace等)、请求类型(CreateIssueRequestUpdateProjectRequest等)与共享枚举(IssuePriorityMemberRolePullRequestStatusNotificationType等)。所有类型derive(TS)(ts-rs),可自动导出为 TypeScript。

remote 前端使用的单一类型文件shared/remote-types.ts由 crates/remote/src/bin/generate_types.rs 生成,运行方式:

pnpm run remote:generate-types # 写入 shared/remote-types.ts pnpm run remote:generate-types --check # CI 模式,文件过期则非零退出

生成内容包含:全部行/请求类型的 TypeScript 接口、每个 ElectricSQL shape 对应的ShapeDefinition<T>常量、每个 CRUD 实体对应的MutationDefinition<TRow, TCreate, TUpdate>常量,以及MutationRowType/MutationCreateType/MutationUpdateType类型工具。在api-types中新增前端所需类型时,需在generate_types.rstype_decls中补充其::decl()调用并重新生成。桌面端另有独立生成器(crates/server/src/bin/generate_types.rs),输出shared/types.ts

测试与常见坑位

运行 remote crate 的测试:

cargo test --manifest-path crates/remote/Cargo.toml

由于 SQLx 在编译期做查询校验,需要运行中的 Postgres 或离线查询数据(.sqlx/目录),本地可用pnpm run remote:prepare-db生成离线数据,便于 CI 构建。

最后是文档与源码共同强调的几个高频坑位:

  1. 空字符串 ≠ 未设置:所有可选配置都要按!v.is_empty()判断,不能只判断env::var是否Ok
  2. 启动顺序:remote-server 必须先启动并完成迁移、创建electric_sync角色,ElectricSQL 后启动才能连上数据库,顺序颠倒会连接失败;
  3. billing 特性门控:所有计费代码必须放在#[cfg(feature = "vk-billing")]之后,自托管 Docker 构建会把 billing crate 从 Cargo.toml 中剥离;
  4. VITE_*是构建期变量:会烘焙进前端 JS 产物,修改后必须重新构建镜像;
  5. SPA 路径硬编码:前端从/srv/static兜底提供,该路径只在 Docker 容器内存在,本地直接跑二进制时需要保证该目录存在或另行调整。

【免费下载链接】vibe-kanbanGet 10X more out of Claude Code, Codex or any coding agent项目地址: https://gitcode.com/GitHub_Trending/vi/vibe-kanban

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 6:15:36

ARM架构VIPT缓存原理与性能优化实践

1. 虚拟地址与物理地址的基本概念在计算机系统中&#xff0c;虚拟地址和物理地址是内存管理的两个核心概念。虚拟地址是程序看到的地址空间&#xff0c;而物理地址则是实际硬件内存中的位置。现代操作系统通过内存管理单元(MMU)实现两者的转换&#xff0c;这个过程被称为地址转…

作者头像 李华
网站建设 2026/9/11 6:14:54

MATLAB柔性梁振动控制实战与DeepSeek文档解析

1. 柔性梁振动控制的MATLAB实现与DeepSeek文档解析 柔性梁结构在机械臂、航天器太阳能帆板等工程领域广泛应用&#xff0c;但其固有的低阻尼特性容易导致持续振动。我在参与某卫星天线展开机构项目时&#xff0c;就遇到过梁结构因微重力环境引发的振动持续30分钟无法衰减的问题…

作者头像 李华
网站建设 2026/9/11 6:14:49

Android终端智能平台:Agent与Skill架构实战

1. 项目概述&#xff1a;当Android不再只是“手机操作系统” “AI时代下&#xff0c;Android的边界正在消失”——这句话不是修辞&#xff0c;而是我过去三年在一线做移动架构、AI工程化和终端智能系统集成时&#xff0c;每天都在验证的事实。它背后藏着一个正在发生的结构性迁…

作者头像 李华
网站建设 2026/9/11 6:14:22

Pico MicroPython文件读写实战:打造断电不丢数据的温度记录器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 6:13:51

SSM框架毕业设计实战:从零搭建留学资讯网站

简介&#xff1a;本资源是一套完整的Java毕业设计项目——基于SSM框架的“萨丁”留学资讯网站&#xff0c;面向计算机专业本科生及Java初学者&#xff0c;解决课程设计、期末大作业与毕业设计选题难、部署调试复杂等实际问题。压缩包共1394个文件&#xff0c;涵盖176个Java后端…

作者头像 李华