Skip to content

通过 SSH / 远程主机进行 OAuth

hermes agent 通过 SSH / 远程主机进行 OAuth

某些 Hermes providers —— 当前包括 xAI Grok OAuth 和 Spotify —— 使用 loopback redirect OAuth flow。auth server(xAI、Spotify)会将你的浏览器重定向到 http://127.0.0.1:<port>/callback,这样由 hermes auth ... 命令启动的一个微型 HTTP listener 就可以获取 authorization code。

当 Hermes 和你的浏览器在同一台机器上时,这可以完美工作。一旦它们不在同一台机器上,就会失效:你笔记本电脑上的浏览器会尝试访问你笔记本电脑上的 127.0.0.1,但 listener 实际绑定在远程服务器上的 127.0.0.1

解决方法是一行 SSH local-forward。

Terminal window
# On your local machine (laptop), in a separate terminal:
ssh -N -L 56121:127.0.0.1:56121 user@remote-host
# In your existing SSH session on the remote machine:
hermes auth add xai-oauth --no-browser
# → Hermes prints an authorize URL. Open it in a browser on your laptop.
# → Your browser redirects to 127.0.0.1:56121/callback, the tunnel forwards
# the request to the remote listener, login completes.

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

ProviderLoopback 端口是否需要 tunnel?
xai-oauth(Grok SuperGrok)56121当 Hermes 在远程机器上时需要
Spotify43827当 Hermes 在远程机器上时需要
anthropic(Claude Pro/Max)n/a不需要 —— 使用粘贴代码流程
openai-codex(ChatGPT Plus/Pro)n/a不需要 —— 使用 device code flow
minimaxnous-portaln/a不需要 —— 使用 device code flow

如果你的 provider 不在表中,就不需要 tunnel。

为什么 listener 不能直接绑定 0.0.0.0

Section titled “为什么 listener 不能直接绑定 0.0.0.0”

xAI 和 Spotify 都会根据 allowlist 校验 redirect_uri 参数。两者都要求使用 loopback 形式(http://127.0.0.1:<exact-port>/callback)。如果将 listener 绑定到 0.0.0.0 或不同端口,auth server 会因为 redirect_uri mismatch 拒绝请求。SSH tunnel 可以保持 loopback URI 从头到尾不变。

  1. 从你的本地机器启动 tunnel
Terminal window
# xAI Grok OAuth (port 56121)
ssh -N -L 56121:127.0.0.1:56121 user@remote-host
# Or for Spotify (port 43827)
ssh -N -L 43827:127.0.0.1:43827 user@remote-host

-N 表示“不要打开远程 shell,只保持 tunnel 打开”。在登录期间保持这个终端运行。

  1. 在单独的 SSH session 中运行 auth 命令
Terminal window
ssh user@remote-host
hermes auth add xai-oauth --no-browser
# or for Spotify:
# hermes auth add spotify --no-browser

Hermes 会检测到 SSH session,跳过浏览器自动打开,并打印 authorize URL,以及一行 Waiting for callback on http://127.0.0.1:<port>/callback

  1. 在你的本地浏览器中打开 URL

从远程终端复制 authorize URL,并粘贴到你笔记本电脑上的浏览器中。批准 consent screen。auth server 会重定向到 http://127.0.0.1:<port>/callback。你的浏览器会访问 tunnel,请求会被转发到远程 listener,然后 Hermes 会打印 Login successful!

看到成功提示后,就可以关闭 tunnel(在第一个终端中按 Ctrl+C)。

如果你通过 bastion / jump host 访问 Hermes,请使用 SSH 内置的 -J(ProxyJump):

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

这会通过 jump host 串联 SSH 连接,而不会把 loopback 端口放在 jump box 本身上。你笔记本电脑上的本地 127.0.0.1:56121 会直接 tunnel 到最终远程主机上的 127.0.0.1:56121

对于不支持 -J 的旧版 OpenSSH,长写法是:

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

tunnel 是底层 SSH 连接的属性。如果你通过 mosh session 在 tmux 中运行 Hermes,mosh 的 roaming 不会携带 -L 转发。请单独打开一个普通 SSH session 专门用于 -L tunnel —— 在 auth flow 期间,必须保持这个连接存活。你的交互式 mosh / tmux session 可以继续正常运行 Hermes。

如果你使用 ssh -o ControlMaster=auto,multiplexed connection 上的端口转发会共享 master 的生命周期。如果 tunnel 没有启动,请重启 master:

Terminal window
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

Section titled “bind [127.0.0.1]:56121: Address already in use”

你的笔记本电脑上已经有东西在使用该端口。可能是之前的 tunnel 没有干净关闭,或者本地 Hermes 也正在监听它。找到并杀掉占用者:

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

然后重试 ssh -L 命令。

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

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

当 xAI 的 authorize 页面重定向到 127.0.0.1:<port>/callback 但没有到达 listener 时,会显示这个错误。可能是 tunnel 没有运行、端口错误,或者你使用的是 Hermes 上一次运行时打印的端口(如果首选端口繁忙,端口可能会自动递增 —— 始终读取最新的 Waiting for callback on ... 行)。

xAI authorization timed out waiting for the local callback

Section titled “xAI authorization timed out waiting for the local callback”

根本原因同上 —— redirect 没有成功返回。检查 tunnel 是否仍然存活(ssh -N 不会显示输出,所以查看你启动它的那个终端),必要时重启 tunnel,并重新运行:

Terminal window
hermes auth add xai-oauth --no-browser

tokens 会写入运行 hermes auth add ... 的 Linux 用户目录下。如果你的 gateway / systemd service 以不同用户运行(例如 root 或专用 hermes 用户),请以该用户身份进行认证,这样 tokens 才会写入他们的 ~/.hermes/auth.json。可以使用 sudo -u hermes -i 或等效方式。

  • xAI Grok OAuth
  • Spotify(通过 SSH 运行)
  • SSH -J / ProxyJump(man page)
-
0:000:00