手机访问 Hermes agent:Tailscale、HTTPS 与 SSH
Hermes v0.20.0 的手机访问指南:比较 Tailscale 私网、HTTPS 反向代理和 SSH,了解控制面板监听地址,并在手机丢失时撤销访问权限。
从手机访问 Hermes agent 的三种方式
要从手机访问 Hermes agent,需要使用其 Web 控制面板。真正需要决定的是控制面板前面部署什么。第一种方式是私有网状网络,控制面板仅监听 Tailscale 地址,不向互联网开放任何端口。第二种方式是通过带有 TLS(传输层安全)的反向代理公开端点,并配置登录验证;此时,登录验证是保护服务器终端的唯一措施。第三种方式是通过终端应用使用 SSH(安全 Shell),配置最少,但授予的访问权限最多。
本指南从在自己的 VPS 上运行 Hermes agent之后开始。agent 已安装,可以在命令行中响应,现在您希望在手机上访问它。
以下命令针对标签 v2026.8.3 编写。该标签于 3 August 2026 发布,发布说明中标记为 v0.20.0。Hermes 发布频繁,因此应将机器固定到某个标签,而不要跟随 main。安装程序接受 commit:
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --commit 3c27eb6234bf
hermes versionhermes version 会显示实际安装的版本。在信任本页中的任何选项之前,请将其与标签进行比较。
仓库包含和不包含的内容
Hermes 仓库中没有 iOS 或 Android 应用。原生客户端是 hermes desktop(别名 hermes gui),它是一个适用于 macOS、Windows 和 Linux 的 Electron 应用。它可以连接远程代理,而不是本地代理:在 Settings 的 Gateway 下将远程 URL 设置为 http://<server-address>:9119,或者在启动前导出 HERMES_DESKTOP_REMOTE_URL=http://<server-address>:9119。这样可以解决使用第二台笔记本电脑的需求,但对手机没有帮助。
手机端使用的是 hermes dashboard,即浏览器界面。它可以管理配置、会话、cron 任务、技能、日志和消息平台,还内置了终端:服务器会在 PTY(伪终端)后启动 hermes --tui,并将输出流式传输到页面。在窄屏上,会话切换器会折叠为滑出式面板,因此布局仍适用于手机。
默认情况下,仪表板监听 127.0.0.1:9119,并在服务器本身打开浏览器标签页。对于无头 VPS(虚拟专用服务器),这没有用处。请在不打开浏览器的情况下启动它,然后查看套接字:
hermes dashboard --no-open
ss -lntp | grep 9119监听 127.0.0.1:9119 的服务只能从服务器本机访问。监听 0.0.0.0:9119 的服务可以从该计算机所连接的所有网络访问,包括公网。暴露范围由这一行决定,因此应查看它,不要凭假设判断。
选项 1:使用 Tailscale 构建私有网络
除非您有明确理由不使用它,否则请选择此方案。Tailscale 是基于 WireGuard 构建的网状 VPN(虚拟专用网络)。您加入的每台设备都会获得一个稳定地址,并与其他设备直接通信。手机也加入同一网络,因此仪表板完全不需要开放公网端口。
在服务器上:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale ip -4在手机上安装 Tailscale 应用,并使用同一账户登录。此时,在服务器上运行 tailscale status 会按名称列出手机。然后,将仪表板绑定到 tailscale ip -4 输出的地址:
hermes dashboard --host 100.101.102.103 --port 9119 --no-open绑定到网状网络地址,而不是绑定到 0.0.0.0,意味着监听套接字只存在于 Tailscale 接口上。扫描您的公网 IP 地址时,在 9119 端口上不会发现任何服务,因为没有进程监听该端口。因此,防火墙不再是唯一的安全保障。再次使用 ss -lntp | grep 9119 确认。
绑定地址还会决定身份验证方式,这是很多人容易忽略的一点。在 127.0.0.1 上,仪表板没有登录保护。在其他任何地址上,身份验证网关都是必需的;如果未配置提供程序,服务器会拒绝启动。项目将这种行为称为故障关闭。首次运行时,请在交互模式下启动它;程序会立即提示您设置用户名和密码。结果会写入 ~/.hermes/.env:
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=you
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH=scrypt$16384$8$1$...
HERMES_DASHBOARD_BASIC_AUTH_SECRET=a-long-random-string使用 openssl rand -hex 32 生成该密钥,然后不要再修改它。它用于签署会话 Cookie,因此修改后会使所有设备退出登录。同一个文件还包含模型 API 密钥,因此请使用 chmod 600 ~/.hermes/.env 限制其访问权限。
在信任配置之前,从网状网络中的另一台机器检查身份验证网关:
curl -s http://100.101.102.103:9119/api/status | jq '.auth_required, .auth_providers'true 后跟 ["basic"] 表示网关已启用,并且由密码提供程序负责响应。项目文档对该提供程序的说明很明确:它适用于受信任的网络或 VPN,不适用于面向公网的仪表板。在网状网络中,您正处于前一种场景。
如需在 tailnet 内使用 HTTPS,请将端口交给 Tailscale:
sudo tailscale serve --bg localhost:9119
sudo tailscale serve statusTailscale 使用为该机器的 MagicDNS 名称签发的证书终止 TLS,因此浏览器不再显示警告,会话 Cookie 也会获得其 Secure 标志。请先在 Tailscale 管理控制台的 DNS 页面启用 MagicDNS 和 HTTPS Certificates,并在此处阅读确认信息:您的机器名称和 tailnet DNS 名称会发布到公开的证书透明度日志中,任何人都可以读取。
这里需要正视的代价是协调服务器。手机与 VPS 之间的流量采用端到端加密,不会经过 Tailscale;但决定哪些设备属于该网络的账户并不存储在您的硬件上。如果这点很重要,可以使用 Headscale,即自行托管的 Tailscale 控制服务器运行控制平面,并通过 tailscale up --login-server https://headscale.example.com 让客户端指向它。如果您希望放弃网状网络并手动配置对等节点,请参阅普通 WireGuard 与 Tailscale 的比较,了解需要放弃哪些功能。
选项 2:公共 HTTPS 端点,以及其中隐藏的陷阱
有时无法使用网格网络。工作手机可能不允许安装 VPN 客户端。这时,应将仪表板置于反向代理之后。让仪表板继续监听 loopback,并由 Caddy 管理证书:
hermes.example.com {
reverse_proxy 127.0.0.1:9119
}Caddy 会自行申请和续期证书,其 reverse_proxy 可直接转发 WebSocket 升级请求,无需额外指令;仪表板的内置终端需要此功能。使用 nginx 时,必须自行添加 Upgrade 和 Connection 请求头;在 nginx 上使用 Certbot 申请 Let's Encrypt 证书介绍了这部分 TLS 配置。为 Hermes 设置公共名称,使登录回调指向正确的主机:
dashboard:
public_url: "https://hermes.example.com"现在来看这个陷阱。身份验证网关依据绑定地址进行判断,而不是依据请求来源地址。绑定到 127.0.0.1 的仪表板位于代理之后时,看到的来源是 loopback,因此会认为无需登录,并向代理允许访问的任何人提供服务。检查实际发布的内容:
curl -s https://hermes.example.com/api/status | jq '.auth_required'如果输出 false,则互联网上的任何人只需访问一个 URL,就能连接到服务器上的终端。这里不需要利用漏洞,日志中也不会报告任何异常。有两种修复方法,至少应采用其中一种。可以在代理中配置身份验证,通过 forward auth 将 Authentik 作为自托管单点登录提供商置于仪表板前面;也可以配置仪表板自身的 OIDC(OpenID Connect)提供商:
HERMES_DASHBOARD_OIDC_ISSUER=https://auth.example.com/application/o/hermes/
HERMES_DASHBOARD_OIDC_CLIENT_ID=hermes-dashboard
HERMES_DASHBOARD_OIDC_SCOPES="openid profile email"即使配置正确,此选项仍有无法降低的安全下限。公共登录页面任何人都能访问和攻击,而其后面是 VPS 上的 shell。用户名和密码对此提供的保护很有限,因此文档建议公共绑定使用 OAuth 或 OIDC。为登录接口设置速率限制,保持 ufw 仅允许代理端口和 SSH,拒绝其他所有访问,并定期查看访问日志。
选项 3:从移动终端使用 SSH 和 mosh
最省事的方法是:在手机上安装终端应用,将 SSH 密钥导入其中,然后使用代理自身的文本界面。
ssh you@vps.example.com
tmux new -A -s phone
hermes --tuitmux new -A -s phone连接到名为 phone 的会话;如果该会话不存在,则创建一个。这样,即使连接中断,代理仍会继续运行;下次连接时,您会回到同一位置。其模式与通过手机操作 Claude Code相同。
通过移动网络使用纯 SSH 并不方便,因为手机更换网络地址或进入休眠后,连接就会中断。mosh 可以解决这个问题。它通过 UDP(用户数据报协议)运行,并同步终端状态,而不是传输字节流。因此,从 Wi-Fi 切换到蜂窝网络时,会话仍可继续:
sudo apt install -y mosh
sudo ufw allow 60000:61000/udp在手机上运行 mosh you@vps.example.com。mosh 会通过现有的 SSH 登录启动 mosh-server,然后将会话切换到 60000 到 61000 范围内的 UDP 端口,因此必须放行该端口范围。
安全风险很明确。SSH 会话就是一个 shell,而 shell 可以执行该账户有权执行的所有操作。此时,代理的审批提示就成了被盗的已解锁手机与您的文件之间的最后一道防线。请为此使用专用的非 root 账户,并且只允许使用密钥登录。在将密钥放到随身携带的设备上之前,先完成VPS 上的 SSH 加固。
移动网络环境下会出现什么问题
有4类问题,而且都无法通过配置消除。
您未操作时,控制面板会将您登出。访问令牌的 TTL(生存时间)为 15 分钟,当前 API 契约不提供刷新令牌。令牌过期后,页面会收到 401 响应,并跳转回 /login。打开控制面板后将手机放入口袋 20 分钟,再拿出来时,您会回到登录页面,正在输入的内容也已丢失。这不是故障。重新登录即可。
嵌入式终端无法在后台标签页中保持运行。服务器会在 PTY 后台启动 TUI(文本用户界面),标签页关闭时会正常回收该进程;重新打开时则会启动新的进程。移动浏览器会回收后台标签页以释放内存,因此切换到其他应用并持续足够长时间后,该终端会结束。聊天记录是安全的,因为会话存储在服务器上,hermes sessions list仍会显示这些会话。终端本身无法重新连接。如果需要能够持续保持的会话,请通过 SSH 使用 tmux。
空闲连接会静默断开。移动运营商会断开空闲 TCP 连接,以释放 NAT(网络地址转换)表项;屏幕关闭后,手机也几乎会完全停止处理网络通信。静默一段时间的 WebSocket 通常在您解锁手机时已经断开,页面只有在您触摸屏幕后才会重新连接。这就是为什么在手机上使用 mosh 比 SSH 体验更好:mosh 从来不依赖一个可能断开的连接。
不会推送任何通知。控制面板和 SSH 会话都无法唤醒您的手机。设备上没有 Hermes 应用,因此无法连接到平台的推送服务。长时间运行的代理任务完成后,您只能在下次查看时才会发现。
通过消息网关接收通知
最后一个问题的解决方案是使用网关。这是完全不同的代理访问方式。hermes gateway 可将代理连接到 Telegram、Discord、Slack、WhatsApp、Signal 和电子邮件等消息平台。这样,您可以直接在手机上已有推送通道的应用中与代理通信。这些应用已经处理后台投递,也能应对网络中断。
hermes gateway setup
hermes gateway install
hermes gateway statushermes gateway install 会将网关注册为 systemd 服务,因此系统重启后网关会自动恢复。Hermes 安装程序不会为您创建任何服务单元,因此系统重启后 hermes dashboard 不会自行恢复。请为所依赖的组件编写服务单元;在 VPS 上编写 systemd 服务和计时器介绍了服务文件本身的写法。
定时任务也可以用相同方式推送结果,无需建立对话:
hermes send -t telegram -s "Backup report" -f /home/you/report.txt这里默认拒绝授权。未设置允许列表且未设置 GATEWAY_ALLOW_ALL_USERS 时,所有用户都会被拒绝。这是正确的初始配置。请在 ~/.hermes/.env 中指定允许使用的账户:
TELEGRAM_ALLOWED_USERS=123456789
GATEWAY_ALLOWED_USERS=123456789您也可以在 ~/.hermes/config.yaml 中设置 unauthorized_dm_behavior: pair,改用基于代码的配对,而不是粘贴数字 ID。未知账户向代理发送消息后,会收到一个八位字符的代码。在您批准之前,不会发生其他操作:
hermes pairing list
hermes pairing approve telegram ABC12DEF
hermes pairing revoke telegram 123456789代码在一小时后过期。用户每十分钟可以请求一次代码。连续五次验证失败后,该账户会被锁定。
限制被盗手机的影响范围
能够访问代理的手机,也能够在您的服务器上执行命令,而手机可能会丢失。现在就确定持有手机的人可以执行哪些操作。
保持审批功能开启。approvals.mode 的默认值为 smart,它会请求辅助模型评估风险,并且仅自动批准低风险命令。将其设置为 off,等同于使用 --yolo 运行所有命令;HERMES_YOLO_MODE=1 则通过环境变量实现相同效果。不要让能够连接代理的手机处于这种状态。设置 approvals.cron_mode: deny,这样计划任务在您休息时无法自行批准命令。
approvals:
mode: smart
cron_mode: deny限制代理可以破坏的范围。terminal.backend: docker 会在容器中执行命令,删除除少数允许项之外的所有 Linux capability,设置 no-new-privileges,并限制进程数。这样,边界由容器提供,而不是由提示词提供。terminal.cwd 固定工作目录。HERMES_WRITE_SAFE_ROOT 将 write_file 和 patch 限制在您指定的目录中;在这些目录之外写入时会被阻止,且无法通过审批绕过。
export HERMES_WRITE_SAFE_ROOT=/home/you/projects:/home/you/.hermesHermes 已经阻止向 ~/.ssh、~/.aws、~/.kube 和 /etc/sudoers 写入,拒绝在磁盘任何位置写入 .env 文件,并且无论审批设置如何,都会拒绝执行一组严格限制的破坏性命令。请将这些措施视为最低防线,而不是完整方案。使用普通用户运行代理,绝不要使用 root。相同的原则也适用于任何无人值守运行的代码代理;在 VPS 上安全运行 Claude Code对此有更详细的说明。
然后在需要撤销权限之前,先写下撤销步骤。在 Tailscale 管理控制台中移除设备,会立即切断网状网络访问。修改 HERMES_DASHBOARD_BASIC_AUTH_SECRET 并重启服务,会使所有设备上的 dashboard 会话失效,因为该值用于签名会话 cookie。从 ~/.ssh/authorized_keys 中删除手机的公钥即可终止 SSH。hermes pairing revoke telegram <user-id> 会移除一个消息传递账户。如果设备上保存了能够读取服务商密钥的任何内容,请使用 hermes auth logout <provider> 撤销这些密钥,并在上游服务商处签发新密钥。
检查实际结果,不要想当然。以下命令应在您自己的服务器上运行,输出内容取决于您的配置:
tailscale status
hermes pairing list
hermes logs gateway -n 100
hermes status --deep日志位于 ~/.hermes/logs/ 下。发生安全事件后请读取日志;没有发生事件时,也应偶尔读取。
FAQ
Hermes 是否提供适用于 iOS 或 Android 的官方移动应用?
不提供。Hermes 仓库包含命令行界面、Web 控制面板,以及适用于 macOS、Windows 和 Linux 的 Electron 桌面客户端。官方没有提供 iOS 或 Android 版本。使用手机时,您可以在浏览器中打开 Web 控制面板,使用 SSH 客户端,或通过 hermes gateway 连接消息平台。第三方移动客户端确实存在,但它们属于第三方代码,并会持有访问您代理的凭据,因此安装前请先阅读源代码。
为什么 Hermes 控制面板会在手机上将我登出?
访问令牌的 TTL 为 15 分钟,当前 API 契约不支持刷新令牌。令牌过期后,页面会收到 401 响应,并跳转到 /login。在手机上将浏览器切换到后台后,这一问题会更加明显,因为切换到其他应用 20 分钟就足以触发令牌过期。将 HERMES_DASHBOARD_BASIC_AUTH_SECRET 设置为稳定的随机值,使会话签名密钥在重启后保持不变,这样可以消除被登出的另一个原因。
可以安全地将 Hermes 控制面板放到公网吗?
只有在您亲自验证过身份验证配置后才可以。身份验证网关会根据绑定地址启用,因此绑定到 127.0.0.1、位于反向代理后的控制面板不会要求互联网用户登录。运行 curl -s https://your-host/api/status | jq '.auth_required' 并查看返回结果。请使用 OAuth 或 OIDC,而不是用户名和密码,因为项目文档说明,密码提供程序适用于受信任的网络和 VPN。使用私有网络可以完全避开这个问题,因此通常是更好的默认选择。
我需要 Tailscale 账户吗?还是可以自行托管控制平面?
可以自行托管。Headscale 是 Tailscale 协调服务器的开放实现,官方 Tailscale 客户端可以通过 tailscale up --login-server https://headscale.example.com 连接到它。这样,允许加入该网络的设备列表由您自行管理。代价是您需要运行并备份这台服务器;服务器停止运行期间,您无法注册新设备或重新验证设备。
代理完成任务后,如何在手机上收到通知?
使用消息网关。控制面板和 SSH 都无法唤醒手机,因为设备上没有 Hermes 应用来接收推送通知。使用 hermes gateway setup 将代理连接到 Telegram、Signal、Discord 或其他受支持的平台,然后由该平台的应用负责发送通知。Cron 作业也可以使用 hermes send -t telegram -s "Job done" -f /path/to/report.txt 推送一条消息,而且无需调用模型即可发送。