HAPI + Tailscale 远程编程部署指南:手机随时写代码,数据全程加密

用手机远程操控电脑写代码——不是远程桌面那种卡顿体验,而是真正的原生 Web IDE,支持 Claude Code、Codex、Gemini 等 AI 代理,数据全程走加密隧道,零公网暴露。这就是 HAPI + Tailscale 的组合拳。

我的判断

关于远程 AI 编程,我认为 HAPI + Tailscale 是目前最优雅的方案,因为它解决了三个核心痛点:公网安全(零暴露)、多设备访问(手机/平板随时连)、AI 代理统一管控。而网上的教程大多只讲安装,忽略了实际部署中的防火墙、WebSocket 代理、Android VPN 冲突等真实问题——这些坑我全都踩过,下文逐一给出解决方案。

HAPI 是什么?为什么要配 Tailscale?

HAPI 是一个本地优先的 AI 编程工具,充当 AI 代理(Claude Code、Codex、Gemini 等)的协调中心(Hub)。你在本地运行 Hub,通过 Web 界面在其他设备上操控 AI 代理写代码。

但问题来了:如果你想让手机访问电脑上的 HAPI,传统方案要么暴露端口到公网(危险),要么用 frp/ngrok 等内网穿透(配置复杂、第三方中转)。

Tailscale 提供了一个基于 WireGuard 的私有网络(tailnet),所有流量端对端加密,设备之间直接通信,不需要公网端口。两者结合,就是最安全的远程编程方案。

核心架构:手机 → Tailscale 加密隧道 → Mac(HAPI Hub + Agent)→ AI 代理执行代码

完整部署步骤

1. 注册 Tailscale 并安装

访问 tailscale.com 注册账号(支持 Google/GitHub SSO 登录),个人版免费。

macOS 安装:

1
2
3
4
# Homebrew 安装
brew install --cask tailscale

# 或从官网下载:https://tailscale.com/download

安装后运行 tailscale up,浏览器中授权登录。授权成功后设备获得一个 100.x.y.z 的 Tailscale IP。

1
2
3
4
5
6
7
8
# 查看 Tailscale IP
tailscale ip -4
# 示例输出:100.x.y.z(你的实际 IP)

# 查看设备状态
tailscale status
# 100.x.y.z your-device-name your-email@ macOS -
# 100.x.y.z phone-name your-email@ android -

建议开启 MagicDNS,这样可以用域名代替 IP:

  1. 访问 Tailscale 管理控制台
  2. DNS → 开启 MagicDNS
  3. 设备会获得类似 your-device-name.tail-xxxxx.ts.net 的域名

2. 安装 HAPI

1
npm install -g @twsxtd/hapi --registry=https://registry.npmjs.org

3. 配置环境变量

这里是关键——环境变量决定了 HAPI 如何监听和暴露服务。直接写入 ~/.zshrc 永久生效:

1
2
3
4
5
6
7
# 编辑 ~/.zshrc,添加以下内容
# HAPI 配置(使用 Tailscale serve 方式)
# 将 your-device-name.tail-xxxxx.ts.net 替换为你自己的 MagicDNS 域名
export HAPI_PUBLIC_URL="https://your-device-name.tail-xxxxx.ts.net"
export HAPI_LISTEN_HOST=127.0.0.1
export HAPI_LISTEN_PORT=3006
export HAPI_TRUST_PROXY=true

为什么用 127.0.0.1 而不是 0.0.0.0? 因为后面我们会用 Tailscale Serve 做反向代理,不需要 HAPI 直接对外暴露。127.0.0.1 只监听本地,安全性更高。HAPI_TRUST_PROXY=true 让 HAPI 识别 Tailscale Serve 的代理头信息,这样才能正确处理 WebSocket 连接。

your-device-name.tail-xxxxx.ts.net 替换为你在步骤 1 中获得的 MagicDNS 域名。 可以通过 tailscale status 或在 Tailscale 管理控制台查看。

加载配置:

1
source ~/.zshrc

4. 启动 Tailscale Serve(核心配置)

这是整个方案最容易出问题的地方。 如果你直接让 HAPI 监听 0.0.0.0 并用 IP 访问,macOS 防火墙会阻止外部连接(即使防火墙已关闭,某些系统安全策略仍可能拦截)。Tailscale Serve 是官方提供的反向代理方案,所有流量走 Tailscale 的加密隧道,不需要开放任何端口。

1
2
# 启动 Tailscale Serve,将 HTTPS 流量代理到本地 HAPI
sudo tailscale serve --bg --set-path=/ http://127.0.0.1:3006

输出类似:

1
2
3
4
5
6
Available within your tailnet:

https://your-device-name.tail-xxxxx.ts.net/
|-- proxy http://127.0.0.1:3006

Serve started and running in the background.

如果遇到 “Serve is not enabled” 错误,需要在 Tailscale 管理控制台启用。访问控制台输出的链接即可。

管理命令:

1
2
3
4
5
6
7
8
# 查看状态
sudo tailscale serve status

