跳到主要内容

通过 SSH / 远程主机进行 OAuth 认证

部分 Hermes 提供商——目前是 xAI Grok OAuthSpotify——使用 环回重定向 OAuth 流程。认证服务器(xAI、Spotify)将你的浏览器重定向到 http://127.0.0.1:<port>/callback,这样由 hermes auth ... 命令启动的一个小型 HTTP 监听器就能获取授权码。

当 Hermes 和你的浏览器在同一台机器上时,这完全没问题。但一旦它们不在同一台机器上,就会出问题:你笔记本电脑的浏览器试图访问你笔记本电脑上的 127.0.0.1,但监听器绑定在远程服务器上的 127.0.0.1

解决办法是一行 SSH 本地转发——或者,当你没有真正的 SSH 客户端(GCP Cloud Shell、GitHub Codespaces、EC2 Instance Connect、Gitpod、基于浏览器的 Web IDE)时,可以使用 #26923 中新增的 --manual-paste 标志。

快速上手

# 在你的本地机器(笔记本电脑)上,另开一个终端:
ssh -N -L 56121:127.0.0.1:56121 user@remote-host

# 在远程机器上已有的 SSH 会话中:
hermes auth add xai-oauth --no-browser
# → Hermes 会打印一个授权 URL。在笔记本电脑的浏览器中打开它。
# → 你的浏览器会重定向到 127.0.0.1:56121/callback,隧道将请求转发给远程监听器,登录完成。

端口 56121 是 xAI OAuth 使用的。对于 Spotify,将其替换为 43827。Hermes 会在 Waiting for callback on ... 这一行打印它绑定的确切端口——从那里复制即可。

纯浏览器远程环境(Cloud Shell / Codespaces / EC2 Instance Connect)

如果你没有常规的 SSH 客户端——例如,你在 GCP Cloud Shell、GitHub Codespaces、AWS EC2 Instance Connect、Gitpod 或其他基于浏览器的控制台中运行 Hermes——则无法使用上述 SSH 隧道。请改用 --manual-paste

hermes auth add xai-oauth --manual-paste
# → Hermes 会打印一个授权 URL。在笔记本电脑的浏览器中打开它。
# → 在浏览器中批准。重定向到 127.0.0.1:56121/callback 会加载失败——这是预期行为。
# → 从失败页面的地址栏复制完整的 URL。
# → 在终端中粘贴到 "Callback URL:" 提示符处。

同样的标志也适用于 hermes model --manual-paste(用于集成模型选择器)。如果你不想粘贴整个 URL,只粘贴 ?code=...&state=... 查询片段也是可以的。

Hermes 对两种路径使用相同的 PKCE verifier、state 和 nonce,因此上游 OAuth 流程在字节级别上是完全一致的——--manual-paste 纯粹是回调跳转的传输方式改变,并非安全降级。

哪些提供商需要此操作

提供商环回端口需要隧道?
xai-oauth(Grok SuperGrok)56121是,当 Hermes 在远程时
Spotify43827是,当 Hermes 在远程时
anthropic(Claude Pro/Max)否——粘贴代码流程
openai-codex(ChatGPT Plus/Pro)否——设备代码流程
minimaxnous-portal否——设备代码流程
如果你的提供商不在表格中,则不需要隧道。

为什么监听器不能直接绑定 0.0.0.0

