⏱️ 预计折腾:45 分钟 | 🔥 踩坑指数:⭐⭐⭐ | 🛠️ 前置环境:macOS 终端 / 中兴问天 BE7200 Pro+ / NanoPi R4S

家里软路由一旦承担拨号和流量转发,每次折腾重启都会导致全屋断网挨骂。这篇笔记直接分享我目前稳定运行的家庭网络架构:主路由专心负责拨号与无线组网,NanoPi R4S 刷入 Armbian 挂在旁边只跑 Pi-hole与 Docker 服务,适合追求极致稳定又想玩容器的折腾党直接抄作业。

📌 核心结论

  • 职责彻底解耦:主路由负责宽带拨号与 DHCP,NanoPi R4S 仅作纯 DNS 与容器宿主,重启维护完全不影响家里正常上网。
  • 纯文本栈管理:底层刷入纯净 Armbian,所有容器统一交由 Dockge 以标准 compose.yaml 文件管理,拒绝黑盒数据库。
  • 内网穿透直连:借助 Tailscale 子网路由公告内网网段,出门在外手机无需记复杂端口,直接敲内网 IP 就能访问家里所有后台。
  • 警惕解析绕过:开启 IPv6 后客户端可能优先走运营商下发的 IPv6 DNS,发现去广告失效时优先排查路由器的 IPv6 DNS 设置。

家庭网络拓扑

这一节先交代清楚家里各台设备的接线位置与角色边界,理顺了拓扑后面配参数才不会乱。

核心设备分工

我家宽带是电信 1000M,光猫已经改成桥接模式,拨号和全屋 DHCP 全部交给主路由中兴问天 BE7200 Pro+(管理地址 192.168.5.1)处理,同时开启了 IPv6。

旁挂的 NanoPi R4S 固定分配内网地址 192.168.5.10,底层跑 Armbian 加 Docker,定位非常纯粹:只负责内网 DNS 解析和托管容器服务,绝不参与任何流量转发或行为管理。

物理接线方案

主路由背后的三个 LAN 口按设备属性做了固定分配,废话不多说,直接看接线清单:

  • LAN1 接口:网线直连极空间 Q2C,专门承担家里的数据存储与照片影音备份。
  • LAN2 接口:连接一台中兴 ZXHN E1630,走有线 Mesh 组网补齐房间死角的无线信号。
  • LAN3 接口:直接插到 NanoPi R4S 的 WAN 口上,把 R4S 当作一台普通内网服务器接入主路由网段。
💡 舒服的地方:把 NanoPi R4S 的 WAN 口当普通网口接在主路由 LAN 口下,网关依然指向 192.168.5.1,就算把 R4S 拔掉电源,家里照样能正常刷视频看网页。

R4S刷机初始化

硬件接线搞定后,这一节我们从零开始给 NanoPi R4S 刷入官方 Armbian 系统并完成网络初始化。

烧录系统镜像

准备一张 16GB 以上的 TF 卡和读卡器插到 macOS 上,按下面三步把系统写进去:

  1. 打开浏览器前往 Armbian 官方 NanoPi R4S 下载页,下载最新的 Armbian 26.8.1 Minimal (CLI) 镜像压缩包,并用 Keka 解压出 .img 格式文件。
  2. 下载并打开 balenaEtcher 烧录工具,依次选中解压好的 .img 镜像与 TF 卡,点击 Flash! 等待写入与校验完成。
  3. 拔下读卡器取出 TF 卡,插入处于断电状态的 NanoPi R4S 卡槽,确认 WAN 口已接好主路由 LAN3 网线后插上 Type-C 电源开机。

首次登录配置

等 R4S 指示灯正常闪烁后,先去中兴主路由后台 http://192.168.5.1 的设备列表里把 R4S 的 IP 绑定固定为 192.168.5.10,接着打开 macOS 终端通过 SSH 连上去完成初始化。

在 macOS 终端执行下面的命令连接 R4S:

code

