LuoTianyi_HOLOMAIN/Tailscale + SSH 远程开发操作指南.md
Rdzleo 3373e88e5c 新增远程开发操作指南和官方参考文档
1、新增 Tailscale + SSH 远程开发操作指南:Mac 跨网络连接 Windows 虚拟机的完整配置(网络架构、ClashX Pro 增强模式与 Tailscale 共存、Docker Android 编译环境、换新电脑迁移方案、故障排除)
2、新增 Radxa 官方 Android 底层开发文档(Dockerfile 环境参考)
3、新增 .gitignore,排除 macOS 自动生成的 .DS_Store

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:03:46 +08:00

30 KiB
Raw Blame History

Tailscale + SSH 远程开发操作指南

文档概述

Mac 电脑通过 Tailscale 跨网络 SSH 连接 Windows 电脑上的 Linux 虚拟机VMware实现远程 Android 底层开发。

当前环境信息2026-04-15 已验证)

项目 信息
Mac 电脑 macOS, ClashX Pro (VPN), Tailscale
Windows 电脑 VMware Workstation 17, Clash for Windows v0.19.10
Linux 虚拟机 Ubuntu 20.04 LTS, VMware 桥接模式
虚拟机用户 zhangwenqi
Tailscale IP 100.123.82.91
虚拟机局域网 IP 192.168.6.60
SSH 密钥 Mac ~/.ssh/id_ed25519 已部署到虚拟机
Docker 28.1.1, 镜像 android-builder:12.x (3.43GB)
Android SDK 压缩包 102GB 已备份到 Windows虚拟机已删除
磁盘 700GB 虚拟磁盘,当前已用 13GB可用 640GB

第一部分:网络架构

1.1 整体架构

Mac (ClashX Pro VPN + Tailscale)
  |
  | Tailscale P2P (100.x.x.x)
  |
Linux 虚拟机 (Tailscale, IP: 100.123.82.91)
  |
  | VMware 桥接 (192.168.6.60)
  |
Windows (Clash for Windows, 端口 7890)

1.2 各设备职责

  • Mac: 开发主机VPN 翻墙 + SSH 远程开发
  • Windows: 宿主机,运行 VMware 虚拟机 + Clash 代理
  • Linux 虚拟机: 编译服务器Docker + Android SDK 编译环境

第二部分ClashX Pro 与 Tailscale 共存配置(关键)

Mac 上 ClashX Pro增强模式/TUN与 Tailscale 存在两个冲突,必须同时解决。

2.1 问题一:增强模式流量劫持

ClashX Pro 增强模式创建 TUN 虚拟网卡拦截所有流量Tailscale 的 WireGuard UDP 流量也被劫持,导致 Tailscale 连不上。

解决方法: 在 ClashX Pro 代理配置文件的 rules 最前面添加直连规则。

配置文件路径: ~/.config/clash/你的订阅配置.yaml

rules: 下方、第一条规则之前插入:

rules:
 - PROCESS-NAME,tailscaled,DIRECT
 - IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
 - IP-CIDR6,fd7a:115c:a1e0::/48,DIRECT,no-resolve
 - DOMAIN-SUFFIX,tailscale.com,DIRECT
 - DOMAIN-SUFFIX,login.tailscale.com,DIRECT
 # ... 原有规则保持不变 ...

各规则作用:

  • PROCESS-NAME,tailscaled,DIRECT → Tailscale 进程所有流量直连(最关键)
  • IP-CIDR,100.64.0.0/10,DIRECT → Tailscale 内网 IP 段直连
  • IP-CIDR6,fd7a:115c:a1e0::/48,DIRECT → Tailscale IPv6 段直连
  • DOMAIN-SUFFIX,tailscale.com,DIRECT → Tailscale 控制服务器直连
  • DOMAIN-SUFFIX,login.tailscale.com,DIRECT → Tailscale 认证直连

2.2 问题二MagicDNS 劫持域名解析

Tailscale 默认开启 MagicDNS将系统 DNS 改为 100.100.100.100,与 ClashX Pro 增强模式的 fake-ip DNS198.18.0.2)冲突。

