Files
infrastructure/machines/modules/autoupdate.nix
kalipso 98a79d708a [durruti] fix wiping of hosts /nix/store
the automatic garbage collection of durruti - which runs inside a
nixos-container - complelty wiped the hosts nix store making basically
all the services fail and the machine unbootable.
2024-10-25 12:47:27 +02:00

140 lines
4.6 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.malobeo.autoUpdate;
in
{
options.malobeo.autoUpdate = {
enable = mkOption {
description = ''
Enables a timer that periodically checks a hydra instance for the last build of the local system, and switches to it if it is different.
Also enables periodical /nix/store GC.
'';
type = types.bool;
default = false;
};
# https://hydra.dynamicdiscord.de/job/malobeo/infrastructure/louise/latest
url = mkOption {
description = lib.mdDoc ''
Url to your hydra instace. like https://hydra.example.de
'';
type = types.str;
default = "";
};
project = mkOption {
description = lib.mdDoc ''
Name of the project at the hydra instace
'';
type = types.str;
default = "";
};
jobset = mkOption {
description = lib.mdDoc ''
Name of the jobset at the hydra instace
'';
type = types.str;
default = "";
};
cacheurl = mkOption {
description = lib.mdDoc ''
Url of the binary cache
'';
type = types.str;
default = cfg.url;
};
};
config = {
# the presence of this .service file signifies that the system is
# autoupdate-enabled. it is checked to prevent autoupdating back
# to a system without autoupdate when deploying with autoupdate
# for the first time.
systemd.services.autoupdate = lib.mkIf config.malobeo.autoUpdate.enable {
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ nix nettools curl jq ];
serviceConfig = {
Type = "oneshot";
# switch-to-configuration may not return. HACK: cap running
# time so that the timer can be scheduled again.
TimeoutStartSec = "30min";
};
script = ''
OLD=$(readlink /run/current-system)
echo Current system: $(basename $OLD)
NEW=$(curl -sLH "Accept: application/json" ${cfg.url}/job/${cfg.project}/${cfg.jobset}/${config.networking.hostName}/latest | jq -er .buildoutputs.out.path)
if [ -z "$NEW" ] || [ "$NEW" = "null" ]; then
echo "Unable to obtain updated system"
exit 1
fi
echo New system: $(basename $NEW)
if [ "$OLD" != "$NEW" ]; then
echo "Fetching new system built by ${cfg.url}/job/${cfg.project}/${cfg.jobset}"
# this should fetch the new system from the binary cache
nix copy --from ${cfg.cacheurl} "$NEW"
if [ -e "$NEW/etc/systemd/system/autoupdate.timer" ]; then
echo "Switch to the new system..."
nix-env -p /nix/var/nix/profiles/system --set $NEW
"$NEW/bin/switch-to-configuration" switch
else
echo "New system is not yet autoupdate-enabled. Refusing to switch into a dead end."
fi
else
echo "No update required"
fi
'';
# don't let the switch kill this service, aborting the switch
restartIfChanged = false;
unitConfig.X-StopOnRemoval = false;
# create timer
startAt = "hourly";
};
nix = {
# Show a diff when activating a new system except for microvms which handle this seperately
#diffSystem = config.malobeo.deployment.server or "" == "";
#TODO: THIS WIPES HOSTS NIX STORE FROM WITHIN NIXOS-CONTAINER
#gc = lib.mkIf config.malobeo.autoUpdate.enable {
# automatic = true;
# randomizedDelaySec = "6h";
# options = "--delete-older-than 21d";
#};
};
environment.systemPackages = [ (
# Provide a manual updating script that fetches the latest
# updated+built system from Hydra
pkgs.writeScriptBin "update-from-hydra" ''
#! ${pkgs.runtimeShell} -e
OLD=$(readlink /run/current-system)
echo Current system: $(basename $OLD)
NEW=$(curl -sLH "Accept: application/json" ${cfg.url}/job/${cfg.project}/${cfg.jobset}/${config.networking.hostName}/latest | ${pkgs.jq}/bin/jq -er .buildoutputs.out.path)
if [ -z "$NEW" ] || [ "$NEW" = "null" ]; then
echo "Unable to obtain updated system"
exit 1
fi
echo New system: $(basename $NEW)
if [ "$OLD" != "$NEW" ]; then
echo "Fetching new system built by ${cfg.url}/job/${cfg.project}/${cfg.jobset}"
# this should fetch the new system from the binary cache
nix copy --from ${cfg.cacheurl} "$NEW"
echo "Switch to the new system..."
nix-env -p /nix/var/nix/profiles/system --set $NEW
"$NEW/bin/switch-to-configuration" switch
else
echo "No update required"
fi
''
) ];
};
}