Files
dotfiles/modules/nixos/frajul-auto-upgrade.nix

155 lines
4.4 KiB
Nix

{
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/frajul-auto-upgrade/last-status";
lastAttemptFile = "/var/lib/frajul-auto-upgrade/last-attempt";
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 -"
"f ${lastAttemptFile} 0644 root root -"
];
environment.systemPackages = [
(pkgs.writeShellScriptBin "frajul-auto-upgrade" ''
#!/bin/sh
FLAG_FILE="${flagFile}"
LOCK_FILE="${lockFile}"
LAST_STATUS_FILE="${lastStatusFile}"
LAST_ATTEMPT_FILE="${lastAttemptFile}"
TODAY=$(date +%Y-%m-%d)
if [ ! -f "$FLAG_FILE" ] || [ "$(cat "$FLAG_FILE")" != "enabled" ]; then
echo "Auto upgrade disabled. Exiting."
exit 0
fi
# Check if already attempted today
if [ -f "$LAST_ATTEMPT_FILE" ]; then
LAST_ATTEMPT_DATE=$(cut -d' ' -f1 "$LAST_ATTEMPT_FILE")
if [ "$LAST_ATTEMPT_DATE" = "$TODAY" ]; then
echo "Update already attempted today. Skipping."
exit 0
fi
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
# Write full timestamp
date '+%Y-%m-%d %H:%M:%S' > "$LAST_ATTEMPT_FILE"
'')
(pkgs.writeShellScriptBin "frajul-auto-upgrade-status" ''
#!/bin/sh
FLAG_FILE="${flagFile}"
LOCK_FILE="${lockFile}"
LAST_STATUS_FILE="${lastStatusFile}"
LAST_ATTEMPT_FILE="${lastAttemptFile}"
if [ -f "$LOCK_FILE" ]; then
ICON=" "
STATUS="running"
elif [ -f "$FLAG_FILE" ] && [ "$(cat "$FLAG_FILE")" == "enabled" ]; then
LAST_STATUS="unknown"
LAST_ATTEMPT="never"
if [ -f "$LAST_STATUS_FILE" ]; then
LAST_STATUS=$(cat "$LAST_STATUS_FILE")
fi
if [ -f "$LAST_ATTEMPT_FILE" ]; then
LAST_ATTEMPT=$(cat "$LAST_ATTEMPT_FILE")
fi
if [ "$LAST_STATUS" = "success" ]; then
ICON=""
elif [ "$LAST_STATUS" = "failure" ]; then
ICON=""
else
ICON=""
fi
STATUS="enabled (last attempt: $LAST_ATTEMPT, $LAST_STATUS)"
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";
};
};
};
}