写在前面
这次升级的设备是红米 AX6000,运行的是 ImmortalWrt,原始版本为 24.10.6,目标版本为 25.12.0。
这次更值得记录的是升级的协作方式。我没有凭经验直接刷机,而是让 Codex 全程参与。它先盘点设备事实、目标版本、包体系变化、备份范围、升级步骤和恢复验证,再由我审核方案;确认没有问题后,Codex 继续执行能执行的步骤,我根据输出结果决定下一轮指令。
结果很好。升级完成后,LAN、Wi-Fi、LuCI、OpenClash、WireGuard、DDNS 都恢复正常。过程中真正需要我手工接管的窗口很短:升级后先恢复 OpenClash 代理网络,随后 Codex 重新接手 WireGuard、DDNS、服务验证和文档整理。
这篇文章就是这次升级的复盘。

为什么我要把路由器升级交给 Agent?
路由器升级和普通软件升级不一样。失败以后,很难靠“重跑一次命令”解决:你可能会失去 SSH、失去 DNS、失去外网,甚至因为正在升级的路由器本身就是控制链路的一部分,导致远程操作中断。
我希望 Codex 处理的核心工作,是把升级拆成几个必须回答清楚的问题:
- 当前设备到底是什么 profile?
- 当前版本、内核、包管理器、源、已安装软件包是什么状态?
- 目标固件是否真的支持这个设备?
- 25.12.0 的包体系是否还能安装我依赖的软件?
- 哪些配置应该进入 sysupgrade 备份,哪些 runtime 数据应该单独备份?
- 升级前要怎样临时脱离 OpenClash DNS?
- 升级后恢复包、服务、DNS、WireGuard、DDNS 的顺序是什么?
- 每一步失败时应该停在哪里,怎样避免继续扩大风险?
这类问题很适合 Agent:它可以不厌其烦地把当前系统事实、官方 release 目录、目标镜像、软件包列表、备份内容和验证命令串起来,最后形成一个可执行的 checklist。
理想流程是:Codex 给方案,我审核;审核通过后,Codex 执行命令、读取输出、继续给出下一步建议;我主要负责判断方案是否合理、验证结果是否符合预期,以及在关键节点给出继续或停止的指令。
这次没有做到完全由 Codex 执行,原因在我的网络环境。Codex 访问外网依赖 OpenClash 代理,而 OpenClash 又运行在被升级的路由器上。升级后代理恢复之前,我需要手工完成最小闭环:更新 apk 索引、安装 OpenClash、恢复代理网络。之后再把后续排查、验证和文档整理交回给 Agent。
当前环境与目标版本
升级前设备状态:
设备: Xiaomi Redmi Router AX6000
board: xiaomi,redmi-router-ax6000-ubootmod
target: mediatek/filogic
arch: aarch64_cortex-a53
当前版本: ImmortalWrt 24.10.6
当前内核: 6.6.133
包管理器: opkg
root shell: /bin/bash
目标版本:
目标版本: ImmortalWrt 25.12.0
目标内核: 6.12.87
包管理器: apk
目标镜像: xiaomi_redmi-router-ax6000-ubootmod-squashfs-sysupgrade.itb
这里最关键的点是 ubootmod。红米 AX6000 有不同布局,镜像不能只看“AX6000”这个商品名,必须匹配到 xiaomi,redmi-router-ax6000-ubootmod 对应的 sysupgrade 镜像。
另一个关键点是 25.12.0 不是普通小版本升级。它跨过了包体系边界:从 opkg 迁移到 apk。这意味着升级后的恢复逻辑不能再沿用 /etc/opkg/distfeeds.conf、customfeeds.conf 和 .ipk 软件包的习惯。

