diff options
author | Alan Pearce | 2025-03-10 12:48:11 +0100 |
---|---|---|
committer | Alan Pearce | 2025-03-10 12:48:11 +0100 |
commit | d434b963b14e14ea5fb36c600bd19f6ffb9cd1c3 (patch) | |
tree | a5a8636729768000bc50d782b6d3965f4809a9c6 /system/settings/colmena-auto-upgrade.nix | |
parent | 1f522140b56606a3c5ad7114cf04ce0676330212 (diff) | |
download | nixfiles-d434b963b14e14ea5fb36c600bd19f6ffb9cd1c3.tar.lz nixfiles-d434b963b14e14ea5fb36c600bd19f6ffb9cd1c3.tar.zst nixfiles-d434b963b14e14ea5fb36c600bd19f6ffb9cd1c3.zip |
linde: automatically upgrade with colmena
Diffstat (limited to 'system/settings/colmena-auto-upgrade.nix')
-rw-r--r-- | system/settings/colmena-auto-upgrade.nix | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/system/settings/colmena-auto-upgrade.nix b/system/settings/colmena-auto-upgrade.nix new file mode 100644 index 00000000..add141b6 --- /dev/null +++ b/system/settings/colmena-auto-upgrade.nix @@ -0,0 +1,237 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.services.colmenaAutoUpgrade; + + mainScript = + let + colmena = "${pkgs.colmena}/bin/colmena"; + date = "${pkgs.coreutils}/bin/date"; + readlink = "${pkgs.coreutils}/bin/readlink"; + shutdown = "${config.systemd.package}/bin/shutdown"; + in + if cfg.allowReboot then + '' + ${colmena} apply-local boot + booted="$(${readlink} /run/booted-system/{initrd,kernel,kernel-modules})" + built="$(${readlink} /nix/var/nix/profiles/system/{initrd,kernel,kernel-modules})" + + ${lib.optionalString (cfg.rebootWindow != null) '' + 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 [ "''${booted}" = "''${built}" ]; then + ${colmena} apply-local switch + ${lib.optionalString (cfg.rebootWindow != null) '' + elif [ "''${do_reboot}" != true ]; then + echo "Outside of configured reboot window, skipping." + ''} + else + ${shutdown} -r +1 + fi + '' + else + '' + ${colmena} apply-local switch + '' + ; +in +{ + options.services.colmenaAutoUpgrade = { + enable = lib.mkEnableOption { + default = false; + description = "Enable automatic upgrades for Colmena"; + }; + + pullGit = lib.mkOption { + default = false; + type = lib.types.bool; + description = '' + Whether to pull the latest changes from the Git repository before upgrading. + ''; + }; + + useNixShell = lib.mkOption { + default = false; + type = lib.types.bool; + description = '' + Whether to run colmena in a nix-shell. + ''; + }; + + dates = lib.mkOption { + type = lib.types.str; + default = "04:40"; + example = "daily"; + description = '' + How often or when upgrade occurs. For most desktop and server systems + a sufficient upgrade frequency is once a day. + + The format is described in + {manpage}`systemd.time(7)`. + ''; + }; + + allowReboot = lib.mkOption { + default = false; + type = lib.types.bool; + description = '' + Reboot the system into the new generation instead of a switch + if the new generation uses a different kernel, kernel modules + or initrd than the booted system. + See {option}`rebootWindow` for configuring the times at which a reboot is allowed. + ''; + }; + + randomizedDelaySec = lib.mkOption { + default = "0"; + type = lib.types.str; + example = "45min"; + description = '' + Add a randomized delay before each automatic upgrade. + The delay will be chosen between zero and this value. + This value must be a time span in the format specified by + {manpage}`systemd.time(7)` + ''; + }; + + fixedRandomDelay = lib.mkOption { + default = false; + type = lib.types.bool; + example = true; + description = '' + Make the randomized delay consistent between runs. + This reduces the jitter between automatic upgrades. + See {option}`randomizedDelaySec` for configuring the randomized delay. + ''; + }; + + rebootWindow = lib.mkOption { + description = '' + Define a lower and upper time value (in HH:MM format) which + constitute a time window during which reboots are allowed after an upgrade. + This option only has an effect when {option}`allowReboot` is enabled. + The default value of `null` means that reboots are allowed at any time. + ''; + default = null; + example = { + lower = "01:00"; + upper = "05:00"; + }; + type = + with lib.types; + nullOr (submodule { + options = { + lower = lib.mkOption { + description = "Lower limit of the reboot window"; + type = lib.types.strMatching "[[:digit:]]{2}:[[:digit:]]{2}"; + example = "01:00"; + }; + + upper = lib.mkOption { + description = "Upper limit of the reboot window"; + type = lib.types.strMatching "[[:digit:]]{2}:[[:digit:]]{2}"; + example = "05:00"; + }; + }; + }); + }; + + persistent = lib.mkOption { + default = true; + type = lib.types.bool; + example = false; + description = '' + Takes a boolean argument. If true, the time when the service + unit was last triggered is stored on disk. When the timer is + activated, the service unit is triggered immediately if it + would have been triggered at least once during the time when + the timer was inactive. Such triggering is nonetheless + subject to the delay imposed by RandomizedDelaySec=. This is + useful to catch up on missed runs of the service when the + system was powered down. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.colmena-auto-upgrade = { + description = "Upgrade nixos with colmena"; + + restartIfChanged = false; + unitConfig.X-StopOnRemoval = false; + + serviceConfig.Type = "oneshot"; + + environment = + config.nix.envVars + // { + inherit (config.environment.sessionVariables) NIX_PATH; + HOME = "/root"; + } + // config.networking.proxy.envVars; + + path = with pkgs; [ + coreutils + gnutar + xz.bin + gzip + gitMinimal + colmena + config.nix.package.out + config.programs.ssh.package + ]; + + serviceConfig.WorkingDirectory = "/etc/nixos"; + script = + let + git = "${pkgs.gitMinimal}/bin/git"; + nix-shell = "${pkgs.nix}/bin/nix-shell"; + in + '' + ${lib.optionalString cfg.pullGit + '' + ${git} fetch --all --prune + ${git} checkout FETCH_HEAD + '' + } + ${if cfg.useNixShell then '' + ${nix-shell} --run "${pkgs.writeShellScript "colmena-auto-upgrade" mainScript}" + '' + else mainScript + } + ''; + startAt = cfg.dates; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + }; + + systemd.timers.colmena-auto-upgrade = { + timerConfig = { + RandomizedDelaySec = cfg.randomizedDelaySec; + FixedRandomDelay = cfg.fixedRandomDelay; + Persistent = cfg.persistent; + }; + }; + }; +} |