返回文章
NO.
048
DATE
更新于
READ
~21 min
KIND
教程
STATUS
原文

TAGS: AI 协作 Cloudflare

用手机接着用电脑上的 Pi

不必先学内网穿透。按手机是否要同时开其他 VPN 应用,选 Tailscale 或 Cloudflare,只走一条路线;附 Windows/WSL 配置、验收、每次开机后的命令和远程桌面的区别。

离开电脑后,用手机看看回答,补一句要求,让电脑继续做事。先实现这个目标,不必先买服务器,也不用先弄懂路由器端口映射。

本文用 Pi Web 举例,方法也适用于其他已经在电脑上运行的网页工具。示例环境是 Windows + WSL2(Windows 中的 Linux 环境)、Android 手机;示例环境里,路线 A 已经走通:手机关掉 Wi-Fi、用蜂窝网络打开电脑上的 Pi Web,登录后能看到会话、收到回复。路线 B 还没有实测,只按官方文档整理,文中标明了需要自己核对的地方。

先选一条路,另一条不用读

只问一个问题:使用 Pi Web 时,手机是否必须同时开着另一个 VPN 类应用?

  • 不需要,或可以暂时关掉它:走 A:Tailscale 私有连接。网页内容只在自己的电脑上解开,不用买域名。
  • 必须同时开:走 B:Cloudflare 固定网址。手机只用浏览器,代价是网页内容会先在 Cloudflare 解开,再转给你的电脑。

如果“必须同时开着另一个 VPN 应用”和“不让第三方解开内容”都是硬要求,这两条入门路线不能同时满足。先不要配置 B;需要另评估只转发密文、本机负责 HTTPS 的中继方案。

示例环境里,手机另装有一个 VPN 类应用,但不常开。Android 同一用户资料同时只能有一个活动 VPN(Android 开发者文档),Tailscale 也说明了 它不能与其他 VPN 同时运行;所以先关掉它试 A,不必卸载,也不必换成别的软件。

自己的域名只在 B 中使用。A 用 Tailscale 分配的 *.ts.net 地址,不要把自己的域名硬填进去。

两条路线到底怎么连?谁能看到什么?

把 HTTPS 想成一个封好的信封:路上的人只看得到信封,看不到信。两条路线的区别,在于信封在哪里拆开。

A:手机和电脑之间先搭一条只属于自己设备的加密通道,开启它的钥匙只存在两台设备上。直连不上时,数据会借道 Tailscale 的中继服务器,但中继没有钥匙,只能原样转交(DERP 中继说明)。Tailscale 的登录服务器只帮设备互相“介绍”,交换的是公钥和设备信息(Tailscale 的工作原理)。信封在你电脑上的 Serve 这里拆开,再交给本机的 Pi Web。

B:电脑上的 cloudflared 主动连到 Cloudflare,路由器不用开任何端口(Cloudflare Tunnel 说明)。手机打开固定网址时,信封在 Cloudflare 拆开,Access 先核对是不是你本人,再装进另一个信封经隧道送到电脑。访客到 Cloudflare、Cloudflare 到你的电脑,是两段各自加密的连接(Cloudflare 加密模式)。

A:TailscaleB:Cloudflare
谁能打开只有登录了你账号的设备谁都能到门口,只有通过 Access 的本人能进
在哪解开你的电脑先在 Cloudflare,再到你的电脑
服务商知道账号、设备和谁连了谁;记录里没有流量内容账号、登录记录,以及经过它的网页内容
进门后还要输 Pi Web 密码还要输 Pi Web 密码

Pi Web 密码是第二道锁:设备被别人拿到、或访问规则配错时,还有它挡着。它本身不加密连接,Pi Web 的说明也要求远程使用放在 HTTPS 或可信 VPN 后面(Pi Web 中文说明),这两条路线都满足。

只想偶尔点一下电脑:向日葵、UU 远程也可以吗?

可以。电脑和手机安装相应客户端,绑定本人设备后,在手机里控制电脑上的 Pi Web。通常不用另外配置本文的网页入口,远程控制功能一般也不占用第二个系统 VPN;具体版本仍需检查,手机上其他 VPN 应用的分流规则也可能影响连接。

