12k
All articles

为智能体编程配置远程服务器

用 Tailscale、tmux、mosh 和 systemd 在远程主机上搭建 Claude Code,并涵盖 SSH 密钥、密钥管理和私有访问安全。

OpenReplay Team
OpenReplay Team
为智能体编程配置远程服务器

在远程服务器上运行 Claude Code 所需的最小技术栈包括:一台 Linux VPS 或长期运行的机器、用于构建无需端口转发或动态 DNS 的私有 WireGuard 网格的 Tailscale、用于在断线后保持终端会话持久存在的 tmux,以及作为连接层的 mosh 或 SSH——这些工具全部免费、可自由组合,且不会因本月某个封装工具的消亡而失效。本指南将端到端地介绍这一技术栈,专门针对现有文档普遍忽略的常见场景:在云端 VPS 或备用机器上运行编程智能体,经过安全加固后从笔记本或手机远程驱动。

这里要解决的核心问题是持久性。当你在本地运行编程智能体并合上笔记本时,会话就会终止。而远程服务器能让智能体在断线后继续运行,让你对平台拥有完全掌控权和可预期的成本,并允许你从任何地方指挥工作。其中一个被严重忽视的问题是:一台运行着具有 shell 访问权限和 API 密钥的智能体的服务器,是一个严重的攻击面。因此,本指南将安全性置于首位,而不是事后补救。

核心要点

  • 读者经常混淆两个截然不同的目标:在可随时挂接和分离的持久会话中运行 Claude Code 等 CLI 智能体(tmux 模式),以及将智能体作为始终在线的 HTTP 服务托管(systemd 模式)——两者需要不同的配置和不同的安全策略。
  • Tailscale 在你的设备之间构建 WireGuard 加密网格;你的远程服务器将获得一个稳定的 100.x.x.x 地址,任何经过身份验证的设备都可以访问,无需开放防火墙端口或配置动态 DNS。
  • 运行编程智能体的远程服务器持有 shell 访问权限、API 密钥和代码仓库凭据——即便只是为了冒烟测试,将智能体端口绑定到公共 VPS 的 0.0.0.0 也会使这三者同时面临风险。
  • 切勿将 API 密钥放入 systemd 单元文件的 Environment= 行;应使用 EnvironmentFile= 使其不出现在 systemctl show 输出中,并使用 LoadCredential= 实现真正的密钥保护。
  • Claude Code 现已内置远程控制(Remote Control)和云端远程会话(Remote Sessions),但两者均为单会话且依赖于活跃进程;对于始终在线、无头运行或多项目场景,自建技术栈才是正确选择。

为什么选择远程服务器,以及自建方案与其他方案的对比

当你需要一个能在断线后继续运行、可无人值守运行、并可从任何设备访问的编程智能体时,远程服务器是最优选择——无需支付平台的按席位费用,也无需接受其沙箱限制。代价是运维责任:安全性、可用性和补丁管理都由你负责。对于已经熟悉 SSH 和 Git 的开发者而言,这个代价通常是值得的。

在动手构建之前,先确定以下三种方案中哪种适合你。2026 年初,这一领域发生了重大变化,“使用 Claude Code 远程工作必须用 tmux 和 SSH”的旧有说法现在已经不够全面。

方案说明最适合局限性
原生远程控制 / 远程会话Claude Code 内置的远程功能——通过手机或浏览器进行仅出站 HTTPS 控制,以及 Anthropic 托管的云端会话零基础设施的单会话操控单会话;依赖活跃进程;运行在他人的平台上
自建远程服务器你的 VPS 或备用机器,在 tmux 或 systemd 下运行智能体完全自主的始终在线、无头运行、多项目工作安全性和可用性由你负责
托管智能体平台编排并行智能体的托管产品希望获得完善合并工具而无需运维的团队供应商锁定;持续性费用

Anthropic 于 2026 年初发布了原生远程控制研究预览版和云端远程会话(截至 2026 年中,CLI 版本为 v2.1.x)。远程控制采用仅出站 HTTPS——无需开放入站端口——让你可以从手机操控会话。这个功能确实实用,但它是单会话的,且会随启动它的终端一同终止。Claude Code 本身作为 CLI 工具运行,交互式会话没有后台守护进程;关于无头守护进程模式的功能请求证实了关闭终端即结束会话这一事实。对于始终在线、无头运行或多项目场景,你需要构建在持久化原语之上,再在其上叠加便利工具。

托管平台这一类别已经存在且资金充裕,但对于已经习惯 SSH 和 Git 的开发者而言,自托管服务器能以更低的成本提供更多控制权。本指南专注于自建方案。

