iTerm2 Buddy:自托管部署

40次阅读
没有评论
iTerm2 Buddy 中文版下载|自托管部署
获取下载链
微信关注「软件教程管家」公众号,回复 iTerm2 Buddy

30秒速读:手机连回家里 Mac 终端要绕远路,打开要等好几秒。本篇讲自托管中继的部署与配对方法。

iTerm2 Buddy 是著名开源 macOS 终端 iTerm2 推出的 iPhone 应用:它能在异地通过 iOS 连接回 macOS 上已打开的 iTerm2 标签页,两端实时同步。但默认走 iTerm2 官方的公共中继服务器,连接速度很慢——实测从打开 App 到终端可用,经常要 5 秒以上。

好消息是,中继服务器本身也是开源的(iterm2-companion-relay),完全可以自托管一台,把”绕地球一圈”的链路缩短到直连,手机连 Mac 终端的速度会有质的提升。本文是一份完整可复现的自托管部署教程。

iTerm2 Buddy 连接示意

iTerm2 Buddy能做什么:手机远程连接 Mac 终端

iTerm2 Buddy 并不是”iPhone 版终端”——真正的终端会话始终跑在你的 Mac 上,手机 App 只是一个远程镜像。它通过中继服务器在 Mac 与 iPhone 之间转发加密数据,实现异地实时同步操作。

默认情况下,Buddy 使用 iTerm2 官方的公共中继服务器:

  • relay1.iterm2.com
  • relay2.iterm2.com

公共中继远在海外,国内用户从 5G 网络连回家里的 Mac,要经过”连接、中继、加密”多个步骤,延迟明显。实测从点开手机上的 iTerm2 Buddy 算起,最少也要 5 秒才能进入终端,慢到影响使用。

公共中继连接耗时

为什么要自托管中继

既然中继服务器开源了,最直接的优化就是自己搭一台:Mac 和手机都直连你自己的服务器,不再绕远路;甚至在局域网内,也可以避免流量先出国再回来。实测对比:自建中继后,家中 Wi-Fi 下从家中连回家中,连接几乎是秒开,和走公共中继完全没有可比性。

原理很简单:Mac 端和手机端分别主动建立一条 WebSocket 连接到你的中继服务器,中继把两条连接接起来,只做加密数据的转发——中继服务器本身看不到终端内容。连接时用 Ed25519 签名验证配对身份,用 Apple App Attest 验证手机上的应用是否为正版 Buddy;配对记录保存在 SQLite 数据库中,重启中继后依然有效。

自托管中继的工作方式如上文所述:Mac 端与手机端分别连接中继,中继只转发加密数据。

准备条件

  • 一台 Linux 服务器(群晖等 NAS 也可,需支持 Docker Compose v2);
  • 公网 IP(或能从外部访问到服务器的网络环境),并配置路由器端口转发;
  • 一个可修改 DNS 的域名,用于申请 TLS 证书;
  • 一张覆盖中继域名、受 iOS / macOS 信任的 TLS 证书;
  • Mac 上安装支持 Companion 功能的 iTerm2(本次验证版本 3.7.3),手机上安装 iTerm2 Buddy。

本教程以群晖 NAS 为例,部署目录统一使用 /volume1/docker/iterm2-relay-nas,域名统一使用 relay.example.com(实际部署时全部替换成自己的域名),对外只发布 TCP 18443 端口。

自托管架构示意

部署步骤

1. 建立目录,下载官方源码

SSH 登录 NAS 后执行(先确认目录没有其他用途):

export PATH=/usr/local/bin:/usr/bin:/bin:$PATH
docker --version
docker compose version

mkdir -p /volume1/docker/iterm2-relay-nas
cd /volume1/docker/iterm2-relay-nas
mkdir -p certs
chmod 700 certs

git clone https://github.com/gnachman/iterm2-companion-relay.git upstream
git -C upstream checkout --detach f1c3371cdab8e7d361db9e8b439551f2fea1d95b

这里固定到验证过的 commit,便于复现。NAS 上没有 Git 的话,也可以在电脑上下载对应源码,再复制到 NAS 的 upstream 目录。

2. 创建部署文件

在部署目录下创建以下文件,注意文件名大小写。

Dockerfile(Node 24 构建依赖,最终容器用普通 node 用户运行):