两种体验有区别:远程桌面传输电脑画面和操作,能处理桌面弹窗、重启应用;手机网页把聊天内容按手机宽度排版,更适合长时间阅读和输入。前者在高画质、画面持续变化时通常更耗带宽,还受电脑屏幕分辨率影响。

远程桌面授权通常覆盖整台电脑,需保护账号、开启可用的二次验证,不分享连接码;不用的文件传输、剪贴板同步和无人值守权限可以关闭。厂商页面上的“加密”“隐私屏”不足以证明中继无法解密,本文没有核实这两款产品的完整加密实现,也没有做延迟排名。

如果已经装有一个可信的远程桌面工具,可以把它留作恢复电脑服务的备用入口,不必再装多个。没有特殊唤醒条件时,电脑关机或断网,它也不能凭空连上。

出门前,只确认电脑能打开

在运行网页工具的电脑上打开它的本地地址。Pi Web 默认是:

http://127.0.0.1:30141

看到页面才继续。本地还打不开,先修本地服务;隧道不会把坏掉的应用修好。手机里的 127.0.0.1 指手机自己,不能直接复制这个地址到手机使用。

首次安装 Pi Web,先按官方说明检查 Node.js 版本,再全局安装发布包。日常远程使用不要用开发服务器替代正式运行方式。

首次安装/WSL 用户:展开这一步

本文实测用的 Pi Web 0.12.2 要求 Node.js 22.19.0 或更高版本:

node --version
npm install -g @agegr/pi-web@0.12.2
command -v pi-web
pi-web version
pi-web --hostname 127.0.0.1 --port 30141 --no-open

版本只写在安装命令里,用来复现本文;之后启动的都是已经安装的 pi-web,不会每次自动升级。command -v pi-web 应指向 npm 的全局安装目录,而不是 .npm/_npx/ 临时缓存。npm 提示有安装脚本尚未批准时,不要批量批准。已有 Pi Web 正在占用 30141 时,不再启动第二个实例。选择与原有 Pi 相同的系统用户和文件系统环境,避免打开一套空会话。

示例中的 Pi Web 跑在 WSL,Windows 也需要能访问它。用 Windows 浏览器打开上述地址;或者在 PowerShell 执行只读检查:

(Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:30141/' -TimeoutSec 10).StatusCode

预期为 200。示例机器的 WSL2 使用镜像网络,这一步已通过;其他机器以自己的结果为准。不通时先查 WSL 服务与本机访问,不要直接关防火墙或把监听地址改成 0.0.0.0。

macOS/Linux 原生运行时,后面的连接工具放在应用所在的同一台机器即可。

A:手机和电脑建立私有连接

这条路只做三件事:让设备互相看见 → 给本地网页一个 HTTPS 地址 → 手机打开。第一次不用处理开机自启。

路线 A 示意:手机经 Tailscale 的加密连接到自己的电脑,Serve 在电脑上解开 HTTPS,再交给本机 Pi Web;不是操作截图。

A1 · 两台设备出现在同一个列表里

从 Tailscale 官方下载页安装 Windows 和 Android 客户端,用同一账号登录。点击登录后,浏览器可能要等几秒到十几秒才弹出登录页;先等一会儿,不要连续点击。手机先关掉其他 VPN 类应用,再开启 Tailscale。账号开启双重验证;这次不启用 Exit Node(让手机其他上网流量也从某台设备出去的功能)。

打开设备列表,确认手机与电脑都在线。刚连上时手机可能经中继(relay)连到电脑,能用就行,这一步不用处理。仅在自己的新网络里试验,不把电脑分享给其他人。已有团队网络的用户,先核对访问规则是否只允许预期的本人设备访问这台电脑的 HTTPS 端口。

到这里可以停一下。今天只做到设备在线,也是一项完整的小进展。

A2 · 让电脑提供 HTTPS 地址

首次配置按下面三步做。Windows 上运行 Serve,Pi Web 继续留在 WSL。先给 Pi Web 设置密码并核验,再打开远程入口;以后开机按后文的启动脚本恢复。

A2.1 · Windows:取得设备完整域名

在 Tailscale 管理控制台的 DNS 页面开启 MagicDNS(设备名称解析)与 HTTPS Certificates。示例环境里 MagicDNS 默认已开,HTTPS Certificates 要自己打开;在控制台里开,比等命令行临时申请更稳。开启后,设备的完整域名会写进任何人都能查的公开证书记录。别人能查到这个名字,但连不进来;先把带真名、公司名的设备名改掉。

在 Windows PowerShell 查看设备完整域名:

$ts = tailscale status --json | ConvertFrom-Json
$ts.Self.DNSName.TrimEnd('.')

记下输出,不带末尾的点、不带 https://。如果命令找不到,安装后重新打开 PowerShell,或使用安装目录里的 tailscale.exe。

A2.2 · WSL:保存启动脚本,带密码重启并检查

在 Pi Web 所在的 WSL Bash 中,先保存 A2.1 的完整域名。已有这个文件时命令会停下,不覆盖:

(
  set -eu
  umask 077
  file="$HOME/.config/pi-web/allowed-hosts"
  test ! -e "$file" || {
    printf '文件已存在,未覆盖,请先核对。\n'
    exit 1
  }
  read -r -p '粘贴完整设备域名(不含 https://):' host
  [[ "$host" == *.ts.net && "$host" != *[[:space:]/:]* ]] || {
    printf '域名格式不对,未保存。\n'
    exit 1
  }
  mkdir -p "$HOME/.config/pi-web"
  (set -C; printf '%s\n' "$host" > "$file")
  printf '域名配置已保存。\n'
)

再创建启动脚本。它读取这个域名,启动时让你输入密码,密码不写入磁盘;最后调用已安装的 pi-web,脚本里不写版本:

(
  set -eu
  umask 077
  script="$HOME/.local/bin/pi-web-start"
  test ! -e "$script" || {
    printf '启动脚本已存在,未覆盖。\n'
    exit 1
  }
  mkdir -p "$HOME/.local/bin"
  set -C
  cat > "$script" <<'EOF'
#!/usr/bin/env bash
set -eu
PI_WEB_ALLOWED_HOSTS=$(cat "$HOME/.config/pi-web/allowed-hosts")
test -n "$PI_WEB_ALLOWED_HOSTS" || {
  printf '域名配置为空,未启动。\n'
  exit 1
}
export PI_WEB_ALLOWED_HOSTS
read -r -s -p 'Pi Web 密码:' PI_WEB_PASSWORD
printf '\n'
test -n "$PI_WEB_PASSWORD" || {
  printf '密码为空,未启动。\n'
  exit 1
}
export PI_WEB_PASSWORD
exec pi-web --hostname 127.0.0.1 --port 30141 --no-open
EOF
  chmod u+x "$script"
  bash -n "$script"
  printf '启动脚本已准备好;尚未启动。\n'
)

接着停止旧实例,用脚本重新启动。停止会中断旧实例里正在运行的任务和网页终端,已保存的会话不会删除;先等回复结束。如果你正在 Pi Web 里看本文或和智能体对话,先把下面的命令记下来:

pi-web stop --port 30141 &&
  "$HOME/.local/bin/pi-web-start"

前半段失败时不会继续启动;第一次安装后还没运行 Pi Web 的,只执行第二行。出现 Pi Web 密码: 时输入密码管理器里的密码,字符不显示是正常的。保持这个终端窗口打开;关窗口或按 Ctrl+C 都会停止 Pi Web。pi-web stop 找不到实例时,先运行 pi-web status 核对,不要用模糊的批量结束进程命令。

本机浏览器没有出现登录页,不一定说明密码没生效:之前用同一个密码登录过的话,30 天内的登录凭证仍然有效。示例环境里,本机浏览器直接进入了会话,下面两项检查都通过,手机无痕窗口则先出现了登录页。浏览器若弹出自带的“用户名 + 密码”框,点取消,关掉旧标签页再重新打开,在 Pi Web 自己的登录页只输密码。

验证的是正在运行的服务,不是终端里还留着一个变量。新开一个 WSL 终端,执行下面的只读检查;它不带浏览器的登录状态,也不调用模型:

curl -q --noproxy '*' --fail --silent --show-error --max-time 10 \
  http://127.0.0.1:30141/api/web-auth

预期返回:

{"enabled":true,"authenticated":false}

enabled: true 才表示当前服务已开启密码;authenticated: false 表示这次检查没有登录,正是预期结果。再确认未登录请求拿不到会话:

curl -q --noproxy '*' --silent --show-error --max-time 10 \
  --output /dev/null --write-out 'HTTP %{http_code}\n' \
  http://127.0.0.1:30141/api/sessions

预期是 HTTP 401(需要认证),不是 HTTP 200。若 enabled 是 false、会话接口没有拒绝未登录请求,或者检查失败,先不要开启 Serve;在启动窗口按 Ctrl+C 停止这次启动,再核对域名文件和脚本。已经有远程入口的,先按文末停用步骤关闭本教程那一条 Serve,再处理密码。终端的 Ready 和浏览器能打开页面,都不能替代这一步。

A2.3 · Windows:开启并核对 Serve

回到 Windows PowerShell:

tailscale serve status

如果已有其他 Serve 服务,先停在这里,避免占用其端口或覆盖路由。没有冲突再开启:

tailscale serve --bg --https=443 http://127.0.0.1:30141
tailscale serve status

按提示完成 HTTPS 授权。报 error enabling https feature … context deadline exceeded 时,是命令行连 Tailscale 服务器超时,重试多半一样;去控制台 DNS 页面开启 HTTPS Certificates,等一两分钟再运行上面的命令。记录命令打印的完整 https://…ts.net 地址。使用的是 serve,只对自己的设备开放;不是面向公网的 funnel。也不需要单独管理证书文件。

A3 · 手机关掉 Wi-Fi,打开刚才的网址

用蜂窝网络,保持 Tailscale 开启、其他 VPN 应用关闭,在 Chrome 打开 Serve 打印的 HTTPS 地址。关 Wi-Fi 只是为了这次验收:手机和电脑在同一个 Wi-Fi 里时,连上不能证明出门也能用。验收通过后,日常开着 Wi-Fi 照常使用。能看到 Pi Web 登录页、输入密码后看到自己的会话,才算跨网访问成功。浏览器若提示证书错误,先停下排查地址,不点击忽略。

第一次只查看会话。准备好承担模型调用费用后,再发送一句“只回复连接成功,不使用工具”,观察回复是否逐步出现。暂时关闭手机 Tailscale,用新开的无痕窗口重试:应无法连接。这验证的是私有入口,不是页面缓存。

在 Chrome 菜单选择“安装应用”或“添加到主屏幕”。这个 PWA(Progressive Web App,可安装的网页应用,安装说明)只是更方便的入口,电脑仍需开机,手机仍需联网并连接 Tailscale。

部分 Android 手机要先在系统设置里给 Chrome 开启“创建桌面快捷方式”权限,否则添加会失败。提示安装成功却在桌面上找不到时,去应用抽屉或全局搜索里找“Pi Web”。各家系统在这里的表现不一致,快捷方式能打开就够用。

这条路线走通就结束。下面的 B 不用配置。

B:手机 VPN 不能关时,用固定网址访问

手机必须同时开着另一个 VPN 类应用时,可以用 Cloudflare 的固定隧道加一道登录门(Tunnel + Access)。它不占手机的 VPN 名额,但网页内容会在 Cloudflare 解开;如果你要的是“只在自己电脑上解开”,这条不是同等的替代。

这条路线也是三件事:先限制谁能进 → 连接本地服务 → 用手机验收。

路线 B 示意:手机通过 HTTPS 到 Cloudflare,Access 先验证身份;Cloudflare 解开后经加密隧道送到电脑,cloudflared 再校验 Access 凭证;不是操作截图。

B1 · 先为网址加一道只允许本人的门

准备一个由 Cloudflare 托管的域名。下文用 pi.example.com 代表你的子域名;换成自己的,选一个还没有 DNS 记录的子域名,不修改根域名或已有网站的解析。

有多个 CF 账号时,在浏览器中选择包含目标域名的账号,确认 Zone(域名区域)、Tunnel 和 Access 的归属。Windows/WSL 中已有的 cert.pem、Wrangler 登录或环境变量,不证明当前属于正确账号。

在该账号创建或进入 Zero Trust,选择适用套餐,确认结算金额;单人试验先看 Free,不顺手开启付费增值项。管理账号开启双重验证。

在 Access → Applications 新建自托管 Web 应用,覆盖整个 pi.example.com,不要只保护首页。Allow 策略用 Emails 精确填写本人邮箱,未匹配者保持拒绝。不要选 Everyone,也不要把“使用邮箱验证码登录”本身当成授权名单;不要添加 Bypass。官方把“包含所有人”“包含所有有效邮箱”列为常见误配置,这样设等于谁都能进(Access 策略说明)。

登录方式可用本人身份提供商或邮箱验证码;敏感入口进一步开启可用的多因素认证。可以先从 24 小时会话有效期开始,之后按实际需求调整。手机无需安装 WARP。

保存 Access 后再创建公开路由。这个顺序能避免“隧道已经连通,登录保护还没建”的空档。

B2 · 独立隧道连接电脑,不动旧账号凭据

在 Pi Web 所在的 WSL 中,按 Cloudflare 官方下载说明安装 cloudflared。本例把它与 Pi Web 放在同一个环境,不依赖 Windows 到 WSL 的转发。

先给 Pi Web 配置 PI_WEB_ALLOWED_HOSTS=pi.example.com 和非空 PI_WEB_PASSWORD,保留 127.0.0.1:30141 监听。密码可使用 A2 中的静默输入方法;先等任务结束,停止原实例,再以相同用户和确认过的版本重启。不要把网站密码和模型 API Key 混用。

在已确认的 CF 账号中创建控制台管理的 Tunnel,取名如 pi-web。运行它只需要该隧道的专用 Token(运行凭据),不需要执行 cloudflared tunnel login,也不用替换旧 ~/.cloudflared/cert.pem。

先以前台进程验证,不直接复制 service install 覆盖已有服务。以下是 WSL Bash 的独立凭据保存方式;目录已存在就停下核对,不覆盖它:

(
  set -eu
  umask 077
  mkdir -p "$HOME/.config"
  mkdir "$HOME/.config/pi-web-tunnel"
  read -r -s -p '粘贴这条 Tunnel 的 Token:' TOKEN
  printf '\n'
  test -n "$TOKEN" || { printf 'Token 为空,已停止。\n'; exit 1; }
  printf '%s' "$TOKEN" > "$HOME/.config/pi-web-tunnel/token"
  unset TOKEN
)

不要在录屏时粘贴 Token;终端静默输入不能防止录到控制台原文、剪贴板历史或密码管理器。

用独立配置路径避免误读旧的默认配置。下面第一行只在第一次运行时创建空配置,之后重复执行也不会改动它;Token 不出现在命令参数里:

test -e "$HOME/.config/pi-web-tunnel/empty.yml" || printf '{}\n' > "$HOME/.config/pi-web-tunnel/empty.yml"
env -u TUNNEL_TOKEN -u TUNNEL_ORIGIN_CERT \
  cloudflared tunnel \
  --config "$HOME/.config/pi-web-tunnel/empty.yml" \
  run --token-file "$HOME/.config/pi-web-tunnel/token"

--token-file 需要 cloudflared 2025.4.0 或更新版本;其他旧的 TUNNEL_* 配置也应在专用进程环境中核对,不打印含秘密的完整环境变量。按控制台显示确认新隧道在线。

为这条隧道添加 Published application 路由:

配置项本文例子
Hostnamepi.example.com
Service URLhttp://127.0.0.1:30141
Protect with Access开启,选择刚才的 Access 应用及其 Audience

开启 Protect with Access 后,cloudflared 会再核对一次 Access 发的登录凭证。就算 Access 应用哪里配错,或者有别的路由也指向这条隧道,没有有效凭证的请求也到不了 Pi Web(校验 Access 凭证)。

保留公开 Host,不把 HTTP Host Header 强制改成 localhost。Pi Web 会核对请求上的地址是不是它认可的,对不上就拒绝发消息等操作。表里的 http:// 只是电脑内部的最后一段;手机到 Cloudflare、Cloudflare 到电脑都是加密的。

不要使用临时 Quick Tunnel(随机 trycloudflare.com 地址)。官方文档说明它不支持 SSE(Server-Sent Events,Pi Web 流式回复与终端使用的事件流)。也不用增加 Worker、Nginx 或路由器端口映射。

Token 是这条隧道的钥匙,拿到它就能运行这条隧道(Tunnel Token 说明)。单独的目录防止和别的账号混用,0600 让电脑上其他系统用户读不到;但同一用户下运行的智能体仍能读到它。长期运行前,应考虑独立服务身份/凭据隔离,权限和已有服务核对后再配置自启。

B3 · 用一次拒绝和一次成功验收

先开无痕窗口访问 https://pi.example.com/,预期是 Access 登录页;在未登录窗口直接访问 /api/sessions 也不能得到会话数据。非授权身份应被拒绝。只有账号没有密码并不安全,不能因首页出现登录页就省掉 API 验收。

本人通过 Access 后,还需通过 Pi Web 密码。先查看会话,再按 A3 的方式做一次非敏感、小成本回复测试。

在手机上分别测试其他 VPN 应用关闭与开启,再切换 Wi-Fi/蜂窝网络。两种状态用同一网址,但实际走的网络不同;若直连 CF 不畅,应记录具体网络,不把“开着 VPN 应用能用”写成“随时稳定”。

Chrome 安装到桌面后再测试一次登录返回,以及锁屏后重新打开。Access 到期时先重新访问首页完成登录;不要为修登录问题放行 /api/*。首次成功后即可停下,不急着配置通知和自启动。

以后每次开机,怎么重新用起来

第一次配好之后,电脑重启或关机再开,大部分东西会自己回来,只有 Pi Web 要手动启动。下面按路线 A 写。示例环境已用 A2.2 的脚本完成一次手动切换,手机无痕窗口验证过登录;Windows 重启后的完整恢复,还没有在示例环境里按这一节走过一遍。

开机后会不会自己回来
Windows 上的 Tailscale会,但默认要等你登录 Windows 才连上(无人值守模式说明)
Serve 的 HTTPS 地址会。用 --bg 开启的 Serve 在重启后自动恢复(Serve 文档)
WSL 和 Pi Web不会。Pi Web 每次都要在 WSL 里手动启动
手机上 Pi Web 的登录只要启动时用同一个密码,30 天内不用重新登录

最后一行来自 Pi Web 0.12.0 和 0.12.2 的源码:登录凭证用 Pi Web 密码签名,有效期 30 天。所以每次启动都输入同一个密码;换了密码,所有已登录的设备都要重新登录。

每次开机后

  1. 登录 Windows。PowerShell 里不用做任何事;想确认的话,运行 tailscale serve status,应该仍然显示那个 https://…ts.net 地址指向 http://127.0.0.1:30141。

  2. 打开 WSL 终端,运行 A2.2 创建的启动脚本,输入 Pi Web 密码:

    pi-web-start

    提示找不到命令时,用完整路径 ~/.local/bin/pi-web-start。在电脑浏览器里打开 http://127.0.0.1:30141,并按 A2.2 的两项只读检查确认 enabled: true 和 HTTP 401,才继续用手机访问。这个终端窗口可以最小化,不要关:关掉窗口或按 Ctrl+C,Pi Web 就停了。

  3. 手机上打开 Tailscale,确认已连接,再点桌面上的 Pi Web 图标。

关机前不用做额外的事。Pi Web 正在回复时,等它答完再关机:重启会打断正在进行的回复,会话记录还在。

升级 Pi Web 单独做,不放进每次开机:先运行 pi-web update --check 查看是否有新版本。要升级时等任务结束,依次执行 pi-web stop --port 30141、pi-web update,用 pi-web version 确认版本,再运行 pi-web-start 和 A2.2 的检查。本文没有实测升级过程。

路线 B 多一步:在另一个 WSL 终端里重新运行 B2 中那条 cloudflared tunnel … run --token-file … 命令。它也是前台进程,窗口关了,隧道就断。

人在外面时,电脑如果被系统更新重启,Pi Web 不会自己回来,只能等你回到电脑前。出门久的话,提前在 Windows 更新里设好使用时段,或者暂停更新。在 Tailscale 托盘菜单的 Preferences 里勾选 Run unattended,能让 Tailscale 在没人登录 Windows 时也保持在线,但它只管 Tailscale,Pi Web 仍要手动启动。让 Pi Web 开机全自动启动,就得把密码存在磁盘上,同一用户下运行的智能体也能读到它,本文不展开。

隔一段时间要重新登录的几样东西
什么多久到期时怎么办
Tailscale 设备密钥默认 180 天这台设备掉线在那台设备上重新登录 Tailscale
Pi Web 登录30 天,或换了密码回到登录页输入 Pi Web 密码
模型账号(订阅登录或 API Key)看提供商Pi Web 回复时报认证错误在电脑上打开 Pi Web 的 Models 面板,重新登录或重填 Key
HTTPS 证书Let's Encrypt 证书 90 天到期手机提示证书错误见下文
B:Access 登录你设的会话时长跳到 Access 登录页重新登录

电脑的密钥到期时,人在外面修不了:电脑已经掉线,手机连不上它。可以在 Tailscale 控制台的 Machines 页,从电脑那一行的菜单里选 Disable Key Expiry,让它不再到期(密钥过期说明)。代价是这台电脑的密钥不再自动作废,Tailscale 账号本身的安全就更要紧。不关的话,到期前回到电脑前重新登录一次。官方提醒,用 tailscale up --force-reauth 续期会短暂断线,不要隔着远程连接执行。

模型凭据和终端里的 Pi 共用,默认存在电脑的 ~/.pi/agent 下(Pi Web 中文说明),在 Pi Web 或终端里重新登录都可以。

证书由 Serve 自动签发,不用自己管理证书文件;官方文档没有写明 Serve 怎样续期,示例环境也还没用满 90 天。手机若提示证书错误,不要点忽略,先在电脑上运行 tailscale serve status,确认地址和服务都还在。

手机丢了、忘了密码、电脑重装:从哪一步重新开始
  • 忘了 Pi Web 密码:Pi Web 不保存密码。先运行 pi-web stop --port 30141,再运行 pi-web-start 输入新密码;所有设备都要用新密码重新登录。
  • 手机丢了:先在 Tailscale 控制台的 Machines 页删除这部手机,它就连不进你的网络了;再用新密码重启 Pi Web,旧手机上的登录随即失效,因为它的凭证是用旧密码签的。走路线 B 的,还要在 Cloudflare Zero Trust 里撤销这个用户的登录会话。
  • 换了新手机:装 Tailscale、登录同一账号,打开电脑的 ts.net 地址登录 Pi Web,再到控制台删掉旧手机。
  • 电脑重装系统,或 Tailscale 被登出:重新登录后,电脑在控制台里可能算一台新设备,名字也可能变,ts.net 地址就跟着变。把新地址写进 ~/.config/pi-web/allowed-hosts,重新执行 A2 里开启 Serve 的那两条命令,再删掉控制台里的旧设备。
  • ~/.pi/agent 丢了:模型要重新登录或重填 Key。会话记录也存在这个目录里(Pi Web 说明),所以它值得备份;备份里有凭据,要像密码一样保管。

连上以后,再解决这些事

组网就不受网络影响了吗?

仍然受影响。Tailscale 会先试着让两台设备直连;网络限制让直连不成时,改走加密中继(连接类型说明)。中继打不开内容,但可能更慢;直连也受手机信号、运营商线路和家里上行带宽影响。

手机保持在线,从电脑执行 tailscale status,或对手机设备名执行 tailscale ping。direct 表示直连,relay/peer-relay 表示经过中继。刚开始先经过中继、随后转直连是正常现象。先看真实路径,不先关防火墙、开路由器端口或购买服务器。

在国内用,经过中继时常常更慢:截至 2026 年 10 月,Tailscale 的默认中继没有设在大陆,最近的在香港、东京和新加坡(中继说明)。tailscale status 里中继后面跟着区域代码,比如 hkg 是香港、tok 是东京。长期走中继又嫌慢,有两个方向,本文都没有实测:

  • Tailscale 的 Peer Relay:让你网络里一台网络条件好、常开的设备当中继。它不能是手机,要 Tailscale 1.86 以上,并开放一个其他设备能访问的 UDP 端口。连接仍在同一个账号和访问规则里,本文的安全说法不变。
  • 换用能走国内共享节点的组网工具,比如国内开发者做的开源工具 EasyTier。代价不小:安卓不 root 时,它也要通过系统 VPN 接口工作,同样占 VPN 名额;没有现成的 HTTPS 地址,Pi Web 要改监听地址,PWA 安装和推送通知也用不了;知道网络名和密钥的设备都能进这个网络。用别人提供的共享节点时,要开启它的安全模式并锁定节点公钥,否则文档没有保证中继看不到内容。

临时关掉手机上的 VPN 应用,和手机完全没有互联网,是两回事。前者 A 仍可能连上;后者任何远程方案都不能用。CF、向日葵、UU 远程也没有免于网络影响。

电脑休眠、手机锁屏、任务会怎样?

电脑、WSL、Pi Web 都需要继续运行;锁屏与睡眠不同。日常使用前核对插电时的睡眠策略,不必把屏幕一直点亮。重启以后哪些会自己回来、哪些要手动启动,见上面「以后每次开机,怎么重新用起来」。

Pi Web 已被服务端接收的智能体任务不要求手机一直亮屏,返回后有状态恢复机制;这不代表重启 Pi Web 进程后任务也能无损继续。

网页终端另有生命周期:本文核对版本中,最后一个客户端断开约 120 秒后会回收。长时间终端工作可用 tmux(保持终端会话的工具),不要靠手机永不锁屏维持任务。

用哪种方式,费用和隐私更合适?

Tailscale 的 Personal 计划免费,官方写明只适合非商业用途(价格页);Serve 提供设备域名,不需要购买自有域名,工作用途按实际套餐条款确认。CF 个人规模可先用 Free,已有域名时不必买服务器,域名续费和模型调用费仍然存在。免费套餐不是无限资源或可用性承诺。

A 的网页内容在自己的电脑上解开;Tailscale 仍知道账号、设备和连接记录。B 的网页内容先在 CF 解开;应用密码和 Access 管的是谁能进,不会让 CF 看不到经过它的内容。需要公司或客户数据授权时,先走组织审批,不能把“只有我用”当成合规结论。

通知可以晚点开。Pi Web 完成推送可能把会话标题显示在手机锁屏上,避免在标题里写客户名或敏感内容。使用云模型还需单独考虑模型提供商的数据政策;换一种接入方式不会改变模型拿到的输入。

打不开时,按这个顺序查;想停用也很简单

先查电脑本地地址,再查连接工具是否在线,最后查手机网络和浏览器登录,不一次改三层配置。

现象先做什么
电脑本地地址打不开检查原 Pi Web 进程,先不改隧道
Windows 点登录后没反应等十几秒看浏览器是否弹出;仍没有,再点一次
A 在打开其他 VPN 应用后失联关掉那个应用,重新连接 Tailscale
重启 Pi Web 后弹出用户名和密码框点取消,关掉旧标签页,重新打开 Pi Web 地址只输密码
Serve 报 error enabling https feature在控制台 DNS 页面开启 HTTPS Certificates,稍等再运行 Serve
电脑上打开 ts.net 地址提示连接被重置电脑开着系统代理时,把 *.ts.net 加入代理绕过列表;手机不受影响
A 设备在线但 HTTPS 拒绝核对完整设备域名、Serve 状态、访问规则与 Pi Web 允许主机名
B 返回 403区分 Access 拒绝还是 Pi Web 的 Untrusted request,检查本人名单与 Host
B 返回 502/隧道离线在 cloudflared 所在环境访问本机服务;确认隧道出站网络通畅
回复一次性出现或长操作超时检查 SSE 是否被缓冲,单独测试手动压缩等长 POST,不反复重发有副作用的操作
登录后突然变成 HTML 错误回首页重新完成 Access 登录,不取消 API 保护

停用 A 时,先看 tailscale serve status,确认 443 确实是本教程的服务,再关闭这一条:

tailscale serve --https=443 off

不要用全局 reset 误删其他路由。停用 B 时,在自己的前台 cloudflared 窗口按 Ctrl+C,然后移除该子域名的隧道路由;保留 Access 到公开路由移除后,避免先撤门禁。Token 泄露需轮换并断开旧连接,不只是删除本地文件。

第一轮的完成标准很小:手机换到蜂窝网络后能登录、读到会话,且不该进入的人进不来。做到这里,再决定是否需要自启、通知和备用远程桌面。

写作说明:gpt-6-astra 起草、修订并绘制示意图;Claude Opus 5.5 补写开机恢复。

评论 →

CC BY-NC-SA 4.0

评论

评论由 GitHub Discussions 提供。登录 GitHub 后即可评论。 前往对应 Discussion