# 关闭 serve
sudo tailscale serve --https=443 off

# 重新配置
sudo tailscale serve --bg --set-path=/ http://127.0.0.1:3006

5. 启动 HAPI

1
2
# 终端1:启动 Hub
hapi hub

看到以下输出说明启动成功:

1
2
3
4
5
6
7
8
9
10
HAPI Hub starting...
[Hub] CLI_API_TOKEN: loaded from settings.json
[Hub] HAPI_LISTEN_HOST: 127.0.0.1 (environment)
[Hub] HAPI_LISTEN_PORT: 3006 (environment)
[Hub] HAPI_PUBLIC_URL: https://your-device-name.tail-xxxxx.ts.net (environment)
[Hub] Telegram: disabled (no TELEGRAM_BOT_TOKEN)
[Web] hub listening on 127.0.0.1:3006
[Web] public URL: https://your-device-name.tail-xxxxx.ts.net

HAPI Hub is ready!

记下 CLI_API_TOKEN,首次登录需要用到。也可以随时在 ~/.hapi/settings.json 中查看。

1
2
3
# 终端2:启动 Agent(在项目目录下)
cd /your/project/directory
hapi agent

6. 从手机访问

  1. 在手机安装 Tailscale App 并登录同一账号
  2. 浏览器访问 https://your-device-name.tail-xxxxx.ts.net/
  3. 输入 CLI_API_TOKEN 登录
  4. 选择可用机器,开始编程

配置 Telegram Mini App

HAPI 支持 Telegram 小程序访问,配置步骤:

创建 Telegram Bot

  1. 在 Telegram 搜索 @BotFather,发送 /newbot
  2. 按提示设置 Bot 名称和用户名
  3. 获得 Bot Token(格式:123456789:ABCdef...

配置环境变量

~/.zshrc 中添加:

1
export TELEGRAM_BOT_TOKEN="你的-bot-token"

重新加载并重启 HAPI:

1
2
source ~/.zshrc
hapi hub

确认启动日志显示 [Hub] Telegram: enabled

绑定账号

  1. 在 Telegram 给你的 Bot 发送 /start
  2. 点击打开 Mini App
  3. 输入 CLI_API_TOKEN 完成绑定

Telegram Mini App 无法复制粘贴 Token? 直接用浏览器访问 https://your-device-name.tail-xxxxx.ts.net/ 登录,功能完全一样,浏览器支持复制粘贴。

启动顺序和日常使用

每次使用需要按顺序启动:

1
2
3
4
5
6
7
8
9
10
# 1. 启动 HAPI Hub(终端1)
hapi hub

# 2. 启动 HAPI Agent(终端2)
cd /your/project/directory
hapi agent

# 3. 首次需要启动 Tailscale Serve
sudo tailscale serve --bg --set-path=/ http://127.0.0.1:3006
# 如果已配置过,系统重启后可能需要重新执行

建议用 pm2 后台运行 Hub,避免终端关闭后停止:

1
2
3
4
npm install -g pm2
pm2 start "hapi hub" --name hapi-hub
pm2 save
pm2 startup

踩坑实录:常见问题和解决方案

问题 1:手机访问显示连接失败或空白

原因:macOS 防火墙阻止了外部连接,或 HAPI 监听了 0.0.0.0 但防火墙拦截。

解决:使用 Tailscale Serve 代理方案(步骤 4),不要让 HAPI 直接对外暴露端口。这是最可靠的方案,不需要关闭防火墙。

问题 2:Web 界面能打开,但点击”终端”报错/无响应

原因:WebSocket 连接失败。Tailscale Serve 提供的是 HTTPS 服务,但 HAPI 内部配置的 PUBLIC_URL 是 HTTP,导致 WebSocket 协议不匹配。

解决:确保环境变量配置正确:

1
2
3
4
# 必须是 HTTPS(Tailscale Serve 提供的域名)
export HAPI_PUBLIC_URL="https://your-device-name.tail-xxxxx.ts.net"
# 必须开启代理信任
export HAPI_TRUST_PROXY=true

这是我实际踩过最折腾的坑。不加 HAPI_TRUST_PROXY=true,HAPI 无法正确识别 Tailscale Serve 的代理头信息,WebSocket 升级请求会失败。

问题 3:手机显示”无可用机器”

原因:只启动了 Hub,没有启动 Agent。Hub 是协调中心,Agent 才是执行代码的机器。

解决:在另一个终端启动 Agent:

1
2
cd /your/project/directory
hapi agent

问题 4:Android 手机 Tailscale 和 FiClash 冲突

原因:Android 系统限制同时只能有一个 VPN 服务。Tailscale 和 FiClash(Clash 客户端)都会创建 VPN 隧道,互相抢占。

这是最棘手的问题,有几种解决方案:

方案 A:FiClash 排除 Tailscale 应用(最简单)

在 FiClash 设置中,将 Tailscale 加入排除列表。但这种方式可能导致 HAPI 访问不通(Tailscale 的 VPN 接口被 Clash 接管)。

方案 B:FiClash 用仅代理模式(推荐)

将 FiClash 切换到”仅代理”模式(非 VPN 模式),让 Tailscale 独占 VPN 接口。然后手动为需要翻墙的应用配置 SOCKS5 代理(127.0.0.1:7890)。

缺点是需要逐个应用配置代理。

方案 C:局域网代理方案(我的选择)

不在手机端开 FiClash,改为使用 Mac 上的 Clash 作为代理服务器:

  1. Mac 上开启 FiClash/Clash,确保”允许局域网连接”已启用
  2. 手机只开 Tailscale(独占 VPN)
  3. 手机 Wi-Fi 设置中配置代理,指向 Mac 的 Tailscale IP:Clash 端口
1
2
代理地址:100.x.y.z(Mac 的 Tailscale IP,通过 tailscale ip -4 查看)
端口:7890(FiClash 默认 SOCKS5 端口)

这种方式 Tailscale 和代理各司其职,HAPI 通过 Tailscale 内网直接访问,外网流量走 Mac 的 Clash 代理。

方案 D:Exit Node 方案(适合 Mac 长期开机)

将 Mac 配置为 Tailscale Exit Node,手机所有流量通过 Mac 出去:

1
2
3
4
5
# Mac 端配置
sudo tailscale up --advertise-exit-node

# 开启 IP 转发(必须)
sudo sysctl -w net.inet.ip.forwarding=1

在 Tailscale 管理控制台批准 Mac 作为 Exit Node,手机 Tailscale App 中选择使用该 Exit Node。

Exit Node 方案有一个大坑:如果你同时在 Mac 上运行 FiClash 的虚拟网卡(TUN 模式),Exit Node 的流量会被 FiClash 拦截,导致手机无法上网。需要在 FiClash 中配置 IP-CIDR 规则让 Tailscale 网段直连,或者开启 IP 转发后确保 FiClash 正确处理转发的流量。这个方案配置复杂,不推荐新手使用。

问题 5:Tailscale Serve 提示 “Serve is not enabled”

需要先在 Tailscale 管理控制台启用 Serve 功能:

  1. 访问控制台输出的链接(类似 https://login.tailscale.com/f/serve?node=xxx
  2. 或手动登录 管理控制台,找到 Apps → Share/Serve 启用

一键启动脚本

为了日常方便,我写了一个启动脚本保存在 ~/start-hapi.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash
# HAPI + Tailscale 一键启动脚本

# 加载环境变量
source ~/.zshrc

# 检查 HAPI Hub 是否已运行
if lsof -i :3006 > /dev/null 2>&1; then
echo "✅ HAPI Hub 已在运行"
else
echo "🚀 启动 HAPI Hub..."
hapi hub &
sleep 3
fi

# 检查 Tailscale Serve 是否已配置
if tailscale serve status 2>/dev/null | grep -q "proxy"; then
echo "✅ Tailscale Serve 已配置"
else
echo "🔗 配置 Tailscale Serve..."
sudo tailscale serve --bg --set-path=/ http://127.0.0.1:3006
fi

# 检查 IP 转发(Exit Node 用户需要)
FORWARDING=$(sysctl -n net.inet.ip.forwarding 2>/dev/null)
if [ "$FORWARDING" = "0" ]; then
echo "⚠️ IP 转发未开启,如需 Exit Node 请运行:"
echo " sudo sysctl -w net.inet.ip.forwarding=1"
fi

echo ""
echo "📱 手机访问地址:https://your-device-name.tail-xxxxx.ts.net/"
echo "🔑 CLI Token: $(cat ~/.hapi/settings.json | grep cliApiToken | awk -F '\"' '{print $4}')"
echo ""
echo "✨ 所有服务已就绪!"
1
chmod +x ~/start-hapi.sh

什么时候该用?什么时候不该用?

该用 HAPI + Tailscale:

  • 你有多台设备(Mac + 手机/平板),想随时随地写代码
  • 你注重安全,不想暴露任何端口到公网
  • 你使用多个 AI 代理(Claude、Codex、Gemini),需要统一管控
  • 你的团队需要共享开发环境

不该用:

  • 你只在本地一台机器上开发 → 直接用 Claude Code 就行
  • 你需要让没有 Tailscale 账号的人访问 → 考虑 HAPI 的 Tunnel 模式
  • 你的网络环境不稳定(校园网/企业网可能封锁 WireGuard)→ 考虑 frp 等方案

读者行动建议

  1. 现在就能做:花 10 分钟注册 Tailscale、安装 HAPI、配置环境变量,按本文步骤启动
  2. 遇到问题先查:Web 界面打不开 → 检查 Tailscale Serve 状态;终端连不上 → 检查 HAPI_TRUST_PROXY=true;无机器 → 检查 Agent 是否启动
  3. Android 用户注意:Tailscale 和 Clash 的 VPN 冲突是最大痛点,推荐方案 C(局域网代理)
  4. 持久化运行:用 pm2 管理 HAPI Hub 进程,系统重启后自动恢复

参考