xAI 和 Spotify 都会根据白名单验证 redirect_uri 参数。两者都要求使用回环形式(http://127.0.0.1:<确切端口>/callback)。将监听器绑定到 0.0.0.0 或不同的端口会导致认证服务器因 redirect_uri 不匹配而拒绝请求。SSH 隧道可保持回环 URI 端到端不变。

逐步操作:单次 SSH 跳转

1. 从本地机器启动隧道

# xAI Grok OAuth (端口 56121)
ssh -N -L 56121:127.0.0.1:56121 user@remote-host

# 或用于 Spotify (端口 43827)
ssh -N -L 43827:127.0.0.1:43827 user@remote-host

-N 表示“不打开远程 shell,仅保持隧道打开”。在登录过程中请保持此终端运行。

2. 在另一个 SSH 会话中运行认证命令

ssh user@remote-host
hermes auth add xai-oauth --no-browser
# 或用于 Spotify:
# hermes auth add spotify --no-browser

Hermes 会检测到 SSH 会话,跳过浏览器自动打开,并打印出一个授权 URL 以及一行 Waiting for callback on http://127.0.0.1:<端口>/callback

3. 在本地浏览器中打开该 URL

从远程终端复制授权 URL,然后粘贴到你笔记本电脑的浏览器中。批准同意屏幕。认证服务器会重定向到 http://127.0.0.1:<端口>/callback。你的浏览器会命中隧道,请求被转发到远程监听器,Hermes 会打印 Login successful!

看到成功行后,你可以关闭隧道(在第一个终端中按 Ctrl+C)。

逐步操作:通过跳板机

如果你通过堡垒机/跳板机访问 Hermes,请使用 SSH 的内置 -J(ProxyJump)参数:

ssh -N -L 56121:127.0.0.1:56121 -J jump-user@jump-host user@final-host

这会通过跳板机串联一个 SSH 连接,而不会将回环端口暴露在跳板机本身。你笔记本电脑上的本地 127.0.0.1:56121 会直接隧道传输到最终远程主机上的 127.0.0.1:56121

对于不支持 -J 的旧版 OpenSSH,使用长格式:

ssh -N \
-o "ProxyCommand=ssh -W %h:%p jump-user@jump-host" \
-L 56121:127.0.0.1:56121 \
user@final-host

Mosh、tmux、SSH ControlMaster

隧道是底层 SSH 连接的一个属性。如果你在通过 mosh 会话运行的 tmux 中启动 Hermes,mosh 的漫游不会携带 -L 转发。请单独打开一个用于 -L 隧道的普通 SSH 会话——这条连接在认证流程期间必须保持活动。你的交互式 mosh/tmux 会话可以继续正常运行 Hermes。

如果你使用 ssh -o ControlMaster=auto,多路复用连接上的端口转发会共享主连接的生命周期。如果隧道没有建立起来,请重启主连接:

ssh -O exit user@remote-host
ssh -N -L 56121:127.0.0.1:56121 user@remote-host

故障排除

bind [127.0.0.1]:56121: Address already in use

你笔记本电脑上的某个进程已在占用该端口。可能是前一个隧道未能正常关闭,或者本地 Hermes 也在监听该端口。找到并终止占用进程:

# macOS / Linux
lsof -iTCP:56121 -sTCP:LISTEN
kill <PID>

然后重试 ssh -L 命令。

"Could not establish connection. We couldn't reach your app."(xAI)

当 xAI 的授权页面重定向到 127.0.0.1:&lt;port&gt;/callback 但未能到达监听器时,就会显示此信息。可能的原因包括:隧道未运行、端口错误、或者你使用了 Hermes 在之前运行中打印的端口(如果首选端口被占用,端口可能会自动递增——请始终读取最新的 Waiting for callback on ... 行)。

xAI authorization timed out waiting for the local callback

根本原因与上述相同——重定向从未返回。检查隧道是否仍存活(ssh -N 不显示输出,因此请查看你启动隧道的终端),必要时重启,然后重新运行 hermes auth add xai-oauth --no-browser

Token 落到了错误的 ~/.hermes 目录下

Token 会被写入运行 hermes auth add ... 的 Linux 用户目录下。如果你的网关 / systemd 服务以其他用户身份运行(例如 root 或专用的 hermes 用户),请以用户身份进行认证,以便 Token 落入其 ~/.hermes/auth.json 文件中。使用 sudo -u hermes -i 或等效命令。

参考