典型表现:浏览器能访问 YouTube但 Claude Code 等终端应用无法连接。

解决方法: 关闭 Tailscale DNS 接管。

操作步骤:

  1. 点击 Mac 菜单栏 Tailscale 图标
  2. 进入 Preferences偏好设置
  3. 找到 "Use Tailscale DNS Settings" → 关闭

或通过管理后台:浏览器打开 https://login.tailscale.com/admin/dns → 关闭 MagicDNS

2.3 订阅更新覆盖问题

ClashX Pro 订阅更新会覆盖配置文件Tailscale 直连规则会丢失。

应对: 每次订阅更新后,重新在 rules: 下插入 2.1 中的 5 条规则,然后 ClashX Pro 菜单 → 配置 → 重新加载配置。

备份规则片段方便粘贴:

 - PROCESS-NAME,tailscaled,DIRECT
 - IP-CIDR,100.64.0.0/10,DIRECT,no-resolve
 - IP-CIDR6,fd7a:115c:a1e0::/48,DIRECT,no-resolve
 - DOMAIN-SUFFIX,tailscale.com,DIRECT
 - DOMAIN-SUFFIX,login.tailscale.com,DIRECT

2.4 验证清单

  1. 开启 ClashX Pro 增强模式 + 选择代理节点
  2. 开启 Tailscale
  3. 浏览器访问 YouTube → VPN 正常
  4. 终端 ssh zhangwenqi@100.123.82.91 → Tailscale SSH 正常
  5. Claude Code 对话 → DNS 解析正常

失败排查:

  • 第 3 步失败 → 检查代理节点
  • 第 4 步失败 → 检查 rules 中 Tailscale 直连规则
  • 第 5 步失败 → 检查 Tailscale DNS Settings 是否已关闭

第三部分Linux 虚拟机环境配置

3.1 Tailscale 安装

# 安装
curl -fsSL https://tailscale.com/install.sh | sh

# 启动并认证(浏览器打开输出的链接登录)
sudo tailscale up

# 查看分配的 IP
tailscale ip -4

3.2 SSH 服务

# 安装(如未安装)
sudo apt update && sudo apt install openssh-server -y

# 启动
sudo systemctl enable --now ssh

# 检查状态
sudo systemctl status ssh

3.3 Docker 安装

# 添加 Docker 清华镜像源
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu focal stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装
sudo apt-get update -y
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 当前用户加入 docker 组(免 sudo
sudo usermod -aG docker $USER
# 需要重新登录生效

3.4 Docker 镜像加速(国内必须配置)

Docker Hub 在国内无法直接访问,需要配置镜像加速器:

sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me",
    "https://docker.m.daocloud.io"
  ]
}
EOF
sudo systemctl daemon-reload && sudo systemctl restart docker

注意:镜像加速器地址可能失效,届时搜索"Docker 镜像加速 2026"获取最新可用地址。

3.5 构建 Android 12 编译镜像

Dockerfile 位于虚拟机 ~/Radxa_CM5/docker/Dockerfile,内容基于 Radxa 官方文档,使用清华镜像源。

cd ~/Radxa_CM5/docker
sudo docker build -t android-builder:12.x .

构建完成验证:

sudo docker run --rm android-builder:12.x bash -c \
  'java -version 2>&1; python3 --version; gcc --version | head -1; which repo'

预期输出:

  • Java: openjdk 1.8.0
  • Python: 3.8.x
  • GCC: 9.4.0
  • Repo: /usr/local/bin/repo

与官方 Dockerfile 的差异(重要)

当前镜像缺少官方 Dockerfile 中的 5 套 Linaro 交叉编译工具链 COPY

gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf   → /opt/ 和 /opt/toolchains/
gcc-linaro-aarch64-none-elf-4.8-2013.11_linux          → /opt/ 和 /opt/toolchains/
gcc-arm-none-eabi-6-2017-q2-update                     → /opt/toolchains/
gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu      → /opt/toolchains/
gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf            → /opt/toolchains/

