前言
MikroTik RouterOS 是一套非常强大的路由操作系统,但在日常使用中,总会遇到一些 RouterOS 原生功能不方便处理的需求:使用标准 Linux 命令排查网络、通过 SSH 执行自动化脚本、使用 curl/tcpdump/dig 诊断网络,或者运行轻量级 Python 和 Shell 工具。
RouterOS 7 提供了 Container 功能,可以在支持的硬件上运行 Linux 容器。我决定在两台 MikroTik RB5009 上分别部署 Debian 12,让路由器兼具 RouterOS 网络能力与 Linux 运维能力。
本文记录部署过程、关键配置、遇到的问题及解决方式。
一、部署环境
| 项目 | 设备 A | 设备 B |
|---|---|---|
| 型号 | RB5009UG+S+ | RB5009UPr |
| 操作系统 | RouterOS 7 | RouterOS 7 |
| CPU 架构 | ARM64 | ARM64 |
| Linux 系统 | Debian 12 Slim | Debian 12 Slim |
| 容器名称 | debian |
debian |
| 容器 IP(示例) | 10.10.10.254 |
172.16.16.254 |
| SSH 用户 | ops |
ops |
| 存储方式 | USB ext4 | USB ext4 |
| 远程接入 | EasyTier | EasyTier |
本文以设备 B 为示例,设备 A 只需替换 IP、网关及存储路径。
1 | 远程 Mac / PC |
Debian 容器有独立 IP,接入 RouterOS LAN Bridge,同网段设备可直接访问 SSH,无需额外端口映射。
二、开启 RouterOS Container 功能
检查设备模式:
1 | /system/device-mode/print |
确认 container: yes,并检查:
1 | /container/print |
如果 Container 未启用,需按当前 RouterOS 版本要求启用,并完成设备所要求的物理确认。远程操作前应确保可以现场维护设备。
三、准备 USB 持久化存储
RB5009 内部存储有限,建议将 Linux 根文件系统和镜像层放在 USB ext4 存储上。先检查:
1 | /disk/print |
本次设备 B 的 USB 挂载路径为 usb2。如果需要格式化,请先核实磁盘没有其他业务数据;格式化会清除数据。创建目录:
1 | /file add type=directory name="usb2/containers" |
踩坑 1:RouterOS 不是 Linux Shell
尝试 /file/make-directory 会失败。本次 RouterOS 版本使用 /file add type=directory name="路径" 创建目录。已存在的目录无需重复创建。
四、创建 Debian 独立网络
设备 B 的示例网络:
1 | RouterOS LAN IP: 172.16.16.172 |
创建 VETH 并接入桥:
1 | /interface/veth/add name=veth-debian address=172.16.16.254/12 gateway=172.16.16.172 |
检查:
1 | /interface/veth/print detail |
容器地址应避开 DHCP 分配池及现有静态设备,先核对 ARP、租约和地址规划。/12 是本次实际网络掩码,不应直接套用到 /24 等其他网络。
五、拉取 Debian 12 ARM64 镜像
配置镜像层和临时目录:
1 | /container/config/set layer-dir=usb2/containers/layers tmpdir=usb2/containers/tmp |
创建容器(可逐行在 RouterOS CLI 中输入,续行写法需符合当前终端):
1 | /container/add remote-image=m.daocloud.io/docker.io/library/debian:12-slim name=debian interface=veth-debian root-dir=usb2/containers/debian-rootfs layer-dir=usb2/containers/layers entrypoint=/bin/sleep cmd=infinity logging=yes start-on-boot=no |
这里使用 debian:12-slim,体积较小,后续按需安装软件。
踩坑 2:Docker Hub 拉取超时
本次直接从 Docker Hub 拉取镜像曾超时,改用 m.daocloud.io/docker.io/library/debian:12-slim 成功。镜像加速服务的可用性可能变化,失效时应更换可用来源。
初次运行采用 entrypoint=/bin/sleep cmd=infinity,是为了让容器持续运行,方便进入容器安装 SSH,而不是让尚未配置的 SSH 服务导致容器立即退出。
1 | /container/start [find where name="debian"] |
在 Debian 内检查:
1 | cat /etc/os-release |
预期系统为 Debian 12,架构为 aarch64。
六、为 Debian 配置文件共享目录
本文配套的完整部署包:rb5009-debian-kit-v1.1.1.zip。解压后包含两台设备对应的 RouterOS 准备脚本、Debian 初始化脚本 02-debian-bootstrap.sh、RouterOS 收尾脚本和详细 README。
SSH 尚未安装时,不能直接用 SCP 上传初始化脚本。可以使用 RouterOS Container 挂载共享目录:
1 | /container/mounts/add list=debian-shared src=usb2/containers/shared dst=/mnt/shared |
进入 Debian 验证:
1 | /container/shell [find where name="debian"] |
1 | ls -lah /mnt/shared |
通过 WinBox Files 将部署包中的 02-debian-bootstrap.sh 上传至 usb2/containers/shared/,在 Debian 中即可通过 /mnt/shared/ 访问。先检查脚本内容,再执行:
1 | bash /mnt/shared/02-debian-bootstrap.sh |
踩坑 3:Mounts 使用 list=,不是 name=
本次 RouterOS 版本的 /container/mounts/add 不接受 name=,需要使用 list=。可在 CLI 输入 /container/mounts/add 后查看支持的参数;关联容器时使用 mountlists=。
七、安装 SSH 和运维工具
在 Debian root Shell 中:
1 | apt-get update |
本次安装了约 65 个软件包及依赖。安装时可能看到:
1 | invoke-rc.d: could not determine current runlevel |
这并不意味着安装失败。容器中没有运行完整的 systemd 服务管理环境,后面直接运行 sshd 即可。
八、创建 SSH 运维用户并配置 sudo
不建议使用 root 直接远程登录。创建 ops 用户(若已存在则跳过 useradd):
1 | id ops >/dev/null 2>&1 || useradd -m -s /bin/bash ops |
建立独立 sudo 授权文件:
1 | printf 'ops ALL=(ALL:ALL) ALL\n' > /etc/sudoers.d/90-ops |
sudo whoami 出现 [sudo] password for ops: 是正常现象,输入 ops 密码后应输出 root。建议保留密码验证,不必默认配置 NOPASSWD。
九、配置 SSH 公钥认证
Mac 上查看已有公钥:
1 | cat ~/.ssh/id_rsa.pub |
如果没有密钥,可生成 Ed25519 密钥:
1 | ssh-keygen -t ed25519 |
在 Debian 中写入公钥(不要上传私钥):
1 | mkdir -p /home/ops/.ssh |
踩坑 4:公钥正确仍然报 Permission denied (publickey)
第一台 RB5009 曾因 .ssh 目录和 authorized_keys 权限不正确导致公钥认证失败。目录应为 700,授权文件应为 600,所有者应为 ops,且用户主目录不能被其他用户随意写入。
十、配置并测试 SSH 服务
在 Debian 中创建配置文件:
1 | cat > /etc/ssh/sshd_config.d/99-ops.conf <<'EOF_SSH' |
初始化阶段暂时保留密码认证,公钥登录验证成功后建议将 PasswordAuthentication 改为 no,并重新加载 SSH 服务。关闭前务必在第二个终端确认公钥可用,避免锁死远程访问。
检查配置并启动:
1 | mkdir -p /run/sshd |
Mac 上连接:
1 | ssh ops@172.16.16.254 |
登录后验证:
1 | sudo whoami |
输出 root 即表示 sudo 授权正常。
十一、让 SSH 随容器自动启动
RouterOS Container 不应依赖完整的 systemd,使用前台 sshd 作为容器主进程即可。
在 Debian 中创建启动脚本:
1 | cat > /usr/local/bin/start-sshd.sh <<'EOF_SSHD' |
踩坑 5:sshd 启动后立即退出
第一台设备曾因 /run/sshd 所有权异常导致 SSH 服务启动失败。启动脚本显式设置目录所有者及权限,再通过 exec /usr/sbin/sshd -D -e 将 sshd 作为容器前台主进程,避免后台守护进程退出导致容器停止。
十二、配置 RouterOS 开机自启
确认 SSH 已能正常登录后,回到 RouterOS:
1 | /container/stop [find where name="debian"] |
确认容器状态为 RUNNING,从 Mac 再次连接:
1 | ssh ops@172.16.16.254 |
两台 RB5009 都已通过容器重启后的 SSH 登录验证。
十三、通过 EasyTier 实现异地访问
不建议将 SSH 22 端口直接映射到公网。本次设备已部署 EasyTier,可以进一步通过对应节点发布 Debian 的单主机子网路由:
1 | 设备 A:10.10.10.254/32 |
需要验证 EasyTier 节点在线、远端路由下发、RouterOS 转发/防火墙放行,以及 Debian 回程路径。配置子网代理不等于远程访问已经成功,应在非局域网环境中实际测试:
1 | ssh ops@172.16.16.254 |
十四、日常维护
SSH 登录:
1 | ssh ops@172.16.16.254 |
上传文件或目录:
1 | scp ./test.sh ops@172.16.16.254:/home/ops/ |
更新软件:
1 | sudo apt-get update |
网络诊断:
1 | ip addr |
RouterOS 检查容器状态:
1 | /container/print detail where name="debian" |
备份 RouterOS 配置:
1 | /export file=rb5009-container-config |
导出文件可能包含网络拓扑、账号或其他敏感信息,请妥善保存,不要直接发布到公开仓库。
十五、部署经验总结
| 问题 | 原因 | 解决方式 |
|---|---|---|
| Docker Hub 拉取超时 | 镜像源网络访问受限 | 使用可访问的镜像加速源 |
| 创建目录失败 | RouterOS CLI 语法与 Linux 不同 | /file add type=directory |
| Mount 参数错误 | 使用了不支持的 name= |
改用 list= |
| SSH 安装后未启动 | 容器没有传统服务管理环境 | 直接启动 sshd |
| 公钥认证失败 | .ssh 权限错误 |
修正所有者及权限 |
| SSH 启动失败 | /run/sshd 权限异常 |
启动前修正目录权限 |
| 重启后 SSH 不运行 | sshd 不是容器主进程 | 使用自定义 entrypoint |
| sudo 要求密码 | sudo 的正常安全机制 | 输入 ops 用户密码 |
RouterOS Container 最重要的原则:不要把它当作完整的 Linux 虚拟机,而要把它当作运行在 RouterOS 上的轻量 Linux 服务环境。
不依赖完整 systemd,让主要服务以前台运行;将根文件系统放在外部存储,使用独立 VETH 网络和 SSH 运维入口,避免直接暴露公网管理端口。
十六、结语
两台 MikroTik RB5009 现在都拥有独立的 Debian 12 ARM64 运维环境。RouterOS 继续负责路由、交换、防火墙和网络连接,Debian 承担 Shell 脚本、网络诊断及轻量自动化任务。
这套方案的价值不只是“在路由器上多运行一个 Linux”,而是让网络设备拥有一个标准化、可脚本化、可远程维护的运维入口。
未来还可以扩展 Python 网络检测、链路质量采集、自动化故障诊断,以及通过 EasyTier 统一管理多台路由器。RB5009 毕竟是路由器,CPU、内存和 USB 存储性能有边界,生产环境应优先保证 RouterOS 核心转发能力。
让路由器专注于网络,让 Debian 专注于工具。