FROM node:24-bookworm-slim AS deps
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends python3 make g++ && rm -rf /var/lib/apt/lists/*
COPY upstream/package.json upstream/package-lock.json ./
RUN npm ci --omit=dev

FROM node:24-bookworm-slim
ENV NODE_ENV=production
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY upstream/package.json ./
COPY upstream/bin ./bin
COPY upstream/host ./host
COPY upstream/src ./src
RUN mkdir /data && chown node:node /data
USER node
CMD ["node", "bin/relay.js"]

compose.yaml(只把 Caddy 的 TCP 18443 发布到 NAS,Relay 的 8787 留在 Docker 网络内;配对数据放在命名卷里,重启不丢):

name: iterm2-relay-nas
services:
  relay:
    build: .
    restart: unless-stopped
    init: true
    environment:
      RELAY_HOST: 0.0.0.0
      RELAY_PORT: "8787"
      RELAY_DB: /data/relay.db
      RELAY_ORIGIN: ${RELAY_ORIGIN:?Set the public HTTPS origin including port}
      ATTEST_REQUIRED: "true"
      APP_ID: H7V7XYVQ7D.com.googlecode.iterm2.companion
      APPATTEST_ENV: production
      RELAY_TRUST_PROXY: "true"
      RELAY_LOG: "false"
      RELAY_DAILY_BYTE_QUOTA: "8589934592"
    volumes:
      - relay-data:/data
    healthcheck:
      test: [CMD, node, -e, "fetch('http://127.0.0.1:8787/metrics').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
  tls:
    image: caddy:2-alpine@sha256:d8542f48d34a9cf4e4c11a478865229840e87e4c96ea3f439101f31a5d35f75f
    restart: unless-stopped
    environment:
      RELAY_ORIGIN: ${RELAY_ORIGIN:?Set the public HTTPS origin including port}
    ports:
      - "18443:18443/tcp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ${RELAY_CERT_DIR:-./certs}:/certs:ro
      - caddy-data:/data
      - caddy-config:/config
    depends_on:
      relay:
        condition: service_healthy
volumes:
  relay-data:
  caddy-data:
  caddy-config

Caddyfile(加载外部证书,反向代理 Relay,同时屏蔽公网访问 /metrics):

{
    admin off
    auto_https off
}

{$RELAY_ORIGIN} {
    tls /certs/fullchain.pem /certs/privkey.pem
    @metrics path /metrics /metrics/*
    respond @metrics 404
    reverse_proxy relay:8787 {
        header_up X-Forwarded-For {remote_host}
        header_up -CF-Connecting-IP
    }
    log {
        output discard
    }
}

.env:

RELAY_ORIGIN=https://relay.example.com:18443
RELAY_CERT_DIR=./certs

RELAY_ORIGIN 必须与 Mac 和手机实际连接的地址一致,包括 https://、域名和端口,末尾不要加 /。

.dockerignore(避免把证书、密钥送进构建上下文):

upstream/.git
**/node_modules
certs
acme
acme-src
acme-state
.env
*.log
*.zip
*.tar.gz

3. 准备 TLS 证书

已有证书:可复用 NAS 现有证书,但必须确认它覆盖你的中继域名且在有效期内。把证书链和私钥放到:

/volume1/docker/iterm2-relay-nas/certs/fullchain.pem
/volume1/docker/iterm2-relay-nas/certs/privkey.pem

检查证书:

openssl x509 -in certs/fullchain.pem -noout -subject -issuer -dates -ext subjectAltName

注意:Cloudflare Origin CA 证书不适用于本教程的直连方式,必须使用受客户端信任的证书。

没有证书:用 DNSPod 签发 Let’s Encrypt(DNS-01 验证,不需要开放 80/443):

cd /volume1/docker/iterm2-relay-nas
umask 077
mkdir -p acme acme-state
chmod 700 acme acme-state

git clone --depth 1 https://github.com/acmesh-official/acme.sh.git acme-src
(cd acme-src && ./acme.sh --install 
  --home /volume1/docker/iterm2-relay-nas/acme 
  --config-home /volume1/docker/iterm2-relay-nas/acme-state 
  --accountemail [email protected] 
  --nocron)

设置 DNSPod Token 后申请证书:

export DP_Id='你的 DNSPod Token ID'
export DP_Key='你的 DNSPod Token'

./acme/acme.sh --issue 
  --home /volume1/docker/iterm2-relay-nas/acme 
  --config-home /volume1/docker/iterm2-relay-nas/acme-state 
  --server letsencrypt 
  --dns dns_dp 
  -d relay.example.com 
  --keylength ec-256

unset DP_Id DP_Key

签发成功后创建 reload-tls.sh:

