61ce1beb19
Three diagnostic defects from the follow-up audit. 1. The reboot plan was entirely best-effort. persist_plan discarded the directory creation, the write and every error. The plan file is the only thing on the host that says when it is going to reboot, so a failed write produced a scheduler sitting on a timer that nothing could report. It now creates the directory, writes through a temp file with sync_all and rename, and returns Result. The plan also outlived its meaning in two places. With reboot.enabled = false the scheduler exited without touching a plan written when it was still enabled, so status kept advertising a reboot that would never happen. And after systemd accepted the reboot request the plan stayed behind, leaving a past timestamp looking pending. Both paths now clear it; an absent plan is the desired end state, not an error. 2. sysctl status turned a read failure into "file absent". inspect_sysctl_tuning used fs::read_to_string(..).ok() for both managed files, so an unreadable file was reported as missing - a diagnostic stating the opposite of the truth, in the module whose whole job is to report drift accurately. Reads now go through ManagedFile::read, which distinguishes absent from unreadable, and an unreadable file produces its own drift reason naming the path and the error. 3. README described the removed ExecStartPre. It still said the service runs ensure-swap before starting the daemon. The daemon performs it as the first step of its own startup sequence. Docs also state explicitly what survives swap.enabled = false, which was implied but never written: the swapfile, its activation and the /etc/fstab entry all remain, so swap comes back after a reboot. Only the vm.swappiness persistence is removed. Acceptance checklist gained seven checks covering the priority-only path not recreating the file, swap remaining active throughout a resize, foreign-swap rollback, the unreadable status, and both reboot-plan lifecycle cases. cargo test --workspace: 179 + 4 passed. clippy -D warnings clean.
awg2-reboot-scheduler
awg2-reboot-scheduler — отдельный production-бинарь в составе пакета AWG2 Harness. Его задача узкая: один раз на старте прочитать секцию [reboot] из общего /etc/awg2-harness/config.toml, выбрать случайный момент внутри заданного UTC-окна, записать план в /run/awg2-harness/reboot.plan и в назначенное время запросить reboot через systemctl --no-block reboot.
Он вынесен отдельно от основного awg2-harness daemon, чтобы плановый reboot не зависел от traffic/firewall reconciliation loop.
Runtime paths
binary: /usr/sbin/awg2-reboot-scheduler
unit: /lib/systemd/system/awg2-reboot-scheduler.service
config: /etc/awg2-harness/config.toml
plan file: /run/awg2-harness/reboot.plan
Конфигурация
[reboot]
enabled = true
window_start_utc = "01:00"
window_end_utc = "02:00"
Если enabled = false, процесс печатает disabled by config и завершается без reboot.
Проверка на production host
systemctl status awg2-reboot-scheduler.service --no-pager -l
journalctl -u awg2-reboot-scheduler.service --since '10 minutes ago' --no-pager
cat /run/awg2-harness/reboot.plan
awg2-harness --config /etc/awg2-harness/config.toml status
Ручной запуск для диагностики
/usr/sbin/awg2-reboot-scheduler --config /etc/awg2-harness/config.toml