Add the Packages page for nixpkgs upgrades

A page under System for router-upgrade: the channel to follow, Check,
Preview (the package versions that change, the download size, what would be
built here, a reboot note for a new kernel), Download now and Upgrade. The
steps run in router-upgrade.service, which the page asks through a request
file; the last run's output is kept in upgrade/last.log because a finished
one-shot unit has no journal to look up.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
2026-11-08 22:27:39 +01:00
co-authored by Claude Sonnet 5.5
parent 4ac8c6ea6f
commit dd03127a24
10 changed files with 653 additions and 11 deletions
+36 -2
View File
@@ -41,7 +41,7 @@ let
];
text = ''
usage() {
echo "usage: router-upgrade check | preview [--force] | download | apply [timeout]" >&2
echo "usage: router-upgrade check | preview [--force] | download | apply [timeout] | --request" >&2
echo " check the newest revision of router.update.channel, against the running one" >&2
echo " preview the packages that change and the size of the download (nothing is fetched)" >&2
echo " download fetch and build what was previewed, without activating it" >&2
@@ -50,6 +50,23 @@ let
}
die() { echo "router-upgrade: $*" >&2; exit 1; }
[ $# -gt 0 ] || usage
if [ "$1" = --request ]; then
# What the web UI asked for (${dir}/request.json).
req=${dir}/request.json
[ -r "$req" ] || die "no request"
action=$(jq -er .action "$req")
force=$(jq -r 'if .force then "--force" else "" end' "$req")
timeout=$(jq -r '.timeout // ""' "$req")
rm -f "$req"
# The web UI shows the last run (a finished unit forgets its journal).
exec > >(tee ${dir}/last.log) 2>&1
case $action in
preview) set -- preview ''${force:+"$force"} ;;
apply) set -- apply ''${timeout:+"$timeout"} ;;
check | download) set -- "$action" ;;
*) die "unknown request: $action" ;;
esac
fi
cmd=$1
shift
[ "$(id -u)" -eq 0 ] || die "must run as root"
@@ -234,5 +251,22 @@ in
};
};
config.environment.systemPackages = [ upgrade ];
config = {
environment.systemPackages = [ upgrade ];
# The web UI starts this rather than running anything itself, so a switch
# that restarts the UI does not cut an upgrade short; a switch must not
# restart or stop it either (router-apply is what runs the switch).
systemd.services.router-upgrade = {
description = "Look for, prepare or apply a nixpkgs upgrade";
restartIfChanged = false;
stopIfChanged = false;
path = [ "/run/current-system/sw" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${lib.getExe upgrade} --request";
TimeoutStartSec = "2h";
};
};
};
}