目标

把一台已经连接电脑并开启 USB 调试的小米手机,做成一个小型“云端 AI 编程工作站”:

  • 浏览器访问公网域名即可进入 Web IDE。
  • 手机本地运行 code-server,提供 VS Code Web UI。
  • 手机本地运行 ttyd,提供备用网页终端。
  • 使用 Cloudflare Tunnel 暴露公网服务,不需要手机有公网 IP,也不需要路由器端口转发。
  • 手机端服务可重启后继续启动。
  • 不暴露 Cloudflare token、code-server 密码等敏感信息。

最终访问地址:

https://ai.caibin.net/

架构

flowchart LR
  User["任意设备浏览器"] --> CF["Cloudflare / ai.caibin.net"]
  CF --> Tunnel["Cloudflare Tunnel"]
  Tunnel --> Phone["小米手机 Termux"]
  Phone --> CodeServer["code-server 127.0.0.1:8080"]
  Phone --> TTYD["ttyd 127.0.0.1:7681"]
  Phone --> SSHD["sshd 0.0.0.0:8022"]

核心思路:

  • code-server 只监听手机本机 127.0.0.1:8080
  • ttyd 只监听手机本机 127.0.0.1:7681
  • cloudflared 从手机主动连出到 Cloudflare。
  • Cloudflare 负责把公网域名 ai.caibin.net 转发到手机内的 http://127.0.0.1:8080

环境

本次环境:

  • 手机:小米,Android 15,arm64-v8a。
  • 手机应用:Termux 0.119.0-beta.3
  • 电脑:Windows。
  • 连接方式:USB 调试 + ADB。
  • 域名:caibin.net 托管在 Cloudflare。
  • 目标子域名:ai.caibin.net

电脑侧使用 ADB 临时转发本地端口:

adb forward tcp:17681 tcp:7681
adb forward tcp:18080 tcp:8080
adb forward tcp:18022 tcp:8022

对应关系:

| 电脑端口 | 手机端口 | 用途 | |---:|---:|---| | 17681 | 7681 | ttyd 网页终端 | | 18080 | 8080 | code-server | | 18022 | 8022 | Termux SSH |

一、准备 ADB

电脑一开始没有 adb,因此下载 Android 官方 platform-tools:

mkdir tools\android
curl.exe -L -o tools\android\platform-tools-latest-windows.zip `
  https://dl.google.com/android/repository/platform-tools-latest-windows.zip
Expand-Archive tools\android\platform-tools-latest-windows.zip -DestinationPath tools\android -Force
.\tools\android\platform-tools\adb.exe version

验证手机在线:

.\tools\android\platform-tools\adb.exe devices -l

能看到类似:

device product:zizhan model:22061218C device:zizhan

二、确认 Termux

确认 Termux 已安装:

adb shell pm list packages | Select-String termux

输出:

package:com.termux

启动 Termux:

adb shell am start -n com.termux/.app.TermuxActivity

三、安装基础工作站组件

在 Termux 中安装基础包:

pkg update -y
pkg install -y git openssh nodejs-lts python ripgrep tmux jq nano curl wget termux-tools ttyd

如果 Termux 出现 curl/libcurl 动态库错位,例如:

CANNOT LINK EXECUTABLE "curl": cannot locate symbol ...

先修复包环境:

apt update
apt full-upgrade -y

之后再继续安装。

四、安装并启动 code-server

Termux 仓库里可以直接安装 code-server

pkg install -y tur-repo
pkg update -y
pkg install -y code-server

配置 code-server:

mkdir -p ~/.config/code-server
cat > ~/.config/code-server/config.yaml <<EOF
bind-addr: 127.0.0.1:8080
auth: password
password: <你的强密码>
cert: false
EOF
chmod 600 ~/.config/code-server/config.yaml

启动:

code-server ~/workspace --bind-addr 127.0.0.1:8080 --auth password

五、安装并启动 ttyd 作为备用网页终端

ttyd 可以把终端暴露成网页。为了安全,绑定本机地址并启用 Basic Auth:

ttyd -i 127.0.0.1 -p 7681 -c "codex:<你的强密码>" tmux new -A -s codex

这样即使 code-server 配置出问题,还可以通过网页终端救回来。

六、写启动脚本

创建统一启动脚本:

mkdir -p ~/bin ~/.termux/boot ~/.local/var/log
nano ~/bin/start-codex-workstation

内容示例:

#!/data/data/com.termux/files/usr/bin/bash
export PATH="$PREFIX/bin:$PATH"

termux-wake-lock >/dev/null 2>&1 || true
mkdir -p "$HOME/.local/var/log"

sshd >/dev/null 2>&1 || true

pgrep -f "ttyd.*127.0.0.1:7681" >/dev/null 2>&1 || \
  nohup ttyd -i 127.0.0.1 -p 7681 -c "codex:$(cat "$HOME/.code-server-pass")" tmux new -A -s codex \
    > "$HOME/.local/var/log/ttyd.log" 2>&1 &

pgrep -f "code-server.*127.0.0.1:8080" >/dev/null 2>&1 || \
  nohup code-server "$HOME/workspace" --bind-addr 127.0.0.1:8080 --auth password \
    > "$HOME/.local/var/log/code-server.log" 2>&1 &

if [ -s "$HOME/.cloudflared/xiaomi-codex-token" ]; then
  pgrep -f "cloudflared tunnel run" >/dev/null 2>&1 || \
    nohup sh -c 'TUNNEL_TOKEN="$(cat "$HOME/.cloudflared/xiaomi-codex-token")"; export TUNNEL_TOKEN; exec cloudflared tunnel run' \
      > "$HOME/.local/var/log/cloudflared-xiaomi-codex.log" 2>&1 &
fi

授权并复制到 Termux:Boot:

chmod +x ~/bin/start-codex-workstation
cp ~/bin/start-codex-workstation ~/.termux/boot/start-codex-workstation
chmod +x ~/.termux/boot/start-codex-workstation

七、创建 Cloudflare Tunnel

进入 Cloudflare Dashboard:

Cloudflare Zero Trust -> 网络 -> 连接器 -> 创建隧道

步骤:

1. 选择 Cloudflared。 2. 隧道命名为 xiaomi-codex。 3. 在“安装并运行连接器”页面复制运行 token。 4. 将 token 保存到手机私有目录:

mkdir -p ~/.cloudflared
printf '%s' '<Cloudflare Tunnel Token>' > ~/.cloudflared/xiaomi-codex-token
chmod 600 ~/.cloudflared/xiaomi-codex-token

启动连接器:

TUNNEL_TOKEN="$(cat ~/.cloudflared/xiaomi-codex-token)" cloudflared tunnel run

日志里看到类似内容说明成功:

Starting tunnel tunnelID=...
Registered tunnel connection ...
Updated to new configuration config="{\"ingress\":[{\"hostname\":\"ai.caibin.net\",\"service\":\"http://127.0.0.1:8080\"},{\"service\":\"http_status:404\"}]}"

八、配置公网路由

在 Cloudflare Tunnel 的“已发布应用程序路由”中添加:

| 字段 | 值 | |---|---| | 子域名 | ai | | 域 | caibin.net | | 类型 | HTTP | | URL | 127.0.0.1:8080 |

最终路由:

ai.caibin.net -> http://127.0.0.1:8080

九、验证公网访问

电脑上验证:

Invoke-WebRequest -UseBasicParsing -Uri https://ai.caibin.net/ -TimeoutSec 20

成功结果:

Status: 200
Title: code-server login

DNS 解析:

nslookup ai.caibin.net 1.1.1.1
nslookup ai.caibin.net 8.8.8.8

会解析到 Cloudflare 的边缘 IP。

手机进程确认:

pgrep -af "cloudflared|code-server|ttyd|sshd"

应能看到:

cloudflared tunnel run
code-server ... 127.0.0.1:8080
ttyd ... 127.0.0.1:7681
sshd

十、把 code-server 改成中文

直接在线安装语言包时,code-server 可能报错:

The 'ms-ceintl.vscode-language-pack-zh-hans' extension is not available in code-server for the Web platform.

解决办法是从 Open VSX 下载 VSIX 离线安装:

curl.exe -L -o vscode-language-pack-zh-hans-1.126.0.vsix `
  https://open-vsx.org/api/MS-CEINTL/vscode-language-pack-zh-hans/1.126.0/file/MS-CEINTL.vscode-language-pack-zh-hans-1.126.0.vsix