原因: 这些工具链需要单独下载(官方文档未提供下载地址),放到 Dockerfile 同目录才能 COPY。

影响评估:

  • Radxa Android SDK 的 prebuilts/ 目录自带编译所需工具链
  • 编译脚本 build.sh 优先使用 SDK 内的工具链
  • 这些 Linaro 工具链主要给 U-Boot 和 kernel 单独编译

编译时如果报错找不到工具链,按以下方式排查修复:

  1. 确认报错中缺少的具体工具链名称
  2. 搜索 Linaro 官网下载对应版本:https://releases.linaro.org/components/toolchain/binaries/
  3. 解压到 Docker 容器的 /opt/toolchains/ 目录:
    # 在容器内
    cd /opt/toolchains
    wget <工具链下载地址>
    tar -xf <工具链压缩包>
    
  4. 或者将工具链放到 ~/Radxa_CM5/docker/ 目录,取消 Dockerfile 中 COPY 行注释后重新构建镜像

3.6 使用 Docker 编译 Android SDK

3.6.1 解压 SDK

cd ~/Radxa_CM5/SDK_Android
tar -xzf radxa_android_sdk_backup.tar.gz
# 解压后目录为 radxa-android-sdk/,耗时视磁盘速度而定

3.6.2 编译前必须修复的问题(重要)

SDK 存在两个已知问题,必须在编译前修复,否则编译会失败。

问题一GMS 引用不存在lunch 阶段报错)

错误信息:vendor/partner_gms/products/gms.mk does not exist

原因RadxaCM5.mk 引用了 Google GMS 包Google Play 服务),但开源 SDK 不包含 GMS需 Google 授权)。

修复:注释掉 GMS 引用行。

cd ~/Radxa_CM5/SDK_Android/radxa-android-sdk
sed -i 's/$(call inherit-product, vendor\/partner_gms\/products\/gms.mk)/#$(call inherit-product, vendor\/partner_gms\/products\/gms.mk)/' device/rockchip/rk3588/RadxaCM5/RadxaCM5.mk

验证:

grep "gms" device/rockchip/rk3588/RadxaCM5/RadxaCM5.mk
# 应看到该行前面有 # 注释符

注意:注释 GMS 后编译出的系统不含 Google Play 商店和 Google 服务,其他功能不受影响。

问题二:缺少 RadxaCM5.config 内核配置文件kernel 编译阶段报错)

错误信息:No configuration exists for this target on this architecture - RadxaCM5.config

原因BoardConfig.mk 指定 PRODUCT_KERNEL_CONFIG := rockchip_defconfig android-11.config RadxaCM5.config,但 kernel-5.10/kernel/configs/ 目录下没有 RadxaCM5.config 文件。

修复:参考 rock5b.config 创建 CM5 内核配置文件。

cat > kernel-5.10/kernel/configs/RadxaCM5.config << 'EOF'
CONFIG_SND_SOC_ES8316=y
CONFIG_RTL8852BE=m
CONFIG_BT_RTKBTUSB=y
CONFIG_SENSORS_PWM_FAN=y
CONFIG_TOUCHSCREEN_GT9XX=y
CONFIG_TOUCHSCREEN_FTS=y
CONFIG_TOUCHSCREEN_FTS_RADXA=y
CONFIG_DRM_PANEL_RADXA=y
CONFIG_DRM_PANEL_RASPBERRYPI_TC358762=y
CONFIG_ROCKPI_MCU=y
CONFIG_VIDEO_IMX219=y
EOF

3.6.3 编译前增大 Swap防止 OOM重要

Android 全量编译内存峰值可超过 20GB虚拟机默认 Swap 仅 1GB编译到 99% 时会因内存不足被 OOM Killer 杀死进程。

# 创建 8GB Swap 文件
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 写入 fstab 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 验证(应显示 9GB 左右 Swap
free -h | grep -i swap

同时建议 VMware 虚拟机内存分配 16GB 以上20GB+ 更佳)。

3.6.4 进入 Docker 编译环境

