来源:
notes/topics/environment_backup_restore/deepin-immutable-and-reboot-verification.mdDeepin 25 不可变系统:修改层机制与重启连通性验证
日期:2026-09-18 · 状态:已通过一次真实重启验证
本文回答一个具体问题:备份机(虚拟机)重启后,ZeroTier 会不会自己起来? 结论:会,已实测。顺带把不可变系统的机制、一个长期失败的系统服务、 以及恢复包的位置记录下来。
1. 为什么这件事必须专门验证
备份机唯一的远程入口是 ZeroTier 分配的 10.71.48.31。一旦重启后 ZeroTier
没起来,就等于彻底失去这台机器的远程访问,只能靠飞牛 NAS 的虚拟机控制台救。
而这台机器是 Deepin 25 的不可变系统(ostree):/usr、/opt、/etc 都是
overlay 挂载,写入内容落在「修改层」里,表面看很像”重启就没了”。所以必须实测,
不能靠推测。
2. 存储布局:哪些是持久的
findmnt 实测(节选):
| 挂载点 | 来源 | 类型 | 说明 |
|---|---|---|---|
/ |
/dev/sda3 |
ext4 rw | 持久 |
/persistent |
/dev/sda5 |
ext4 rw | 持久(62 G 数据盘) |
/usr |
usr-overlay |
overlay ro | 在修改层 |
/opt |
opt-overlay |
overlay rw | 在修改层 |
/etc |
etc-overlay |
overlay rw | 在修改层 |
/var |
/dev/sda5[/ostree/deploy/deepin/var] |
ext4 rw | ✅ 不在修改层 |
/home |
/dev/sda5[/home] |
ext4 rw | ✅ 不在修改层 |
修改层实测只包含三个顶层目录:etc/、opt/、usr/ —— 不含 var/,
也不含 home/。这一点是整个连通性判断的基石。
修改层的物理位置在持久分区上:
/persistent/overlay/data/layer-<16位十六进制>/{etc,opt,usr}
3. 连通性链条
从加电到 SSH 可用的完整依赖链,逐项实测:
| 环节 | 实测状态 | 存放位置 | 重启后 |
|---|---|---|---|
网卡 ens8 自动连接 |
AUTOCONNECT=yes |
层内 /etc/NetworkManager |
✅ |
ssh.service 自启 |
enabled + multi-user.target.wants |
层内 /etc |
✅ |
zerotier-one.service 自启 |
enabled + multi-user.target.wants |
层内 /etc |
✅ |
| ZeroTier 节点身份 | identity.secret |
/var(层外) |
✅ |
已加入网络 166359304eb8bd7a |
networks.d/*.conf |
/var(层外) |
✅ |
| 自管 IP 模式 | allowManaged=1 |
/var(层外) |
✅ |
| SSH 公钥 | authorized_keys |
/home(层外) |
✅ |
关键设计红利:ZeroTier 的身份和网络成员资格都在 /var,不在修改层里。
即使某天丢失了 /opt/zerotier 这个二进制,重装后节点 ID 和 10.71.48.31
都会原样回来 —— 不需要去 ZeroTier 后台重新授权。
4. 实测:一次真实重启
2026-09-18 21:05 执行 sudo systemctl reboot,记录如下:
| 指标 | 重启前 | 重启后 |
|---|---|---|
boot_id |
64329d4d-735c-4afd-99ee-a19cea5f39f2 |
6eee882f-335b-4a41-ad80-6fd7ca45b635 |
| ZeroTier | active | active |
zerotier-cli listnetworks |
OK | OK PRIVATE zteyw6ddju 10.71.48.31/24 |
ssh.service |
active | active |
cc-connect-qqbot |
active | active |
| 工作区 git HEAD | 3cf01a3 |
3cf01a3 |
- 关机耗时约 5 秒内不可达,开机到 SSH 可用约 2.5 分钟
- 全程零人工干预,ZeroTier 自动重连并拿回同一个 IP
结论:重启安全性已由实测确认。
5. 修改层机制
这套系统的关键概念:
- base commit —— 只读的 ostree 系统镜像(
/ostree只读挂载) - 修改层(modification layer) —— overlay 的 upperdir,记录
apt install装的东西、手改的/etc配置等 - 层在持久分区上,重启不会清空
刷新只在两种情况下发生,且都是”先合并、后清空”:
| 触发 | 条件 | 行为 |
|---|---|---|
deepin-immutable-ctl admin deploy |
手动或开机自动 | 把「base + 修改层」合成新 commit → 新 deployment → 更新 GRUB |
--auto-refresh |
修改层体积 > 200 MiB | 合并之后再刷新层,重新开一个干净的 |
阈值配置在 /etc/deepin-immutable-ctl/deepin-immutable-ctl.conf:
# auto-refresh-size-threshold, type int, default is 200,
# the size threshold in MiB for auto refresh modification layer.
[global]
merge-modification-enabled=true # 注意:默认是 false,这台被显式打开了
#auto-refresh-size-threshold=200
5.1 实测到的合并行为
重启前修改层 267 M(usr/ 256 M、opt/ 11 M、etc/ 2 M)。重启后:
| 位置 | 重启前 | 重启后 |
|---|---|---|
活动层 layer-72c793575ac95928 |
267 M | 1 M |
af888468….0/opt-upper/zerotier |
不存在 | 存在 |
也就是内容被搬进了 deployment,没有丢。这印证了”先合并、后清空”的语义。
6. 一个长期失败的系统服务(现已修复)
/usr/lib/systemd/system/deepin-immutable-cleanup.service,由同名 timer 在
每次开机 +5 分钟触发:
ExecStart=/usr/sbin/deepin-immutable-ctl admin deploy --auto-refresh --wait-boot
Restart=no
职责:把修改层合并进 ostree 仓库、按需刷新层、清理旧层目录释放空间。
历史失败记录:
| 启动 | 时间 | 原因 |
|---|---|---|
| boot -1 | 13:53:19 | deepin-immutable-cleanup.timer: Unit to trigger vanished + Failed with result 'resources' |
| boot 0 | 14:28:42 | unable to acquire the operation lock (/var/lib/deepin-immutable-ctl/lock) |
第二次不是偶然,是配置层面的缺陷:unit 只传了 --wait-boot(等 boot 锁),
没传 --wait(等操作锁)。工具自己的报错就提示了 use -w|--wait。
而 Restart=no + timer 只在开机后触发一次 —— 所以开机 5 分钟内只要撞上别的
deepin-immutable-ctl 调用者(同机还有 lastore-daemon、deepin-locale-helper、
uos-recovery),它就当场失败且本次开机不再重试。
风险在于: deploy 从没成功 → 层只增不减 → 机器的”家底”一直处于 未提交状态,靠”层还在”维持,而不是靠”已固化进镜像”。
2026-09-18 21:10:18 首次成功:
Duration: 50.250s
Process: 3039 ExecStart=… admin deploy --auto-refresh --wait-boot
(code=exited, status=0/SUCCESS)
日志里能看到完整的 grub-mkconfig / os-prober 过程。至此该隐患解除。
7. 恢复包
位置:/persistent/recovery-kit/(11 M,在修改层之外,不受层刷新影响)
| 文件 | 内容 |
|---|---|
zerotier/bin/ |
zerotier-one、zerotier-cli、zerotier-idtool |
zerotier-one.service |
systemd unit 原件 |
profile.d-zerotier.sh |
/etc/profile.d/zerotier.sh 原件 |
restore-zerotier.sh |
一键恢复脚本 |
README.md |
说明与验证方法 |
只有在确认 /opt/zerotier 或 unit 丢失时才需要:
sudo bash /persistent/recovery-kit/restore-zerotier.sh
sudo /opt/zerotier/bin/zerotier-cli listnetworks # 期望 … OK … 10.71.48.31/24
如果 SSH 也连不上,用飞牛 NAS 的虚拟机控制台登进去再跑。
8. 待办
- 新 deployment 待生效:本次 deploy 生成了
e1056880fca0a37d…(数据在/persistent/ostree/data/e1056880….0/),当前仍在跑af888468…(已标记hidden)。新部署会在下一次重启时生效,届时需要再验证一次。 GRUB 有「回退到…」菜单项,auto-rollback-on-failure=true仍为开, 兜底存在。 - 系统自带缺陷:
deepin-immutable-cleanup.service只传--wait-boot不传--wait,升级后可能复现,值得复查。 merge-modification-enabled=true与默认不同,走的是较少人验证的分支。/persistent已用 15 G / 62 G,注意 deployment 数量增长 (max-backup-deploys默认 1)。
9. 维护命令速查
# 部署状态(不要用 ostree admin status,这台机器的布局不支持)
sudo /usr/sbin/deepin-immutable-ctl admin status
# 手动提交修改层(慎用,是系统级操作)
sudo /usr/sbin/deepin-immutable-ctl admin deploy
# 快照(安装时已有一个 "First backup" / eb318047dc0ac882)
sudo /usr/sbin/deepin-immutable-ctl snapshot list
# ZeroTier 状态
sudo /opt/zerotier/bin/zerotier-cli info
sudo /opt/zerotier/bin/zerotier-cli listnetworks
# 修改层体积
sudo du -sm /persistent/overlay/data/layer-*
10. 一个容易踩的取证陷阱
虚拟机开机初期系统时钟是错的(boot -1 的日志里时间从 21:48:56 跳回
13:51:47,差约 8 小时,RTC/NTP 校正后恢复)。这导致启动早期创建的文件
带”未来时间戳”—— 例如修改层目录的 Birth 读数是 22:23:41,而当时真实
时间还不到 21:00。
排查这类机器时不要用文件时间戳做因果推断,以 journalctl -b 的日志
顺序和 boot_id 为准。当前时钟已校正正常。
11. 附:两台机器 sudo 密码不同
本机与虚拟机的 admin sudo 密码不是同一个,容易记混。
密码本身不入库,记录在各自的密码管理里。