Files
commoncomputing-nix/hosts/asusmini/auto-update.nix
T

124 lines
4.4 KiB
Nix

{ pkgs, ... }:
{
systemd.services.auto-update = {
description = "Auto-update NixOS configuration";
path = with pkgs; [
coreutils
curl
git
jq
nix
openssh
util-linux
];
serviceConfig = {
Type = "oneshot";
User = "root";
WorkingDirectory = "/etc/commonscomputing-nix";
TimeoutStartSec = "6h";
};
restartIfChanged = false;
unitConfig.ConditionPathExists = "/var/lib/knot/.upgrade-verified";
unitConfig.X-StopOnRemoval = false;
environment = {
GIT_TERMINAL_PROMPT = "0";
GIT_SSH_COMMAND = "${pkgs.openssh}/bin/ssh -o BatchMode=yes -o ConnectTimeout=15";
};
script = ''
set -euo pipefail
exec 9>/run/lock/commonscomputing-update.lock
flock --nonblock 9 || exit 0
lock_snapshot="$(${pkgs.coreutils}/bin/mktemp)"
snapshot_ready=0
activated=0
validated=0
system_profile=/nix/var/nix/profiles/system
cleanup() {
status=$?
trap - EXIT
set +e
if [ "$status" -ne 0 ] && [ "$snapshot_ready" -eq 1 ] && [ "$activated" -eq 0 ]; then
${pkgs.coreutils}/bin/cp "$lock_snapshot" flake.lock
fi
if [ "$status" -ne 0 ] && [ "$activated" -eq 1 ] && [ "$validated" -eq 0 ]; then
# New binaries may already have migrated persistent state. Never
# blindly roll back their data format or discard accepted writes.
rm -f /var/lib/knot/.upgrade-verified
${pkgs.systemd}/bin/systemctl stop auto-update.timer
${pkgs.systemd}/bin/systemctl stop knot-rs.service spindle.service
echo "Activation/health failed: application services and updates stopped; inspect state and retained flake.lock" >&2
elif [ "$status" -ne 0 ] && [ "$validated" -eq 1 ]; then
echo "System is healthy, but Git publication failed; retain/reconcile the local lockfile or commit before retrying" >&2
fi
${pkgs.coreutils}/bin/rm -f "$lock_snapshot"
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
if ! git diff --cached --quiet; then
echo "Refusing to run with staged changes"
exit 1
fi
if ! git diff --quiet -- flake.lock; then
echo "Refusing to run with preexisting flake.lock changes"
exit 1
fi
if ! git diff --quiet -- '*.nix'; then
echo "Refusing to deploy uncommitted Nix configuration changes"
exit 1
fi
git pull --ff-only
git push --dry-run
${pkgs.coreutils}/bin/cp flake.lock "$lock_snapshot"
snapshot_ready=1
nix flake update
echo "Building NixOS toplevel..."
toplevel="$(${pkgs.nix}/bin/nix build .#nixosConfigurations.asusmini.config.system.build.toplevel --no-link --print-out-paths)"
echo "Activating new system..."
activated=1
${pkgs.nix}/bin/nix-env -p "$system_profile" --set "$toplevel"
"$toplevel/bin/switch-to-configuration" switch
${pkgs.systemd}/bin/systemctl is-active --quiet knot-rs
${pkgs.systemd}/bin/systemctl is-active --quiet spindle
${pkgs.systemd}/bin/systemctl is-active --quiet sshd
${pkgs.curl}/bin/curl --fail --silent --show-error --max-time 10 --retry 5 --retry-connrefused --retry-delay 1 http://127.0.0.1:5555/xrpc/_health | jq -e '.version | length > 0'
${pkgs.curl}/bin/curl --fail --silent --show-error --max-time 10 --retry 5 --retry-connrefused --retry-delay 1 http://127.0.0.1:6555/_health | jq -e '.status == "ok"'
${pkgs.curl}/bin/curl --fail --silent --show-error --max-time 15 https://knot.commonscomputer.com/xrpc/org.tangled.knot.describeKnot | jq -e '.did == "did:web:knot.commonscomputer.com" and .contact.email == "pds@email.commonscomputer.com"'
validated=1
snapshot_ready=0
if ! git diff --quiet -- flake.lock; then
git add flake.lock
git commit -m "auto-update: flake inputs $(${pkgs.coreutils}/bin/date -Iseconds)"
fi
git push
echo "Auto-update completed successfully"
'';
};
systemd.timers.auto-update = {
enable = true;
description = "Auto-update timer";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "weekly"; # Run weekly, adjust as needed
Persistent = true; # Run on boot if missed
RandomizedDelaySec = "1h"; # Add some randomness
};
unitConfig.ConditionPathExists = "/var/lib/knot/.upgrade-verified";
};
}