两种模式:tmux 与 systemd

读者经常混淆两个截然不同的目标,而它们需要不同的配置。在可随时挂接和分离的会话中运行 Claude Code 等 CLI 编程智能体,这是 tmux 模式。将智能体作为可通过 API 访问的始终在线 HTTP 服务托管,这是 systemd 模式。选错模式是远程智能体配置中最常见的结构性错误。

tmux(交互式)systemd(服务式)
使用场景实时操控的 CLI 智能体无人值守运行的 HTTP 智能体
崩溃后重启手动重新挂接Restart=always
日志会话滚动缓冲区journalctl -u <service>
密钥管理Shell 环境变量或 .env 文件EnvironmentFile= / LoadCredential=
移动端访问mosh + tmux attachcurl / 通过反向代理访问浏览器

当你需要观察和操控智能体时——输入提示词、审批操作、查看输出——使用 tmux。当智能体作为接受请求、无需人工值守的服务运行时,使用 systemd。大多数交互式运行 Claude Code 的用户需要 tmux;大多数在 API 后端暴露智能体的用户需要 systemd。某些场景下两者同时使用。

远程运行 Claude Code:标准免费技术栈

远程运行 Claude Code 的标准免费技术栈包括:一台 Linux 服务器、用于私有网络层的 Tailscale、用于连接的 OpenSSH 加 mosh,以及用于持久会话的 tmux。本节提供可直接复制粘贴的配置步骤。在将服务器投入生产环境之前,请先执行下一节中的安全加固操作。

安装 Tailscale

Tailscale 在你的设备之间构建 WireGuard 加密网格:安装后,你的远程服务器将获得一个稳定的 100.x.x.x 地址,任何经过身份验证的设备都可以访问,无需开放防火墙端口、配置动态 DNS 或修改路由器设置。Tailscale 的底层协议是 WireGuard,根据 2026 年 4 月的定价调整,免费个人版支持最多 6 个用户和无限数量的用户自有设备——使用前请核实当前限制。

按照官方安装文档在远程服务器上安装:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

tailscale up 命令会输出一个身份验证 URL。打开它,登录后服务器即加入你的 tailnet。运行 tailscale ip -4 获取其 100.x.x.x 地址。以同样的方式在笔记本和手机上安装 Tailscale,并将它们认证到同一账户,三台设备即可直接互相访问。

有一个会导致配置静默失败的注意事项——我们自己也踩过这个坑:如果你计划使用 mosh,不要通过 tailscale up --ssh 启用 Tailscale 内置的 SSH 服务器。Tailscale SSH 运行的是 Tailscale 自己的 SSH 服务器,而非 OpenSSH,而 mosh 必须通过真正的 OpenSSH 运行 mosh-server 并解析其输出来引导会话——Tailscale SSH 不支持这一点。请保持 OpenSSH 与 Tailscale 并行安装和运行,以便 mosh 能够正常连接。

配置 SSH 和 mosh

SSH 提供 shell 访问;mosh 通过在 IP 变更和网络漫游时保持连接,使其在不稳定的移动网络下依然可用。根据 mosh 文档,mosh 需要 60000–61000 范围内的 UDP 端口可达。在 Tailscale 网格中,经过身份验证的设备之间该端口范围已经可达,无需配置路由器。

在服务器和客户端上均安装 mosh:

sudo apt update && sudo apt install -y mosh tmux

从笔记本使用 Tailscale 地址连接:

mosh youruser@100.x.x.x

如果 mosh 连接失败,先用 ssh youruser@100.x.x.x 确认服务器可达,然后检查是否是 OpenSSH(而非 Tailscale SSH)在响应连接。

创建持久 tmux 会话

tmux 是断线后保持智能体存活的关键。启动一个会话,在其中运行 Claude Code,然后分离,智能体会继续工作;之后可以从任何设备重新挂接,查看或操控它。

按项目而非工具来命名 tmux 会话。使用 tmux new-session -s myproject 而不是 tmux new-session -s claude——当你同时跨三个代码仓库运行三个智能体时,tmux ls 需要告诉你哪个会话对应哪个项目:

tmux new-session -s myproject
# 在会话内部:
cd ~/code/myproject
claude
# 用 Ctrl-b 然后 d 分离

-s 标志为会话命名。在任何地方用 tmux attach -t myproject 重新挂接,或用 tmux ls 列出所有正在运行的会话。分离和重新挂接的循环就是整个交互式远程智能体工作流:合上笔记本,通过 mosh 从手机重新挂接,查看智能体的工作进展,给出下一步指令。

安全基线