#!/bin/sh
set -eu
export PATH=/usr/local/bin:/usr/bin:/bin:$PATH
cd /volume1/docker/iterm2-relay-nas
if [ -n "$(docker compose ps -q tls)" ]; then
    docker compose restart tls
fi

然后安装证书并登记续期重载:

chmod 700 reload-tls.sh

./acme/acme.sh --install-cert 
  --home /volume1/docker/iterm2-relay-nas/acme 
  --config-home /volume1/docker/iterm2-relay-nas/acme-state 
  -d relay.example.com --ecc 
  --key-file /volume1/docker/iterm2-relay-nas/certs/privkey.pem 
  --fullchain-file /volume1/docker/iterm2-relay-nas/certs/fullchain.pem 
  --reloadcmd /volume1/docker/iterm2-relay-nas/reload-tls.sh

chmod 600 certs/privkey.pem certs/fullchain.pem

4. 配置 DNS 和端口转发

将中继域名的 A 记录指向 NAS 所在网络的公网 IPv4(公网地址会变化的话,需要配套 DDNS)。在路由器上设置:公网 TCP 18443 → NAS 内网 IP 的 TCP 18443,有防火墙也要放行该端口。本教程只发布 TCP,不需要转发 UDP。

5. 构建并启动

cd /volume1/docker/iterm2-relay-nas
export PATH=/usr/local/bin:/usr/bin:/bin:$PATH

docker compose config --quiet
docker compose up -d --build
docker compose ps
docker compose logs --tail=50 relay tls

正常情况下 relay 显示 healthy,tls 显示运行中。从另一台电脑检查 HTTPS:

curl -I --connect-timeout 10 https://relay.example.com:18443/

根路径返回 HTTP 400 不一定是异常(Relay 的普通请求也需要协议头),这里先确认 TLS 验证无报错、能收到 HTTP 响应即可。

再检查 WebSocket 升级:

probe_room=$(openssl rand -hex 32)
curl --http1.1 -i -N --max-time 5 
  -H 'Connection: Upgrade' 
  -H 'Upgrade: websocket' 
  -H 'Sec-WebSocket-Version: 13' 
  -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' 
  -H "x-relay-room: $probe_room" 
  https://relay.example.com:18443/

收到 101 Switching Protocols 即表示 WebSocket 升级成功。公网测试尽量从外部网络进行,NAS 所在局域网访问自己的公网地址可能受路由器 NAT 回环限制影响。

6. 修改 Mac 的 iTerm2 设置并重新配对

先保存工作,确认没有需要继续运行的下载或任务,再完全退出 iTerm2,然后在 macOS 自带”终端”中执行。

如果之前改过这些设置,先记下原值便于恢复:

defaults read com.googlecode.iterm2 CompanionRelayOrigin
defaults read com.googlecode.iterm2 CompanionResolverURL

首次使用提示找不到键是正常的。写入新地址:

defaults write com.googlecode.iterm2 CompanionRelayOrigin -string 'https://relay.example.com:18443'
defaults write com.googlecode.iterm2 CompanionResolverURL -string ''

第二项设为空,让客户端使用这台固定 Relay,而不是默认的 Relay 解析服务。

Mac 端写入中继地址

再执行两条 defaults read 检查:第一条应输出自己的 HTTPS 地址,第二条应为空。

重新打开 iTerm2,在 iTerm2 → Companion Device Settings 中生成新二维码,用 Buddy 扫描并确认配对码。已有配对会记住原来的 Relay,因此需要建立新配对(官方配对说明)。

配对后分别测试 Wi-Fi 和蜂窝网络,确认终端可访问;再测试网络切换和 Relay 重启后的重连。

7. 设置证书自动续期

如果用了上面的独立 acme.sh,在群晖 DSM 的控制面板 → 任务计划中创建用户定义脚本:用户 root,每天一次(如 04:27):

umask 077
/volume1/docker/iterm2-relay-nas/acme/acme.sh --cron 
  --home /volume1/docker/iterm2-relay-nas/acme 
  --config-home /volume1/docker/iterm2-relay-nas/acme-state

创建后手动运行一次检查结果。每天运行只是检查是否需要续期,不会每天申请新证书;续期成功后会自动调用之前登记的 reload-tls.sh 重载 Caddy。

常见问题

证书报错:检查域名是否在证书 SAN 中、证书是否过期、fullchain.pem 是否包含完整链。用别的域名的证书会导致校验失败。

容器正常,公网仍连不上:检查域名解析、公网地址、端口转发和防火墙。relay healthy 只能证明 NAS 内部服务在运行,不能证明公网入口已打通。