输入默认初始密码 1234 回车后,终端会强制要求你输入两次新 root 密码,随后选择默认 Shell 类型(输入对应 bash 的数字即可),并按提示创建一个日常用户(也可按 Ctrl+C 跳过仅保留 root)。

顺利进入 Armbian 命令行后,在 R4S SSH 终端执行下面的命令更新系统软件源索引与基础包:

code

看到所有软件包下载并解压完毕、终端重新回到 # 提示符,说明系统底层已经更新到最新状态。

固定静态地址

虽然主路由 DHCP 已经绑定了 192.168.5.10,但为了防止后续部署 Pi-hole 时宿主机自带的 systemd-resolved 抢占 53 端口,我们需要在 R4S 上提前释放该端口。

在 R4S SSH 终端执行下面的命令关闭 systemd-resolved 的本地 53 端口监听存根:

code

这行命令不会输出任何提示,直接把配置文件里的监听开关改成了关闭状态。

接着在 R4S SSH 终端执行下面的命令重建 /etc/resolv.conf 软链接:

code

执行后同样没有多余报错输出,下一步重启解析服务让改动立即生效。

在 R4S SSH 终端执行下面的命令重启 systemd-resolved 服务:

code

跑完之后 53 端口就彻底腾出来了,接下来安装容器环境不会再报端口冲突。

⚠️ 千万注意:在中兴主路由后台把 NanoPi R4S 静态绑定为 192.168.5.10 后,如果 R4S 当时拿到的还是别的临时 IP,记得重启一次 R4S 让它正式获取 192.168.5.10 地址。

部署Dockge面板

我不喜欢用臃肿的容器管理面板,这一节我们在 Armbian 上装好 Docker 并部署轻量的 Dockge,把所有服务统一收口管理。

安装Docker环境

在 R4S SSH 终端执行官方一键安装脚本部署 Docker 与 Docker Compose 插件:

code

脚本会自动识别 Armbian 的 ARM64 架构并完成安装,等待一两分钟直到屏幕底部打印出 Docker 版本信息即可。

在 R4S SSH 终端执行下面的命令开启 Docker 开机自启:

code

终端返回创建 symlink 提示或直接无报错返回,代表守护进程已经常驻后台。

启动Dockge服务

按照 Dockge 官方 GitHub 仓库 的规范,我们先在 R4S 上建好存放容器栈与面板自身的目录。

在 R4S SSH 终端执行下面的命令创建 /opt/stacks 和 /opt/dockge 两个文件夹:

code

建好目录后没有任何输出,直接切换到面板目录准备拉取配置。

在 R4S SSH 终端执行下面的命令进入 /opt/dockge 目录:

code

确认终端当前路径变成 /opt/dockge 后,继续下载官方编排文件。

在 R4S SSH 终端执行下面的命令直接从官方生成器下载监听 5001 端口的 compose.yaml 文件:

code

跑完会显示 100% 下载进度条,当前目录下就已经生成好标准的配置文件了。

在 R4S SSH 终端执行下面的命令后台拉起 Dockge 容器:

code

看到终端输出 Container dockge-dockge-1 Started 后,打开浏览器访问 http://192.168.5.10:5001,首次打开设置一下管理员账号密码就能进入主界面。

💡 舒服的地方:Dockge 不会把你的配置锁死在私有数据库里,你在网页上新建的每一个项目,本质上都是老老实实躺在 /opt/stacks 目录下的明文 compose.yaml 文件,随时能用命令行接管。

部署核心容器

有了 Dockge 之后基本就可以告别终端了,这一节我们直接在网页端把 Pi-hole、Tailscale 和 Beszel 三个核心服务跑起来。

部署Pi-hole服务

打开 Dockge 后台 http://192.168.5.10:5001,点击左上角 + Compose,堆栈名称填写 pihole,在右侧编辑器里贴入下面的配置:

yaml

把 your_admin_password 改成你自己的后台密码后点击上方 部署 按钮,等状态变成绿色运行中,浏览器打开 http://192.168.5.10/admin 即可登录 Pi-hole 控制台;注意这里我们只用它做纯 DNS 解析,千万不要去开启它自带的 DHCP 功能。