推送到手机:

adb push vscode-language-pack-zh-hans-1.126.0.vsix /sdcard/Download/

在 Termux 里安装:

code-server --install-extension /sdcard/Download/vscode-language-pack-zh-hans-1.126.0.vsix --force

写入语言配置:

mkdir -p ~/.local/share/code-server/User
cat > ~/.local/share/code-server/User/argv.json <<'EOF'
{
  "locale": "zh-cn"
}
EOF

重启 code-server:

pkill -f "code-server.*127.0.0.1:8080"
~/bin/start-codex-workstation

验证语言包:

code-server --list-extensions | grep -i zh-hans

应输出:

ms-ceintl.vscode-language-pack-zh-hans

注意:登录页标题仍可能显示 code-server login,但登录后的 VS Code 主界面会使用中文语言包。

十一、踩坑记录

1. ADB input 空格问题

adb shell input text 中空格应写成 %s,否则会把 %20 当作字面字符输入:

adb shell input text 'bash%s/sdcard/Download/setup.sh'

2. Termux run-as 不等于真实交互 shell

虽然 debug 版 Termux 可通过 run-as com.termux 切到应用 UID,但 Android 15 / SELinux 会限制访问 Termux 私有目录。最终更稳定的方法是让 Termux 前台执行脚本,并把结果写入 /sdcard/Download/*.txt 再用 ADB 拉回。

3. code-server npm 版在 Termux 上可能编译失败

直接 npm install -g code-server 曾遇到 argon2 编译失败:

Undefined variable android_ndk_path in binding.gyp

解决办法:优先用 Termux 仓库或 TUR 仓库安装 code-server,不要走 npm 编译。

4. Cloudflare Tunnel token 不要放共享目录

初次配置可以临时把 token 推到 /sdcard/Download,但完成后应移入 Termux 私有目录:

~/.cloudflared/xiaomi-codex-token

并删除共享目录中的临时 token 文件。

5. Cloudflare Tunnel 比反向 SSH 更适合手机

本次也尝试过让手机用 SSH 公钥连接一台美国服务器做反向隧道,但服务器端公钥登录没有打通。最终使用 Cloudflare Tunnel 后,手机无需公网 IP,也无需中转 VPS,结构更简单。

安全建议

  • code-server 密码必须使用强密码。
  • 不要把 Cloudflare Tunnel token 写进博客、截图或公开仓库。
  • code-serverttyd 都只监听 127.0.0.1,不要直接监听 0.0.0.0
  • Cloudflare Tunnel 只暴露需要的入口,例如 ai.caibin.net -> 127.0.0.1:8080
  • 后续可以再加 Cloudflare Access,让访问 ai.caibin.net 前先过邮箱或身份验证。
  • 手机要长期插电时,注意散热和电池保护。

最终状态

最终服务状态:

| 服务 | 状态 | 用途 | |---|---|---| | cloudflared | 正常运行 | 公网 Tunnel | | code-server | 正常运行 | Web IDE | | ttyd | 正常运行 | 备用网页终端 | | sshd | 正常运行 | 局域网/ADB 转发 SSH |

公网验证:

https://ai.caibin.net/
HTTP 200
code-server login

至此,小米手机已经变成一个公网可访问的小型云端编程工作站。