自托管 relay

自托管 Happier 的 relay:SSO、mTLS 和你自己的数据库

Happier 采用 MIT 许可,而每台设备都要经过的那个 relay 是一个你可以自己运行的容器。本页列出随之而来的各项控制 —— 服务器强制执行什么、它存储什么,以及它在运行时交给你的客户端什么。

在看清单之前,先把形态弄清楚是值得的。会话运行在你的开发者自己的电脑上,用的是他们已经有的服务方 CLI。relay 在这些电脑和他们的手机、浏览器、桌面之间传递消息。它是唯一一个必须从外部可达的部件,也正是我们请你托管的那个部件。

下面的所有内容都是服务器配置:那个容器上的环境变量,由那个容器强制执行,路径中没有任何由 Happier 运营的服务。全新服务器的默认姿态是端到端加密存储加开放注册,前提假设是大多数人会把它放在 Tailscale 后面。如果你在读这一页,你几乎肯定想要的是这句话后半段的反面。

那个加密默认设置在底层意味着什么 —— 哪一把密钥在哪里生成、你的 relay 最后手里剩下什么、没有密钥它又能读到哪些列 —— 是 加密架构,写给开发者而不是写给你。谁问服务器能看到什么,就把那一页发给谁;本页只谈你能强制执行什么。

SSO:GitHub 组织、OIDC 群组和客户端证书

身份交给你已经在运行的那一套。Happier 的职责是在每一个请求上执行它,而不只是在注册那一刻,并且持续地问下去。

要求使用身份提供方,并在每个请求上重新校验
匿名注册默认是开着的,因为大多数自托管的人把 relay 放在 Tailscale 后面就完事了。把它关掉、改为要求身份提供方,资格校验就会在每一条需要认证的 HTTP 路由上、以及在实时握手时执行 —— 而不只是在大门口。来自已经不再符合条件的人的请求会被拒绝,而不是降级处理。
GitHub 登录,限定在你的组织内
可以放行指定的登录名,或者要求用户属于一个或多个 GitHub 组织,匹配其中任意一个或全部。推荐的做法是通过 GitHub App 而不是用户自己的 OAuth 令牌来验证成员身份,这样开发者撤销授权后访问权限不会继续存在 —— 而且在他们撤销时也不会因此中断。
OIDC 单点登录,每个提供方有各自的放行规则
Okta、Entra ID、Auth0、Keycloak,任何带发现文档的都行。每个提供方有自己的放行规则:登录名白名单、允许的邮箱域名、用户必须属于其中任意一个的群组、必须全部属于的群组。如果你的 IdP 在令牌里省略了群组、转而返回一个溢出指针,Happier 会把该用户视为不符合条件,而不是视为没有群组。
来自你 MDM 的 mTLS 客户端证书
在你的反向代理上终结 mTLS,并把验证过的身份转发给 Happier。用证书的 SAN email 或 SAN UPN 来映射身份,这样一台轮换了证书的设备仍然是同一个人,再用签发者和邮箱域名白名单加以限制。除非你有意启用了自动开通,否则未知证书会被拒绝。
离职处理:按你设定的间隔重新校验成员身份
成员身份会按你设定的间隔重新校验 —— 默认每天一次,最短可到一分钟 —— 结果缓存在身份记录上。值得琢磨的设置是你的 IdP 无法访问时会发生什么:默认宽松,也可以设为严格,此时服务器会失败关闭,而不是让一次陈旧的资格校验顶替一次实时校验。

存储策略、留存期,以及由你托管的数据库

审计人员问完认证之后,紧接着会问到的那些控制项。

三种存储策略,默认是最严的那一种
仅端到端加密,拒绝明文写入,全新的服务器就是这样。可选,由账号或会话来决定。或者仅明文,面向在基础设施层管理加密、并希望有服务端索引的组织 —— 这是一个真实的取舍,直说:在这个设置下,服务器可以读取存储的内容。
由你设定的留存窗口,无需读取会话记录即可执行
默认关闭:什么都不设,服务器就永久保留会话。打开之后,会话的规则是有意保守的 —— 只有当一棵会话树在持久化的标志上处于非活动状态、在两个不同的时间戳上都早于截止时间、并且在内存中未被观察到处于活动状态时,它才会被删除,而且截止时间会在删除事务内部再次校验。它从不需要解密会话记录来做判断。
一次性为所有人关闭某些功能
语音、社交、缺陷报告上传、附件、内嵌终端、会话交接、已连接服务、配额计量 —— 每一项都是服务器上的一个环境变量,在运行时告知客户端。客户端按服务器所说的可用范围来适配,所以被关闭的能力在界面上是不存在的,而不是存在却失败。
限流,以及一个由你控制的诊断端点
一个全局限流器,加上按路由的限流,各有自己的时间窗和你选定的键策略 —— 按 IP,或者按用户并回退到 IP,当一百个开发者共用一个 VPN 出口地址时,你要的就是后者。服务器诊断快照在你启用之前是关闭的,启用之后也只有所有者能看。
一个 Docker 镜像,后面接 SQLite 或 Postgres
发布的 relay-server 镜像以非 root 用户运行,内嵌了 Web 界面,默认在单个挂载卷下使用 SQLite,并支持一份有文档说明的 Postgres 覆盖配置。MySQL 也能用,但需要从源码构建镜像 —— 预构建的镜像有意不带那个客户端。请固定一个不可变的标签;镜像不会自我更新。

如果你的组织有 Zero Data Retention 要求

如果你在读这一页,你可能已经从另一个方向撞上过这堵墙。Anthropic 自己的 Remote Control 文档说得很明确:有 Zero Data Retention 这类合规要求的组织无法启用它。在那种状态下,Claude Code 管理控制台里的开关是灰的,所以这不是 Owner 能另作决定的事。它在 Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 上同样不可用,并且当流量被指向某个 LLM 网关而不是 api.anthropic.com 时会被禁用。

这些都不是批评。Remote Control 把会话记录留在 Anthropic 服务器上,好让它能在你的各台设备之间同步,而一个签了零留存合同的组织理所当然地排除了这一点。这只是对另一个问题的另一个答案;如果你的组织正处在那个位置,那么剩下的那种形态的答案,就是一个由你自己运行的 relay。

采购拿到的是:一份 MIT 许可和一个容器镜像

MIT。不是 source-available,不是把认证栈放在商业版本之后的 open-core,也不是 AGPL。本页上的一切都和客户端在同一个仓库里,用同一份许可,没有一样是以与我们签合同为前提的。如果你所在组织的政策是 copyleft 不得进门,那么这条政策在这里不会被卡住。

上面这些控制项没有一个是要花钱买的:没有可购买的企业版,也没有需要为其中任何一项去谈的席位数。取决于你的采购流程,这要么是本页最让人安心的部分,要么是最让人不安的部分。你得到的是源码、一份 MIT 许可和一个容器镜像。

立起一个测试 relay,看看它强制执行了什么

诚实的顺序是:在一台用完即弃的主机上把 relay 立起来,让一位开发者连上去,然后读 GET /v1/features,看清楚那台服务器究竟在向它的客户端公布什么。那个响应就是契约,也是确认你设定的策略确实会被客户端遵守的最快方式。

curl -fsSL https://happier.dev/install | bash

Docker 部署指南讲了镜像、卷和 Postgres 覆盖配置。服务器认证参考讲了上面提到的每一个变量,包括面向要求 GitHub 或某个 OIDC 提供方的公开服务器的配置示例。