From 8c53c66c4da975e544f3421d72938268927530f3 Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Fri, 11 Jul 2025 13:14:48 +0200 Subject: [PATCH] Add frajul-auto-upgrade module --- modules/nixos/default.nix | 1 + modules/nixos/frajul-auto-upgrade.nix | 130 ++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 modules/nixos/frajul-auto-upgrade.nix diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 321a10a..db58c58 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -1,4 +1,5 @@ { # hydra-auto-upgrade = import ./hydra-auto-upgrade.nix; syncthing = import ./syncthing.nix; + frajulAutoUpgrade = import ./frajul-auto-upgrade.nix; } diff --git a/modules/nixos/frajul-auto-upgrade.nix b/modules/nixos/frajul-auto-upgrade.nix new file mode 100644 index 0000000..4b9006b --- /dev/null +++ b/modules/nixos/frajul-auto-upgrade.nix @@ -0,0 +1,130 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.modules.frajulAutoUpgrade; + + flagFile = "/var/lib/frajul-auto-upgrade/flag"; + lockFile = "/var/lib/frajul-auto-upgrade/lock"; + lastStatusFile = "/var/lib/nixos-auto-upgrade/last-status"; +in { + options.modules.frajulAutoUpgrade = { + enable = lib.mkEnableOption "NixOS auto-upgrade on boot"; + + user = lib.mkOption { + type = lib.types.str; + default = "root"; + description = "User account to run the upgrade service as."; + }; + + flakePath = lib.mkOption { + type = lib.types.path; + description = "The path to your flake"; + }; + }; + + config = lib.mkIf cfg.enable { + # Ensure the flag directory exists + systemd.tmpfiles.rules = [ + "d /var/lib/frajul-auto-upgrade 0755 root root -" + "f ${flagFile} 0766 root root -" + "f ${lastStatusFile} 0644 root root -" + ]; + + environment.systemPackages = [ + (pkgs.writeShellScriptBin "frajul-auto-upgrade" '' + #!/bin/sh + FLAG_FILE="${flagFile}" + LOCK_FILE="${lockFile}" + LAST_STATUS_FILE="${lastStatusFile}" + + if [ ! -f "$FLAG_FILE" ] || [ "$(cat "$FLAG_FILE")" != "enabled" ]; then + exit 0 + fi + + if [ -f "$LOCK_FILE" ]; then + echo "Already running" + exit 1 + fi + + echo $$ > "$LOCK_FILE" + trap 'rm -f "$LOCK_FILE"' EXIT + + if nix flake update --flake "${cfg.flakePath}" && nixos-rebuild switch --flake "${cfg.flakePath}"; then + echo "success" > "$LAST_STATUS_FILE" + else + echo "failure" > "$LAST_STATUS_FILE" + fi + '') + + (pkgs.writeShellScriptBin "frajul-auto-upgrade-status" '' + #!/bin/sh + FLAG_FILE="${flagFile}" + LOCK_FILE="${lockFile}" + LAST_STATUS_FILE="${lastStatusFile}" + + if [ -f "$LOCK_FILE" ]; then + ICON=" " + STATUS="running" + elif [ -f "$FLAG_FILE" ] && [ "$(cat "$FLAG_FILE")" == "enabled" ]; then + LAST="unknown" + if [ -f "$LAST_STATUS_FILE" ]; then + LAST=$(cat "$LAST_STATUS_FILE") + fi + + if [ "$LAST" = "success" ]; then + ICON="" + elif [ "$LAST" = "failure" ]; then + ICON="" + else + ICON="" + fi + + STATUS="enabled (last: $LAST)" + else + ICON=" " + STATUS="disabled" + fi + + echo "{\"text\": \"$ICON\", \"tooltip\": \"NixOS Auto Update: $STATUS\"}" + '') + + (pkgs.writeShellScriptBin "frajul-auto-upgrade-toggle" '' + #!/bin/sh + FLAG_FILE="${flagFile}" + LOCK_FILE="${lockFile}" + + if [ ! -f "$FLAG_FILE" ] || [ "$(cat "$FLAG_FILE")" != "enabled" ]; then + echo "enabled" > "$FLAG_FILE" + else + echo "disabled" > "$FLAG_FILE" + if [ -f "$LOCK_FILE" ]; then + kill -TERM "$(cat "$LOCK_FILE")" + fi + fi + '') + ]; + + systemd.services.frajul-auto-upgrade = { + description = "Frajul's NixOS Auto Upgrade"; + after = ["network-online.target"]; + restartIfChanged = false; # Do not start service on nixos switch + serviceConfig = { + Type = "oneshot"; + User = cfg.user; + ExecStart = "/run/current-system/sw/bin/frajul-auto-upgrade"; + }; + }; + systemd.timers.frajul-auto-upgrade = { + description = "Run Frajul's NixOS Auto Upgrade at boot"; + wantedBy = ["timers.target"]; + timerConfig = { + OnBootSec = "1min"; + AccuracySec = "10s"; + Unit = "frajul-auto-upgrade.service"; + }; + }; + }; +}