# 注意挂载的是解压后的 radxa-android-sdk 目录
sudo docker run -it \
  --name android-build \
  -v ~/Radxa_CM5/SDK_Android/radxa-android-sdk:/workspace \
  -w /workspace \
  android-builder:12.x \
  bash

3.6.5 执行编译

# 在 Docker 容器内执行
source build/envsetup.sh
lunch RadxaCM5-userdebug

# 方法一:全量编译(推荐,约 5 小时)
# 如果虚拟机内存 ≤ 20GB建议用 -j8 限制线程数减少内存峰值
./build.sh -AUCKup

# 方法二:如果 build.sh 因 OOM 中途失败,用 make 继续(会复用已编译缓存)
make -j8

编译参数说明:-A AOSP、-U U-Boot、-C Config、-K Kernel、-u update.img、-p 打包

编译过程中 Build sandboxing disabled due to nsjail error 是正常提示Docker 容器内不支持 nsjail 沙箱,不影响编译。

3.6.6 编译后打包镜像

如果使用 make -j8 单独编译 AOSP非 build.sh需要手动打包

# 在容器内执行
./mkimage.sh

3.6.7 验证编译结果

ls -lh rockdev/Image-RadxaCM5/

预期镜像文件:

文件 说明
MiniLoaderAll.bin Bootloader 加载器
idbloader.img IDB Loader
uboot.img U-Boot
boot.img Boot 镜像(内核+ramdisk
recovery.img Recovery 模式镜像
super.img 系统分区system+vendor+odm约 1.6GB
dtbo.img 设备树 Overlay
resource.img 内核资源

3.6.8 退出和重新进入容器

# 退出容器
exit

# 重新进入已创建的容器
sudo docker start -ai android-build

3.6.9 烧录到开发板

编译完成的镜像在虚拟机 ~/Radxa_CM5/SDK_Android/radxa-android-sdk/rockdev/Image-RadxaCM5/ 目录。

拿到 CM5 开发板后:

  1. 将镜像文件拷贝到 Windows
  2. 使用 RKDevTool(瑞芯微官方烧录工具)烧录
  3. 开发板进入 Loader 模式(按住 Recovery 按键上电)
  4. 在 RKDevTool 中加载各 img 文件烧录

3.7 Linux 虚拟机共享 Windows VPN外网访问

虚拟机通过 VMware 桥接网络使用 Windows 的 Clash 代理上外网。已配置开机自动生效。

当前配置信息2026-04-15 已验证)

项目
Windows 局域网 IP 192.168.6.57
Clash 代理端口 7890
虚拟机代理配置文件 /etc/profile.d/proxy.sh

Windows 端配置(一次性)

  1. Clash for Windows → 开启 "允许局域网连接入Clash"Allow LAN
  2. Windows 防火墙放行 7890 端口(管理员 PowerShell 执行):
    netsh advfirewall firewall add rule name="Clash Proxy" dir=in action=allow protocol=tcp localport=7890
    

Linux 虚拟机端配置(已完成,开机自动生效)

代理配置写入 /etc/profile.d/proxy.sh,每次登录自动加载:

export http_proxy="http://192.168.6.57:7890"
export https_proxy="http://192.168.6.57:7890"
export HTTP_PROXY="http://192.168.6.57:7890"
export HTTPS_PROXY="http://192.168.6.57:7890"
export no_proxy="localhost,127.0.0.1,100.64.0.0/10,192.168.0.0/16"
export NO_PROXY="localhost,127.0.0.1,100.64.0.0/10,192.168.0.0/16"

验证外网

curl -I https://www.google.com
curl -I https://releases.linaro.org/

前提条件

  • Windows 电脑开机且 Clash 运行中
  • Clash 的 "允许局域网连接入Clash" 保持开启

