forked from c3d2/nix-config
106 lines
3.9 KiB
Nix
106 lines
3.9 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
{
|
|
options.c3d2.autoUpdate = with lib; mkOption {
|
|
description = ''
|
|
Enables a timer that periodically checks hydra.hq.c3d2.de 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;
|
|
};
|
|
|
|
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.c3d2.autoUpdate {
|
|
wantedBy = [ "multi-user.target" ];
|
|
path = with pkgs; [ nixFlakes 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" https://hydra.hq.c3d2.de/job/c3d2/nix-config/${config.networking.hostName}/latest | jq -r .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 https://hydra.hq.c3d2.de/jobset/c3d2/nix-config"
|
|
# this should fetch the new system from the binary cache
|
|
nix copy --from https://hydra.hq.c3d2.de "$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.gc = lib.mkIf config.c3d2.autoUpdate {
|
|
automatic = true;
|
|
randomizedDelaySec = "6h";
|
|
options = "--delete-older-than 21d";
|
|
};
|
|
|
|
# Always show a diff when activating a new system
|
|
system.activationScripts.diff-system = {
|
|
supportsDryActivation = true;
|
|
text = ''
|
|
if [ -e /run/current-system ] && [ -e $systemConfig ]; then
|
|
echo System package diff:
|
|
${config.nix.package}/bin/nix store diff-closures /run/current-system $systemConfig || true
|
|
fi
|
|
'';
|
|
};
|
|
|
|
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" https://hydra.hq.c3d2.de/job/c3d2/nix-config/${config.networking.hostName}/latest | ${pkgs.jq}/bin/jq -r .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 https://hydra.hq.c3d2.de/jobset/c3d2/nix-config"
|
|
# this should fetch the new system from the binary cache
|
|
nix copy --from https://hydra.hq.c3d2.de "$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
|
|
''
|
|
) ];
|
|
};
|
|
}
|