能连接,但配对失败:先核对 .env 和 Mac 设置中的 RELAY_ORIGIN,域名、HTTPS、端口必须一致;确认修改后完全重启了 iTerm2,并重新扫码建立配对。

更新证书后客户端仍看到旧证书:执行 docker compose restart tls;如果证书管理工具替换的是整个挂载目录,则用 docker compose up -d --force-recreate tls 刷新挂载。

想恢复原来的 Relay:先退出 iTerm2,恢复之前记下的两项设置;如果两项原本都没设置过,可以删除自定义键:

defaults delete com.googlecode.iterm2 CompanionRelayOrigin
defaults delete com.googlecode.iterm2 CompanionResolverURL

重新打开 iTerm2,按原来的 Relay 重新配对即可。

升级和数据保留:升级官方源码后执行 docker compose up -d --build 重新构建,升级前先看上游变更并备份配对数据库。配对数据在 relay-data 命名卷里,不要随手执行 docker compose down -v,它会删掉卷里的配对数据,之后需要重新配对。

版本说明

中继服务器 iterm2-companion-relay 开源免费,无二进制发行版,需按本教程自行构建部署。本教程已在 x86_64 群晖上验证通过(源码固定 commit f1c3371,其他 NAS 架构尚未验证)。自建 Relay 不会给 Buddy 增加”新建 iTerm2 标签页”等客户端新功能,它只负责更快地连通两端。

下载

前往 GitHub 获取源码

下载方式:iTerm2 中继服务器(iterm2-companion-relay)为开源项目,GitHub 仓库提供完整源码,按上文教程自行构建部署即可,无需网盘中转。

软件信息速览

版本 iterm2-companion-relay,源码固定 commit f1c3371
大小 以官网为准
平台 Linux 服务器或群晖 NAS,需 Docker Compose v2
语言 以官网为准
更新日期 以官网为准

版本对比与推荐

版本 特点
固定 commit f1c3371(本教程验证版) 步骤与配置都按这个版本验证过,复现最稳,推荐使用
直接拉取最新主干(未固定) 可能包含未验证的变更,步骤不一定完全对得上

推荐:固定 commit f1c3371 的验证版,升级前先看上游变更并备份配对数据库。

安装步骤

  1. 按原文部署步骤建好目录并拉取固定版本的官方源码。
  2. 写好部署文件与证书,确认中继域名、端口与证书覆盖范围一致。
  3. 构建并启动容器,确认中继服务健康、反向代理运行正常。
  4. 在 Mac 端写入自建中继地址,重新扫码配对后再分别测试 Wi-Fi 与蜂窝网络。

装完必改设置

中继地址设置

入口:Mac 端终端里写入中继地址的两项设置。体感差别:地址指向自建服务器后,手机与 Mac 不再绕远路连接,打开终端的等待时间会明显缩短。

配对与重连设置

入口:Mac 端的 Companion Device Settings 与手机端配对流程。体感差别:重新配对成功后,配对记录保存在服务器数据库里,重启中继后依然有效,不用每次都重配。

证书与端口检查设置

入口:服务器上的证书目录与路由器端口转发设置。体感差别:证书覆盖域名且端口转发打通后,手机在外网也能连回家里的中继,不会卡在连接阶段。

常见问题与注意事项

  • 系统要求是什么?需要一台支持 Docker Compose v2 的 Linux 服务器或 NAS、公网访问条件、可改 DNS 的域名与受信任的 TLS 证书,Mac 端需支持 Companion 功能的终端版本,手机端需安装对应应用。
  • 容器正常但公网连不上怎么办?先查域名解析、公网地址、端口转发与防火墙,中继健康只能证明 NAS 内部服务在运行,不能证明公网入口已打通。
  • 能连接但配对失败怎么办?先核对服务器与 Mac 两边的中继地址是否完全一致,再完全重启终端并重新扫码配对。
  • 升级后配对丢了怎么办?配对数据在命名卷里,不要随手执行会删卷的操作,升级前先备份配对数据库,丢了只能重新配对。
推广iTerm2 Buddy 中文版下载|自托管部署

关注「软件教程管家」

回复软件名即取即下:网盘下载链接 + 提取码,一步直达,不用再跳转。

版权与使用提示

本站资源仅供个人学习交流,请勿用于商业用途。软件与资料版权归原作者所有;如有侵权,请通过公众号「软件教程管家」联系我们,我们将在 24 小时内下架处理。查看免责声明 ›

上次编辑至今:11小时 · 内容还比较新鲜

公告

契机库网站正式上线!

了解更多
正文完
 0
评论(没有评论)