注意事项

  • Windows IP 变化:如果 Windows 通过 DHCP 获取 IP重启路由器后 IP 可能变化。届时需要修改 /etc/profile.d/proxy.sh 中的 IP 地址:

    sudo nano /etc/profile.d/proxy.sh
    # 将 192.168.6.57 替换为新的 Windows IP
    

    然后重新登录或执行 source /etc/profile.d/proxy.sh 生效。 建议在 Windows 上设置静态 IP 或在路由器中绑定 DHCP 避免此问题。

  • Docker 容器内使用代理/etc/profile.d/ 的代理对 Docker 容器内不生效,启动容器时需传入环境变量:

    sudo docker run -it \
      -e http_proxy="http://192.168.6.57:7890" \
      -e https_proxy="http://192.168.6.57:7890" \
      -e no_proxy="localhost,127.0.0.1" \
      --name android-build \
      -v ~/Radxa_CM5/SDK_Android:/workspace \
      -w /workspace \
      android-builder:12.x bash
    

第四部分Mac 端 SSH 连接配置

4.1 生成 SSH 密钥

ssh-keygen -t ed25519 -C "mac-to-linux-vm"
# 一路回车使用默认设置

4.2 部署公钥到虚拟机

ssh-copy-id zhangwenqi@100.123.82.91
# 输入虚拟机密码,完成后即可免密登录

4.3 SSH 配置文件

编辑 ~/.ssh/config

Host linux-vm
    HostName 100.123.82.91
    User zhangwenqi
    Port 22
    ServerAliveInterval 30
    TCPKeepAlive yes
    ConnectTimeout 60

之后直接 ssh linux-vm 即可连接。

4.4 VS Code Remote-SSH

  1. VS Code 安装 Remote - SSH 扩展
  2. Cmd+Shift+P → "Remote-SSH: Connect to Host"
  3. 选择 linux-vm
  4. 连接成功后打开文件夹 /home/zhangwenqi/Radxa_CM5

第五部分:换新电脑配置指南

5.1 虚拟机备份说明

当前备份状态2026-04-16

项目 状态
备份格式 OVF.ovf + .vmdk + .mf 三个文件)
备份内容 系统 + Docker不含 SDK不含工具链 COPY 到镜像)
Docker 镜像 android-builder:12.x 基础环境已装,未对齐官方工具链
SDK 压缩包 单独存放在 Windows 电脑/移动硬盘

OVF 备份包含的设置

配置项 是否备份 导入后能否修改
硬盘大小700GB 包含 可扩大,不可缩小
内存大小 包含 可自由调整
CPU 核心数 包含 可自由调整
网络适配器类型(桥接) 包含 可改为 NAT/桥接/仅主机
操作系统和所有软件 包含

三个文件必须放在同一文件夹,缺一不可:

  • .ovf — 虚拟机配置描述CPU、内存、网卡等
  • .vmdk — 虚拟磁盘数据(系统和所有文件)
  • .mf — 校验文件(验证完整性)

5.2 新电脑是 Windows — 完整恢复步骤

步骤 1导入虚拟机

  1. 新电脑安装 VMware Workstation 17(或更高版本)
  2. VMware → 文件 → 打开 → 选择 .ovf 文件
  3. 选择虚拟机存放位置(建议放在 SSD 上)
  4. 等待导入完成
  5. (可选)调整虚拟机参数:右键虚拟机 → 设置
    • 内存:建议 16GB+Android 编译非常吃内存)
    • CPU建议分配 8 核+
    • 网络:选择桥接模式(与宿主机同网段)

步骤 2启动虚拟机并恢复网络

  1. 启动虚拟机,登录(用户: zhangwenqi

  2. 检查网络:

    ip addr show    # 确认获取到 IP
    ping 8.8.8.8    # 测试内网连通性
    
  3. 恢复 Tailscale

    sudo systemctl status tailscaled    # 检查 Tailscale 服务
    sudo tailscale up                   # 重新认证(可能需要)
    tailscale ip -4                     # 记录新的 Tailscale IP
    
  4. 更新代理配置Windows IP 可能变化):

    # 在 Windows cmd 执行 ipconfig 获取新的局域网 IP
    # 然后更新虚拟机代理配置
    sudo nano /etc/profile.d/proxy.sh
    # 将 192.168.6.57 替换为新 Windows 的局域网 IP
    source /etc/profile.d/proxy.sh
    
    # 测试外网
    curl -I https://www.google.com
    