运行编程智能体的远程服务器是高价值攻击目标:它持有 shell 访问权限、API 密钥,通常还有代码仓库凭据。即便只是为了冒烟测试,将智能体端口绑定到公共 VPS 的 0.0.0.0 也会使这三者同时面临风险。在用服务器处理任何敏感内容之前,先完成加固。本节内容不可跳过。

仅使用 SSH 密钥

禁用密码认证,使唯一的登录方式是你持有的密钥。编辑 /etc/ssh/sshd_config 并设置:

PasswordAuthentication no
PermitRootLogin no

PasswordAuthentication no 指令禁用密码登录,PermitRootLogin no 阻止直接以 root 身份 SSH 登录——两者均记录在 sshd_config 手册中。一个常见错误是编辑了错误的文件;这些指令应写入 /etc/ssh/sshd_config,而非客户端配置文件。执行 sudo systemctl restart ssh 使配置生效。在关闭当前会话之前,先在另一个会话中确认密钥可以正常使用,以防手误将自己锁在门外。

保持私有网格的私密性

Tailscale 网格已经经过身份验证,但你可以使用 Tailscale ACL 进一步限制哪些设备可以访问哪些端口。ACL 策略限制带标签设备之间的流量——例如,只允许你的笔记本和手机访问智能体服务器,tailnet 上的其他设备均无法访问。对于单用户场景,默认的”允许 tailnet 内所有设备互访”是合理的;当其他人或不受信任的设备共享网络时,再添加 ACL。

切勿将智能体绑定到 0.0.0.0

对本地绑定的服务进行冒烟测试时,应从服务器本身执行 curl http://127.0.0.1:9000/health,而不是临时绑定到 0.0.0.0。在没有防火墙规则阻止 9000 端口的 VPS 上,这一行改动会在进程运行期间将你的智能体暴露在公共互联网上。应将服务绑定到 127.0.0.1,并通过 Tailscale 或反向代理访问——绝不直接暴露。

不要将密钥放入单元文件

切勿将 API 密钥放入 systemd 单元文件的 Environment= 行——它们会出现在 systemctl show 输出中。根据 systemd.exec 文档,使用 EnvironmentFile=/etc/myagent/secrets.env 可以将值保存在单元文件之外,并使其不出现在 systemctl show 中。锁定该文件:

sudo mkdir -p /etc/myagent
sudo chmod 640 /etc/myagent/secrets.env
sudo chown root:myagent /etc/myagent/secrets.env

需要明确这样做的保护范围:EnvironmentFile= 使密钥不出现在单元文件和 systemctl show 中,但一旦加载,这些值仍可通过运行中进程的环境变量和 D-Bus 读取。如需真正的密钥保护,请使用 systemd 的 LoadCredential=,详见 systemd 凭据指南——它通过受限目录而非进程环境传递凭据。

保持服务型智能体持续运行:systemd 单元

对于作为始终在线 HTTP 服务运行的智能体(而非交互式会话),应使用绑定到 127.0.0.1 并配置 Restart=always 的 systemd 单元。这就是 systemd 模式:服务在启动时自动运行,崩溃后自动重启,日志写入 journal,且永远不直接接触公共端口。根据 systemd.exec 文档EnvironmentFile= 是所有当前 systemd 版本均支持的核心指令。

创建 /etc/systemd/system/my-agent.service

[Unit]
Description=My Agent Service
After=network.target

[Service]
User=myagent
Group=myagent
WorkingDirectory=/home/myagent/app
EnvironmentFile=/etc/myagent/secrets.env
ExecStart=/home/myagent/app/venv/bin/uvicorn main:app --host 127.0.0.1 --port 9000
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

每个指令都有其存在的意义。After=network.target 等待网络就绪。使用专用的 User/Group 可在智能体被攻破时限制爆炸半径。EnvironmentFile= 从受保护的文件加载密钥。ExecStart 直接从项目虚拟环境运行服务器——无需包装脚本——并绑定到 127.0.0.1,使端口永远不对外公开。Restart=always 配合 RestartSec=5 在任何崩溃发生五秒后重启服务。

启用并启动服务:

sudo systemctl daemon-reload
sudo systemctl enable --now my-agent
sudo systemctl status my-agent

如需安全地暴露服务,在本地绑定的端口前放置一个反向代理。nginxproxy_pass 指向 127.0.0.1,可在边缘终止 TLS 的同时使上游服务无法从外部直接访问:

server {
    listen 443 ssl;
    server_name agent.example.com;

    ssl_certificate     /etc/letsencrypt/live/agent.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/agent.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

使用 Certbot 申请证书,它可以自动完成 Let’s Encrypt 证书的签发和续期。对于单用户场景,通常根本不需要公共域名——通过 Tailscale 在经过身份验证的设备上访问 100.x.x.x:9000,可以完全避免暴露公共攻击面。

从移动端访问服务器

从手机访问远程智能体的方式与从笔记本访问相同——通过 Tailscale,配合终端客户端或浏览器终端。截至 2026 年中,这一领域的工具生态正在快速演进;将以下内容视为可选增强功能,而非核心基础设施。

持久可靠的选项是:支持持久连接和密钥认证的移动 SSH 客户端加 tmux,或者使用 mosh 应对网络切换。在此之上还有浏览器终端工具。ttyd 通过 Web 暴露终端。vibetunnel(MIT 许可,以 Mac 为主,提供跨平台 Linux npm 构建版本)将终端代理到浏览器中,专为监控 Claude Code 智能体而构建,支持通过 Tailscale 进行远程访问。如果你运行任何浏览器终端,请将其绑定到 localhost 并通过 Tailscale 访问——公开暴露 Web 终端与之前提到的 0.0.0.0 错误本质上是同一个问题,只是换了一种形式。

Claude Code 原生的远程控制覆盖了轻量级场景:仅出站 HTTPS,从手机操控,无需开放入站端口。这是推动单个活跃会话的最快方式。而当工作需要超越任何单个终端的生命周期时,自建技术栈才是你真正需要的。

日常工作流

远程服务器上的日常重新部署流程只需三条命令:拉取代码、重启服务、查看日志。对于 systemd 管理的智能体,操作如下:

cd ~/app && git pull origin main
source venv/bin/activate && pip install -r requirements.txt
sudo systemctl restart my-agent
journalctl -u my-agent -f

git pull 拉取最新代码,依赖安装处理新增的依赖项,systemctl restart 重启服务,journalctl -u my-agent -f 实时跟踪服务日志,以便确认服务是否正常启动——journalctl 读取 systemd journal,freedesktop.org 有详细文档。对于交互式 tmux 智能体,流程更为简单:用 tmux attach -t myproject 重新挂接,执行 git pull,让智能体继续工作。

总结

构建在能够经久不衰的原语之上:SSH 和 Tailscale 负责网络层,tmux 负责你主动操控的会话,systemd 负责无人值守的服务,安全基线确保智能体端口不暴露在公共互联网上。根据你是在操控智能体还是托管智能体,有意识地选择 tmux 模式或 systemd 模式;在用 API 密钥信任服务器之前先完成加固;然后在此之上叠加原生远程控制或浏览器终端作为便利工具。从一台全新的 Linux 服务器和上面的 Tailscale 安装命令开始——其余部分都可以在此基础上自由组合。

常见问题

为什么我断开 SSH 连接后智能体就停止运行了?

普通 SSH 会话将智能体进程与你的终端绑定,因此关闭连接会发送挂起信号并终止进程。应改为在 tmux 会话中运行智能体:用 tmux new-session -s myproject 启动会话,启动智能体,然后按 Ctrl-b 再按 d 分离。进程会继续在服务器上运行,之后可以从任何设备用 tmux attach -t myproject 重新挂接。

什么时候应该使用 Claude Code 原生远程控制,而不是自建 tmux 和 SSH 方案?

当你只需要从手机或浏览器操控单个活跃会话且不想维护任何基础设施时,使用原生远程控制——它采用仅出站 HTTPS,无需开放入站端口。但它是单会话的,且会随启动它的终端一同终止。因此,对于必须在断线后继续运行的始终在线、无头运行或多项目工作,应改为基于 SSH、Tailscale、tmux 和 systemd 构建自建技术栈。

mosh 能在 Tailscale 网络上使用吗?

可以,mosh 能在 Tailscale 网格上正常工作,因为它所需的 60000 到 61000 UDP 端口范围在经过身份验证的设备之间已经可达,无需配置路由器。唯一的失败场景是通过 tailscale up --ssh 启用了 Tailscale 自己的 SSH 服务器,这会替换 OpenSSH;由于 mosh 必须通过真正的 OpenSSH 运行 mosh-server 来引导连接,请保持 OpenSSH 与 Tailscale 并行安装和运行。

systemd 中 EnvironmentFile 和 LoadCredential 在处理密钥方面有什么区别?

EnvironmentFile 从外部文件加载值,使其不出现在单元文件和 systemctl show 输出中,但这些值在运行中的进程环境和 D-Bus 中仍然可读。LoadCredential 的保护更强,因为它通过受限目录而非进程环境传递密钥,使其不在运行进程的环境中暴露。对于配置项使用 EnvironmentFile,对于真正的密钥使用 LoadCredential。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.