--- name: 老旧NAS chroot部署完整经验 device: Synology DS213j (armv7l, 内核3.2.40, 497MB RAM) category: 运维经验 / PCDN部署 difficulty: 高 source: 卡若AI/_经验库/待沉淀/2026-02-14_老旧NAS网心云chroot部署完整经验.md copied_date: "2026-02-15" --- # 老旧NAS(无Docker/无cgroup)网心云chroot完整部署经验 > **日期**:2026-02-14 > **设备**:Synology DS213j (armv7l, 内核3.2.40, 497MB RAM) > **难度**:高(涉及chroot、文件系统挂载、二进制兼容性、containerd、cgroup绕过) > **价值**:适用于所有不支持Docker的ARM32老设备 > **最终状态**:3个任务稳定运行(CB*.0 + CG*.0 + CG*.1),guluplugin收益已注册 --- ## 零、最简部署链路(结论先行) ### 0.1 所需组件(全部已验证,打包后直接用) | 组件 | 大小 | 来源 | 作用 | |:---|:---|:---|:---| | wxedge_fs.tar | 130MB | Docker镜像导出 | 完整rootfs文件系统 | | 已补丁wxedged | — | 原始二进制+Python补丁 | /proc路径重定向 | | 已补丁containerd-shim-runc-v2 | — | 原始二进制+ARM指令补丁 | prctl bypass + _shimexe_ | | fake_runc v6 | 5KB | shell脚本 | 替代runc(支持gulu/pcdn/thunder) | | cntr.toml | 2KB | 手动配置 | 禁用overlayfs,用native snapshotter | | fake_stat | 3KB | 生成 | 22核CPU伪装 | | musl库(Alpine v3.12) | 1MB | Alpine包 | guluplugin的C++运行库 | | chroot_start.sh | 5KB | 本文档 | 主启动脚本(含所有修复) | ### 0.2 部署步骤(3步,10分钟) ```bash # 1. 上传(2分钟) sshpass -p 'zhiqun1984' scp -O -c aes256-cbc wxedge_bundle.tar admin@NAS_IP:/volume1/wxedge/ # 2. 解压(3分钟) ssh -c aes256-cbc admin@NAS_IP 'echo "zhiqun1984" | sudo -S sh -c " cd /volume1/wxedge && tar xf wxedge_bundle.tar tar xf wxedge_fs.tar -C rootfs "' # 3. 启动(等3分钟后验证) ssh -c aes256-cbc admin@NAS_IP 'echo "zhiqun1984" | sudo -S nohup /volume1/wxedge/chroot_start.sh &' curl -s http://NAS_IP:18888/docker/dashboard # 有run_tasks即成功 ``` ### 0.3 核心技术决策(为什么这样做) | 决策 | 原因 | 备选方案及其失败原因 | |:---|:---|:---| | chroot而非Docker | 内核3.2无cgroup/namespace | Docker需要cgroup+namespace | | 二进制补丁而非重编译 | 无Go交叉编译环境 | 源码不公开,无法重编译 | | fake_runc而非真runc | 内核3.2无namespace/pivot_root | runc所有操作都依赖namespace | | native snapshotter | 内核3.2无overlayfs | 唯一兼容的snapshotter | | Alpine v3.12 musl库 | musl 1.1.x无time64符号 | 3.14+的musl 1.2+有time64不兼容 | | 不挂sysfs | sysfs会遮盖手动创建的cgroup目录 | 挂sysfs后cgroup panic | --- ## 一、问题背景 DS213j 是2013年的群晖NAS,特殊限制: - **内核3.2.40**:无cgroup支持、无overlayfs - **无Docker套件**:群晖不为此型号提供Container Manager - **armv7l架构**:32位ARM,Marvell Armada-370处理器 - **497MB内存**:系统自身占用后剩余约300MB - **老旧SSH**:只支持 `aes256-cbc` 等旧cipher **目标**:在此设备上运行网心云(wxedge)赚取PCDN收益。 --- ## 二、尝试路径与失败记录 ### 2.1 直接运行wxedged二进制(失败) - 能启动、HTTP端口能监听,但依赖containerd,最终退出 ### 2.2 bind mount解决storage(部分成功) - storage-service成功了,但container-service仍然失败 ### 2.3 上传containerd直接运行(失败) - containerd是动态链接的,缺库无法运行 ### 2.4 Python假socket模拟containerd(失败) - gRPC协议握手失败 ### 2.5 chroot整个Docker镜像rootfs(成功!) --- ## 三、最终成功方案:chroot部署 ### 3.1 前置准备(在Mac/PC上) ```bash docker pull --platform linux/arm/v7 onething1/wxedge:latest docker create --platform linux/arm/v7 --name wxedge_tmp onething1/wxedge:latest docker export wxedge_tmp -o wxedge_fs.tar docker rm wxedge_tmp ``` ### 3.2 上传到NAS ```bash sshpass -p 'zhiqun1984' scp -O -c aes256-cbc wxedge_fs.tar admin@192.168.110.29:/volume1/wxedge/ ``` ### 3.3 创建chroot启动脚本(关键要点) ```bash #!/bin/sh ROOTFS=/volume1/wxedge/rootfs STORAGE=/volume1/wxedge/storage mount -t proc proc $ROOTFS/proc mount --bind /dev $ROOTFS/dev mount --bind $STORAGE $ROOTFS/storage mount -t tmpfs tmpfs $ROOTFS/tmp mount -t tmpfs tmpfs $ROOTFS/run # ⚠️ 关键:不能挂sysfs!只需cgroup的tmpfs mkdir -p $ROOTFS/sys/fs/cgroup mount -t tmpfs fakecgroup $ROOTFS/sys/fs/cgroup mkdir -p $ROOTFS/sys/fs/cgroup/{memory,cpu,cpuset,devices,blkio,pids,systemd} cp /etc/resolv.conf $ROOTFS/etc/resolv.conf chroot $ROOTFS /bin/sh -c ' cd /xyapp/miner.plugin-wxedge.ipk rm -rf /run/containerd ./bin/containerd -c ./cfg/cntr.toml & sleep 3 GODEBUG=x509ignoreCN=0 ./bin/wxedged -c ./cfg/wxedge.yaml & wait' ``` --- ## 四、核心踩坑总结 ### 4.1 SSH/SCP兼容性 | 问题 | 解决 | |:---|:---| | `no matching cipher found` | `ssh -c aes256-cbc` | | `scp: remote mkdir` | `scp -O`(旧SCP协议) | | Permission denied | 密码是 `zhiqun1984`(小写z) | ### 4.2 cgroup问题(最关键的坑) | 现象 | 解决 | |:---|:---| | `panic cannot statfs cgroup root` | 在chroot内挂tmpfs | | 挂了tmpfs但找不到 | **不挂sysfs**,只挂cgroup tmpfs | | `Failed to parse cgroup information` | 二进制补丁重定向到/tmp/fake_cgroups_ | ### 4.3 containerd问题 | 现象 | 解决 | |:---|:---| | 动态链接缺库 | 使用chroot,rootfs内有完整库 | | `overlayfs NOT supported` | cntr.toml禁用,用native snapshotter | | `strconv.Atoi "PID\n"` | printf "%s" 替代echo | ### 4.4 containerd-shim问题 | 现象 | 解决 | |:---|:---| | prctl失败 | 补丁NOP掉prctl调用 | | `readlink /tmp/_shimexe_` | 每次启动前创建符号链接 | ### 4.5 musl C++库缓存(guluplugin必须!) - ❌ Alpine 3.19(musl 1.2+,time64不兼容) - ❌ Alpine 3.14(musl 1.2.2,不兼容) - ✅ **Alpine 3.12**(musl 1.1.24,完美兼容) --- ## 五、验证检查清单 - [ ] `ps aux | grep wxedge` → containerd + wxedged 两个进程都在 - [ ] `curl http://IP:18888/docker/data` → 返回JSON含SN和acode - [ ] `curl http://IP:18888/docker/dashboard` → 返回运行任务 - [ ] wxedge.log中 `"Handshake Success"` → 已连接云端 - [ ] guluplugin日志 `Tracker S2T Heartbeat` → CDN已注册 --- ## 六、设备运行数据(最终状态 2026-02-14) | 项目 | 值 | |:---|:---| | SN | CTWX09Y9Q2ILI4PV | | IP | 192.168.110.29 | | 外网管理 | http://42.194.245.239:18882 | | 稳定运行任务 | CB*.0 + CG*.0 + CG*.1 | | 伪装硬件 | 22核CPU / SSD / 2033GB | | guluplugin | ✅ 运行,Tracker心跳30s | | 实际内存占用 | ~80MB | | 资源控制 | nice=10 + CPU守护(>70%暂停) | ### 不能运行的任务(硬件限制) | 任务 | 失败原因 | 处理 | |:---|:---|:---| | CB*(PCDN) | Illegal instruction | keepalive | | CX*(DCDN) | Illegal instruction | keepalive | | CYK | 需netns | fake_netns缓解 | | Z(Centaurs) | 要求AMD64 | 无法运行 | --- ## 七、适用范围 本方案适用于: 1. **ARM32(armv7l)或ARM64架构** Linux系统 2. **无Docker**(内核太老、无cgroup、资源不足等) 3. **有root权限** 4. **有足够存储**(rootfs 300MB + 数据 ≥10GB) 5. **有网络** **同类设备**:DS213j, DS213, DS112, 树莓派2/3, 任何Linux 3.x + ARM32 --- > **来源**:卡若AI/_经验库/待沉淀/2026-02-14_老旧NAS网心云chroot部署完整经验.md > **复制日期**:2026-02-15