步骤 3恢复 SDK

# 将 SDK 压缩包从移动硬盘拷贝到虚拟机
# 可以通过 VMware 共享文件夹、scp、或 USB 挂载
cd ~/Radxa_CM5/SDK_Android/
# 确认文件
ls -lh radxa_android_sdk_backup.tar.gz
# 校验 MD5
md5sum radxa_android_sdk_backup.tar.gz

步骤 4对齐官方 Dockerfile 环境(重要)

备份的虚拟机中 Docker 镜像是基础版本,缺少 5 套 Linaro 交叉编译工具链。需要重新下载工具链并重建镜像。

4.1 确认 Docker 和基础镜像正常

docker images android-builder
# 预期看到 android-builder:12.x 镜像

4.2 确认代理可用(下载工具链需要外网)

curl -I https://releases.linaro.org/
# 预期 HTTP 200

如果不通,先按 3.7 节配置虚拟机代理。

4.3 下载 5 套交叉编译工具链

cd ~/Radxa_CM5/docker

# 1. gcc-linaro-6.3.1 arm-linux-gnueabihf99MB
curl -L -o gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz \
  'https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/arm-linux-gnueabihf/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz'

# 2. gcc-linaro-aarch64-none-elf-4.850MB
curl -L -o gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.bz2 \
  'https://releases.linaro.org/archive/13.11/components/toolchain/binaries/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.bz2'

# 3. gcc-arm-none-eabi-6-2017-q2-update96MB
curl -L -o gcc-arm-none-eabi-6-2017-q2-update.tar.bz2 \
  'https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2'

# 4. gcc-linaro-6.3.1 aarch64-linux-gnu106MB
curl -L -o gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz \
  'https://releases.linaro.org/components/toolchain/binaries/6.3-2017.02/aarch64-linux-gnu/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz'

# 5. gcc-linaro-7.2.1 aarch64-elf51MB
curl -L -o gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf.tar.xz \
  'https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/aarch64-elf/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf.tar.xz'

4.4 解压工具链

cd ~/Radxa_CM5/docker
tar -xf gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz
tar -xf gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.bz2
tar -xf gcc-arm-none-eabi-6-2017-q2-update.tar.bz2
tar -xf gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz
tar -xf gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf.tar.xz

# 确认解压结果(应有 5 个目录)
ls -d gcc-*/

4.5 确认 Dockerfile 包含 COPY 命令

查看 ~/Radxa_CM5/docker/Dockerfile,确认包含以下 COPY 行:

COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/toolchains/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
COPY ./gcc-arm-none-eabi-6-2017-q2-update /opt/toolchains/gcc-arm-none-eabi-6-2017-q2-update
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu
COPY ./gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf /opt/toolchains/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf

如果 Dockerfile 中没有这些行(备份时可能是旧版本),用以下完整 Dockerfile 替换:

cat > ~/Radxa_CM5/docker/Dockerfile << 'EOF'
FROM ubuntu:20.04

RUN rm /etc/apt/sources.list
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse" | tee /etc/apt/sources.list
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse" >> /etc/apt/sources.list
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse" >> /etc/apt/sources.list
RUN echo "deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse" >> /etc/apt/sources.list

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -y && apt-get install -y software-properties-common apt-utils
RUN add-apt-repository -y ppa:deadsnakes/ppa
RUN apt-get update -y && apt-get install -y python3.8
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 150
RUN apt-get install -y python3-pip && pip install pycrypto

RUN apt-get update -y && apt-get install -y openjdk-8-jdk python git-core gnupg flex bison gperf build-essential \
    zip curl gawk liblz4-tool zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
    libncurses5 libncurses-dev x11proto-core-dev libx11-dev lib32z-dev ccache \
    libgl1-mesa-dev libxml2-utils xsltproc unzip mtools u-boot-tools \
    htop iotop sysstat iftop pigz bc device-tree-compiler lunzip \
    dosfstools vim-common parted udev libssl-dev sudo rsync python3-pyelftools cpio

