diff --git a/module/script.nix b/module/script.nix index ccba7eb..ebe9d4f 100644 --- a/module/script.nix +++ b/module/script.nix @@ -18,168 +18,174 @@ ... }: '' - #!/usr/bin/env bash - set -e - - hostname=$(${hostname}) - new_system=$(nix build --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 +do_update() { + hostname=$(${hostname}) + new_system=$(nix build --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 - echo $btime + do_reboot="false" 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 + 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 [[ "$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 [[ "$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 + 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 do_update +then + while true + do + do_update "forced" + done +fi ''