{ cfg, nixos-rebuild, date, realpath, stat, cut, head, grep, grub-reboot, shutdown, bootctl, systemd-analyze, upgradeFlag, units, jq, hostname, ... }: '' do_update() { hostname=$(${hostname}) new_system=$(nix build --refresh --no-link --print-out-paths "${cfg.flake}#nixosConfigurations.''${hostname}.config.system.build.toplevel") last_flake_update_time() { nix flake metadata --refresh --json "$1" | ${jq} .lastModified } updated_since_reboot() { [[ $(${stat} -c %Y /run/current-system) -gt $(($(${date} +%s) - $(${cut} -d. -f1 /proc/uptime) + $(${units} --compact --one-line "ceil($(${units} --compact --one-line "$(${systemd-analyze} time | head -n 1 | ${grep} -Eo "\S+\s+$")" seconds))"))) ]] } boot_system_path() { bpath="" btime=0 for f in /nix/var/nix/profiles/* do if [[ -z $bpath ]] || [[ $btime -lt $(${stat} -c %Y $f) ]] then bpath=$f btime=$(${stat} -c %Y $f) fi done if [[ -d "/nix/var/nix/profiles/system-profiles/" ]] && [[ -n "$(ls -A /nix/var/nix/profiles/system-profiles/)" ]] then for f in /nix/var/nix/profiles/system-profiles/* do if [[ -z $bpath ]] || [[ $btime -lt $(${stat} -c %Y $f) ]] then bpath=$f btime=$(${stat} -c %Y $f) fi done fi echo "$bpath" } last_update_time() { rpath=$(${realpath} /run/current-system) rtime=$(${stat} -c %Y /run/current-system) boot_system=$(boot_system_path) bpath=$(${realpath} "$boot_system") btime=$(${stat} -c %Y "$boot_system") if [[ "''${rpath}" == "''${bpath}" ]] then if ! updated_since_reboot then echo $btime return fi fi if [[ $rtime -gt $btime ]] then echo $rtime else echo $btime fi } latest_system=$(boot_system_path) if [[ "$(${realpath} /run/booted-system)" == "$(${realpath} /run/current-system)" ]] && [[ "$(${realpath} /run/booted-system)" == "$(${realpath} "$latest_system")" ]] then if [[ -f /boot/grub/grub.cfg ]] then if [[ $(($(${date} +%s) - $(${cut} -d. -f1 /proc/uptime))) -gt $(${stat} -c %Y /boot/grub/grub.cfg) ]] then echo "persisting boot system" "$(${realpath} /run/booted-system)/bin/switch-to-configuration" "boot" fi fi fi if [[ "$new_system" == "$(${realpath} /run/current-system)" ]] && [[ "$new_system" == "$(${realpath} "$latest_system")" ]] then echo "system is up-to-date" exit 0 fi system_update_time=$(last_update_time) flake_update_time=$(last_flake_update_time "${cfg.flake}") echo "last system update: $(${date} -d @"$system_update_time")" echo "last flake update: $(${date} -d @"$flake_update_time")" if [[ -z "$1" ]] && [[ "$system_update_time" -gt "$flake_update_time" ]] then echo "" echo "System is newer than remote!" echo "This happens if the system was updated manually or a system update failed." echo "Skipping system update to prevent potential downgrade!" exit 0 fi echo "Updating system ..." system_info_booted="$(${realpath} /run/booted-system/{initrd,kernel,kernel-modules})" system_info_built="$(${realpath} "''${new_system}"/{initrd,kernel,kernel-modules})" echo $system_info_booted echo $system_info_built current_time="$(${date} +%H:%M)" lower=${cfg.rebootWindow.lower} upper=${cfg.rebootWindow.upper} if [[ "''${lower}" < "''${upper}" ]]; then if [[ "''${current_time}" > "''${lower}" ]] && \ [[ "''${current_time}" < "''${upper}" ]]; then do_reboot="true" else do_reboot="false" fi else # lower > upper, so we are crossing midnight (e.g. lower=23h, upper=6h) # we want to reboot if cur > 23h or cur < 6h if [[ "''${current_time}" < "''${upper}" ]] || \ [[ "''${current_time}" > "''${lower}" ]]; then do_reboot="true" else do_reboot="false" fi fi if [[ "$system_info_booted" != "$system_info_built" ]] then echo "Updating system requires reboot!" if [ "''${do_reboot}" != true ] then echo "Outside of configured reboot window, skipping update." exit 0 fi echo nix-env --profile /nix/var/nix/profiles/system --set "$new_system" if [[ -f /boot/grub/grub.cfg ]] then echo "bootloader 'GRUB' detected, configuring test-boot into new system" "''${latest_system}/bin/switch-to-configuration" "boot" ${grub-reboot} "NixOS - All configurations>0" #${grub-reboot} "NixOS - Profile '$PROFILE_NAME'>0" elif ${bootctl} list 2>&1 | ${grep} -v "No boot loader entries found." > /dev/null then echo "bootloader 'systemd-boot' detected, configuring oneshot-boot into new system" # TODO exit -1 else echo "test-boot not supported. persisting new boot system" "''${new_system}/bin/switch-to-configuration" "boot" fi ${shutdown} -r +1 else nix-env --profile /nix/var/nix/profiles/system --set "$new_system" if ! "''${new_system}/bin/switch-to-configuration" "test" then echo "testing new configuration failed!" echo "system was automatically rolled back to old configuration." exit 1 fi "''${new_system}/bin/switch-to-configuration" "boot" fi if [[ "$(last_flake_update_time "${cfg.flake}")" -gt "$flake_update_time" ]] then echo "flake was update after last update." do_update force fi } ''