RUN curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > /usr/local/bin/repo && \
    chmod +x /usr/local/bin/repo && \
    which repo

ENV REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'

RUN apt-get install -y lzop swig
RUN apt-get update -y && apt-get install -y tzdata

RUN mkdir /opt/toolchains

COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
COPY ./gcc-linaro-aarch64-none-elf-4.8-2013.11_linux /opt/toolchains/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
COPY ./gcc-arm-none-eabi-6-2017-q2-update /opt/toolchains/gcc-arm-none-eabi-6-2017-q2-update
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf
COPY ./gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu
COPY ./gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf /opt/toolchains/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf

RUN apt-get install -y net-tools gcc-arm-linux-gnueabihf gcc-arm-none-eabi

ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
EOF

4.6 重建 Docker 镜像

cd ~/Radxa_CM5/docker
sudo docker build -t android-builder:12.x .
# 耗时约 10-15 分钟

4.7 验证环境完整

sudo docker run --rm android-builder:12.x bash -c \
  'echo "=== 工具链 ===" && ls /opt/toolchains/ && \
   echo "" && echo "=== 编译器 ===" && \
   /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc --version | head -1 && \
   /opt/toolchains/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf-gcc --version | head -1 && \
   /opt/toolchains/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc --version | head -1 && \
   java -version 2>&1 | head -1 && python3 --version && which repo'

预期输出:

  • /opt/toolchains/ 下有 5 个工具链目录
  • arm-linux-gnueabihf-gcc 6.3.1
  • aarch64-elf-gcc 7.2.1
  • aarch64-linux-gnu-gcc 6.3.1
  • openjdk 1.8.0
  • Python 3.8.x
  • /usr/local/bin/repo

4.8 清理下载的压缩包

cd ~/Radxa_CM5/docker
rm -f *.tar.xz *.tar.bz2

注意Docker 镜像加速器配置(/etc/docker/daemon.json)在备份中已保留,但镜像加速地址可能失效。 如果 docker build 拉取 ubuntu:20.04 失败,参考 3.4 节更新加速器地址。

5.2 新电脑是 Windows — 快速恢复

步骤 1导入虚拟机

  1. 新电脑安装 VMware Workstation 17
  2. VMware → 文件 → 打开 → 选择 .ovf 文件
  3. 选择存放位置,等待导入
  4. 调整参数(右键 → 设置):内存 16GB+CPU 8 核+,网络桥接模式

步骤 2恢复网络和代理

  1. 启动虚拟机,检查网络
  2. 更新 /etc/profile.d/proxy.sh 中的 Windows IP如果 IP 变化)
  3. Windows 安装 Clash开启 Allow LAN防火墙放行 7890
  4. 安装 TailscaleWindows + 虚拟机),同账号登录

步骤 3恢复 SDK 并对齐 Dockerfile

  1. 拷贝 SDK 压缩包到虚拟机 ~/Radxa_CM5/SDK_Android/
  2. 按上方 步骤 44.1~4.8 对齐官方 Dockerfile 环境
  3. 解压 SDK 并编译验证

步骤 4配置 Mac 远程开发(如有)

按第四部分重新配置 Mac 端 SSH 和 Tailscale。

5.3 新电脑是 Mac远程控制 Windows 开发)

Mac M 芯片无法运行 x86 虚拟机,采用 Mac 远程控制 Windows 方案。

前提条件

  • Windows 电脑保持运行(作为编译服务器)
  • Windows 上已按 5.2 完成虚拟机恢复和 Dockerfile 对齐
  • Mac 和 Windows 都安装 Tailscale

步骤 1Windows 端配置

  1. 按 5.2 完成虚拟机导入、网络恢复、SDK 恢复、Dockerfile 对齐

  2. 安装 TailscaleWindows 版),用同一账号登录

  3. 安装 Clash for Windows导入订阅开启 "允许局域网连接入Clash" 防火墙放行:

    netsh advfirewall firewall add rule name="Clash Proxy" dir=in action=allow protocol=tcp localport=7890
    
  4. 启动虚拟机,确认服务正常:

    tailscale status
    sudo systemctl status ssh
    curl -I https://www.google.com    # 验证外网代理
    docker images android-builder     # 验证 Docker 镜像
    
  5. 可选设置虚拟机开机自启VMware → 编辑 → 首选项 → 共享虚拟机 → 开机启动