25.12.0 相比 24.10.6 值得升级在哪里?
对我来说,25.12.0 的吸引力主要来自三个方面:新内核、新包体系,以及个人维护习惯。
第一是内核版本。我的 24.10.6 运行在 kernel 6.6.133,25.12.0 对应 kernel 6.12.87。路由器这种设备不需要追新内核,但内核分支更新通常意味着驱动、网络栈、安全修复和 kmod 生态都会进入新的维护线。只要目标设备 profile 和关键包兼容,这本身就是一个合理的升级理由。
第二是包管理器变化。OpenWrt 25.12 系列将默认包管理器从 opkg 切换到 apk。opkg 是 OpenWrt 多年来的传统方案,但长期维护和依赖处理能力已经显得吃力;apk 来自 Alpine 生态,仍在活跃维护,索引、依赖解析和命令体验都更现代。
从日常维护角度看,最直接的变化是:
- 软件源从
distfeeds.conf迁移到/etc/apk/repositories - 安装、查询、升级、删除命令全部换成 apk 语法
- 排查软件包问题时,要围绕 apk 仓库索引和
apk命令来查,而不是继续看 opkg 状态
第三是我的个人偏好:基础设施可以稳定,但不能长期落后太多。过去我会因为步骤繁琐、失败成本高而推迟升级;这次有 Agent 加持,盘点、比对、备份清单、恢复顺序和验证命令都可以交给 Codex 处理,升级负担明显降低。
24.10.6 作为 24.10 系列的 service release,仍然适合作为稳定维护版本;25.12.0 则是新稳定分支的起点。对路由器这种基础设施来说,新分支不等于自动更好。这次我的判断是:设备 profile 明确支持、关键包能从官方源恢复、DNS 和 OpenClash 风险可控,升级收益大于维护成本。
升级前必须做的检查
这部分是整个方案里最重要的部分。固件升级的风险通常在执行 sysupgrade 之前就已经埋下了:设备 profile、备份范围、DNS 链路、包源和恢复顺序,只要有一项判断错,后面都会变得被动。
1. 确认设备 profile
至少要确认:
ubus call system board
cat /etc/openwrt_release
重点看 board_name、target、arch 和当前版本。镜像必须匹配 ubootmod,不能拿普通布局镜像碰运气。
2. 确认备份空间和运行状态
df -h / /overlay /tmp
ip route
wifi status
/tmp 要能放下固件,/overlay 要有足够空间处理备份和临时配置。路由器升级时不要通过 WireGuard 远程执行,因为升级会中断网络栈,最好在本地网络内操作。
3. 备份关键配置
我把备份分为两类。
第一类是 sysupgrade 应该保留的配置,例如:
/etc/config/network
/etc/config/wireless
/etc/config/firewall
/etc/config/dhcp
/etc/config/ddns
/etc/config/openclash
/etc/config/system
/etc/config/luci
/etc/dropbear/authorized_keys
/etc/passwd
/etc/group
/etc/shadow
/etc/crontabs/root
第二类是只做离线备份、不放进 sysupgrade 的 runtime 数据,例如 OpenClash 的 core、规则库、Geo 数据和历史缓存。这些东西体积大、状态复杂,不应该全部塞进系统升级保留列表。
4. 收窄 sysupgrade 保留范围
这是 Agent 方案里我认为最有价值的一步:不要把旧系统里所有看起来“有用”的目录都保留下来。
尤其要避免:
/etc/opkg
/usr/share/openclash
/etc/openclash 全目录
/data
/www
25.12.0 已经切到 apk,保留 /etc/opkg 只会把旧包体系的历史状态带进新系统。OpenClash runtime 也应该单独备份、升级后再恢复。
5. 临时脱离 OpenClash DNS
我原来的 DNS 链路依赖 OpenClash:
dnsmasq -> 127.0.0.1#7874 -> OpenClash
升级后 OpenClash 尚未恢复时,如果 DNS 仍指向 127.0.0.1#7874,就会出现“Wi-Fi 连接正常、WAN 也正常、但不能解析域名”的假死状态。
所以升级前先把 DNS 临时改回普通上游,确认:
nslookup openwrt.org 127.0.0.1
能正常解析以后再继续。
6. 临时把 root shell 切回 ash
我的 root shell 原来是 /bin/bash。升级后如果 bash 尚未安装,而 /etc/passwd 仍指向 /bin/bash,SSH 登录可能会出问题。
所以升级前先临时切回 /bin/ash,升级后确认 bash 安装成功,再切回去。
7. 固件校验和兼容性测试
固件下载后先做 sha256 校验,再复制到路由器,用:
sysupgrade -T <firmware.itb>
只有没有 device mismatch、format error、compat error 时才正式升级。
需要规避的坑
不要混用 opkg、ipk 和 apk
这是 25.12.0 升级最大的边界。
升级后不要把 24.10 的第三方 .ipk 源写入 /etc/apk/repositories,也不要试图用 opkg 恢复旧包。一个第三方源要能在 25.12 上使用,至少要满足:
1. 包文件是 .apk
2. 仓库有 packages.adb
3. arch 是 aarch64_cortex-a53
4. 版本线是 25.12
5. 不混入 24.10/opkg/ipk 包
不要把 OpenClash 当成普通配置目录备份
/etc/config/openclash 可以保留,但 /etc/openclash 里有很多 runtime 数据。我的做法是:配置走 sysupgrade,runtime 单独打包,升级后在 OpenClash 停止状态下恢复,再启动服务。
不要过早恢复 OpenClash DNS
只有 OpenClash 已经启动,并且监听 7874 后,才把 dnsmasq 的上游切回 127.0.0.1#7874。
不要远程跨 WireGuard 升级
WireGuard 会跟着 network 和内核模块一起重启。正式升级时不要依赖它作为控制通道。
不要批量恢复历史软件包
opkg list-installed 可以作为参考,但不能升级后无脑批量安装。正确做法是只恢复已确认存在于 25.12 官方 apk 源的关键包,再逐项验证服务。
root shell 的 bash/ash 切换要闭环
如果 root shell 指向 /bin/bash,升级前最好先临时切回 /bin/ash。新系统起来后,bash 可能还没安装;这时 /etc/passwd 继续指向 /bin/bash,SSH 登录就可能把自己锁在门外。
恢复阶段也要反过来检查:确认 bash 已安装、/bin/bash 存在,再把 root shell 切回去。
Agent 依赖 OpenClash 时要预留人工接管窗口
这次的限制很具体:OpenClash 没恢复前,Codex 可能无法稳定访问外网。方案里要提前标出这个人工接管窗口:升级后先由人手工 apk update、安装 OpenClash、恢复代理;OpenClash 正常后,再把操作权交回给 Agent。
我这次的两个特别操作
1. 从 USTC 源改回官方源
我之前因为网络速度问题,把源换成了 USTC 镜像。升级前的直觉是:继续用镜像会更快。
但实际恢复时发现,USTC 镜像缺少某些关键包,尤其是某科学上网应用相关包。反而官方 downloads.immortalwrt.org 源里的包更完整,并且在我的网络环境下不需要科学上网就能访问。
所以最终方案是:25.12.0 恢复阶段只使用官方源,不使用 USTC,不启用第三方源。先保证系统和关键服务恢复,再考虑镜像加速。
我的 /etc/apk/repositories 使用官方 25.12 源,包括 target packages、kmods 和 aarch64_cortex-a53 下的 base、luci、packages、routing、telephony。
2. 唯一的人工接管窗口:恢复 OpenClash
升级后我的手工操作集中在恢复代理网络:
apk update
apk add luci-app-openclash luci-compat
OpenClash 恢复并且代理可用后,我把后续工作交回给 Codex。WireGuard 的包安装、network restart、接口验证和日志检查都是 Codex 接手后处理的内容。
升级后的恢复顺序
最终恢复顺序分成两段:
- 人工恢复代理:基础验证,确认
apk和/etc/apk/repositories,使用官方源apk update,安装 OpenClash 并恢复代理网络。 - Codex 接手收尾:安装 bash、WireGuard、DDNS、Argon、bridger 等关键包;把 root shell 切回
/bin/bash;恢复 OpenClash runtime 和 DNS;重启 network;验证 WireGuard、DDNS、LuCI、客户端访问和日志。
这个顺序的好处是每一步都有明确的前置条件。DNS 不会早于 OpenClash 恢复,bash 不会早于软件包安装;WireGuard 也不只验证包列表,还要验证 network handler 和实际接口。
apk 常用法速记
25.12 之后,日常维护需要把 opkg 习惯切换到 apk。
更新索引:
apk update
安装软件包:
apk add bash luci-app-openclash wireguard-tools
搜索软件包:
apk search openclash
apk search wireguard
查看已安装包:
apk list --installed
apk list --installed | grep wireguard
查看包信息:
apk info bash
apk info -a bash
删除软件包:
apk del <package>
查看和编辑源:
cat /etc/apk/repositories
vi /etc/apk/repositories
apk update
和 opkg 相比,最需要重新建立肌肉记忆的是:不要再去改 /etc/opkg/distfeeds.conf,不要把 .ipk 当成可安装包,也不要混用旧源。
这次使用 Agent 的体会
这次升级让我更确认一件事:Agent 能显著降低基础设施维护的操作负担。除了写方案,它还可以执行大量繁琐、重复、容易漏项的步骤,把升级任务拆成可验证的阶段。
它真正帮上忙的地方包括:
- 从设备事实出发,不把“AX6000”当成唯一判断依据
- 把 25.12.0 的
apk迁移识别为主要风险边界 - 把备份拆成 sysupgrade 配置和 runtime 数据两类
- 提前处理 OpenClash DNS 和 bash shell 这种容易把自己锁在门外的问题
- 明确哪些第三方源不能迁移,哪些包可以从官方源恢复
- 给每个阶段安排验证命令
- 执行繁琐命令、读取结果,再根据结果提出下一轮操作建议
人的角色也变得更清晰:我不需要把精力消耗在复制命令、整理包列表、反复查路径这类机械操作上,可以把注意力放在审查方案、观察关键输出、判断恢复结果和给 Agent 下达下一轮指令。任务推进速度比纯手工方式快很多,思路也更稳定。
我的结论是:路由器升级可以让 Agent 深度参与,但不适合做成无人值守脚本。最稳的方式是让 Agent 负责计划、执行、校验和信息整理,人负责审查、授权、接管网络中断阶段,并在关键节点做判断。
总结
红米 AX6000 从 ImmortalWrt 24.10.6 升级到 25.12.0 是可行的,但这次升级要按 opkg -> apk 迁移来准备,不能按普通小版本升级处理。
这次升级最重要的经验有四条:
- 先确认
ubootmodprofile、固件 sha256 和sysupgrade -T - 升级前收窄备份范围,不把旧
opkg和大块 runtime 状态带进新系统 - 升级后优先使用官方 apk 源,先恢复关键服务,再考虑第三方源
- OpenClash 恢复前需要人工接管;恢复后再交给 Codex 处理 WireGuard、DDNS 和后续验证
如果你也要升级类似设备,我建议先让 Agent 做一份基于你当前机器事实的方案,再逐项执行。不要直接套别人的命令,尤其不要忽略 board profile、包源、DNS 和第三方插件这几个边界。