部署Tailscale

为了出门在外也能直接用 http://192.168.5.10/admin 这种内网地址访问家里设备,我们在 R4S 上跑一个 Tailscale 容器并开启 subnet router 公告 192.168.5.0/24 网段。

先在 R4S SSH 终端执行下面的命令开启宿主机内核 IPv4 转发,确保子网路由流量能顺利通往内网其他机器:

code

终端输出 net.ipv4.ip_forward = 1 即代表内核转发已生效,接着去 Tailscale 管理控制台 Keys 页面 生成一个 Reusable 的 Auth key。

回到 Dockge 点击 + Compose,堆栈名称填 tailscale,在右侧粘贴下面的 compose.yaml 配置:

yaml


点击 部署 启动容器后,去 Tailscale 设备管理列表 找到 nanopi-r4s 节点,点开右侧菜单选择 Edit route settings 勾选批准 192.168.5.0/24;随后在 iPhone 上安装客户端登录同一账号,哪怕在外面用蜂窝流量也能直接敲 http://192.168.5.10/admin 进后台。

部署Beszel监控

最后我们部署一套极简的 Beszel 监控探针,随时看一眼 NanoPi R4S 的温度、内存和各个容器的资源占用。

先在 Dockge 点击 + Compose 新建名为 beszel 的堆栈,贴入下面第一阶段只含面板端的配置来拿公钥:

yaml

先点 部署 拉起服务,浏览器打开 http://192.168.5.10:8090注册管理员账号,点击右上角 Add System 复制弹窗里的 Public Key 填入上方配置的 KEY 字段重新部署,接着在弹窗主机地址栏填入 /beszel_socket/beszel.sock 保存,就能看到 R4S 本机和所有容器的实时监控曲线了。

⚠️ 千万注意:Tailscale 容器里的 TS_STATE_DIR 环境变量和 ./ts-state:/var/lib/tailscale目录挂载必须同时保留,否则每次在 Dockge 里更新重启容器都会在控制台生成一台重复的新设备。

路由联调避坑

容器全部跑通之后,只差最后一步把家里设备的 DNS 请求引导过来,并定好省心的日常维护规矩。

下发内网DNS

现在我们要让中兴主路由通过 DHCP 把 Pi-hole 的地址自动分发给家里所有联网设备:

  1. 浏览器打开 http://192.168.5.1 登录中兴问天 BE7200 Pro+ 管理后台,进入局域网(LAN)的 DHCP 服务器设置页面。
  2. 将首选 DNS 服务器地址修改为 192.168.5.10,保存设置后把 iPhone 或 macOS 的 Wi-Fi 断开重连一次,再去 http://192.168.5.10/admin 就能看到源源不断的解析记录了。

排查IPv6绕过

主路由开启 IPv6 后有一个非常隐蔽的坑:部分终端系统会优先使用运营商下发的 IPv6 DNS 服务器,导致请求直接绕过 192.168.5.10 的 Pi-hole。

如果你平时用着突然发现去广告失效,或者 Pi-hole 后台拦截率莫名其妙暴跌,先别急着重装容器,第一时间进主路由 192.168.5.1 的 IPv6 LAN 设置里检查 IPv6 DNS 下发策略。

⚠️ 千万注意:千万不要在 R4S 上安装任何自动更新容器的工具,所有容器统一在 Dockge 面板 http://192.168.5.10:5001 手动点 Update 更新,避免半夜自动拉取新镜像把 DNS 搞崩。

日常维护备份

平时维护 Pi-hole 我定了一条铁律:遇到小版本更新,直接在 Dockge 界面点一下 Update 按钮拉取最新镜像重建即可,无需额外备份。

但如果是跨大版本升级,或者准备大改上游 DNS 和拦截规则前,务必先打开 http://192.168.5.10/admin,依次进入 Settings → Teleporter,点击导出按钮把当前配置打包下载到 macOS 本地留底,哪怕玩脱了也能一键恢复。