步骤 2新 Mac 端配置

  1. 安装 TailscaleApp Store用同一账号登录

  2. 安装 ClashX Pro导入订阅

  3. 配置 ClashX Pro 与 Tailscale 共存(按第二部分操作):

    • 添加 Tailscale 直连规则到代理配置
    • 关闭 Tailscale DNS Settings
  4. 生成 SSH 密钥并部署:

    ssh-keygen -t ed25519 -C "new-mac-to-linux-vm"
    ssh-copy-id zhangwenqi@<虚拟机Tailscale_IP>
    

    注意Tailscale IP 可能与之前不同,在虚拟机中执行 tailscale ip -4 确认。

  5. 配置 SSH config~/.ssh/config

    Host linux-vm
        HostName <虚拟机Tailscale_IP>
        User zhangwenqi
        Port 22
        ServerAliveInterval 30
        TCPKeepAlive yes
        ConnectTimeout 60
    
  6. 安装 VS Code + Remote-SSH 扩展

  7. Cmd+Shift+P → "Remote-SSH: Connect to Host" → linux-vm

步骤 3验证

# Mac 终端测试
ping <虚拟机Tailscale_IP>
ssh linux-vm

# 验证 Docker 环境完整(应显示 5 套工具链)
ssh linux-vm "docker run --rm android-builder:12.x ls /opt/toolchains/"

# 验证 VPN
# 浏览器访问 YouTube

日常使用流程

  1. Windows 电脑开机 → 虚拟机自动启动(或手动启动)
  2. Mac 打开 Tailscale + ClashX Pro
  3. VS Code → Remote-SSH → linux-vm
  4. 打开 /home/zhangwenqi/Radxa_CM5 开始开发

第六部分:故障排除

6.1 Tailscale 连不上

# Linux 端检查
sudo tailscale status
sudo systemctl restart tailscaled
sudo tailscale up

# 诊断
tailscale netcheck

6.2 SSH 连接被拒绝

# Linux 端检查
sudo systemctl status ssh
sudo netstat -tlnp | grep :22
sudo ufw status

# 重启 SSH
sudo systemctl restart ssh

6.3 VPN 开启 Tailscale 后失效

检查两个配置:

  1. ClashX Pro 配置文件中 Tailscale 直连规则是否存在(订阅更新会覆盖)
  2. Tailscale DNS Settings 是否已关闭

6.4 Docker 拉取镜像超时

Docker Hub 被墙,检查镜像加速配置:

cat /etc/docker/daemon.json
# 确认 registry-mirrors 配置正确
sudo systemctl restart docker

6.5 VS Code Remote-SSH 连接超时

~/.ssh/config 中增大超时:

Host linux-vm
    ConnectTimeout 120
    ServerAliveInterval 30
    ServerAliveCountMax 5

第七部分:快速参考

日常连接命令

# Mac 终端直连
ssh linux-vm

# 文件传输
scp file.txt linux-vm:~/
scp -r folder/ linux-vm:~/destination/

VS Code 操作

  • Cmd+Shift+P → "Remote-SSH: Connect to Host" → linux-vm
  • Cmd+Shift+P → "Remote-SSH: Disconnect"

Linux 虚拟机管理

# Tailscale
tailscale ip -4
tailscale status
sudo tailscale down / up

# Docker
docker images
docker run -it --name android-build -v ~/Radxa_CM5/SDK_Android:/workspace -w /workspace android-builder:12.x bash
docker start -ai android-build    # 重新进入已创建的容器

# SSH
sudo systemctl status ssh
sudo systemctl restart ssh

文档版本: 2.0 最后更新: 2026-04-15 适用系统: Ubuntu 20.04 LTS (x86_64), macOS 网络环境: 跨网络远程开发Tailscale + ClashX Pro 共存)