{ 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 = lib.mkIf config.c3d2.autoUpdate { # the presence of this 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. environment.etc."autoupdated".text = ""; systemd.services.autoupdate = { wantedBy = [ "multi-user.target" ]; path = with pkgs; [ nixFlakes nettools curl jq ]; serviceConfig.Type = "oneshot"; script = '' OLD=$(readlink /run/current-system) NEW=$(curl -sLH "Accept: application/json" https://hydra.hq.c3d2.de/job/c3d2/nix-config/x86_64-linux.$(hostname)/latest | jq -r .buildoutputs.out.path) if [ -z "$NEW" ]; then echo "Unable to obtain updated system" exit 1 fi if [ "$OLD" != "$NEW" ]; then echo "New system available: $NEW" # this should fetch the new system from the binary cache nix build --no-link "$NEW" if [ -e "$NEW/sw/etc/autoupdated" ]; then # switch to the new system "$NEW/bin/switch-to-configuration" switch else echo "New system is not yet autoupdated" fi else echo "No update required" fi ''; # don't let the switch kill this service, aborting the switch restartIfChanged = false; unitConfig.X-StopOnRemoval = false; }; systemd.timers.autoupdate = { partOf = [ "autoupdate.service" ]; wantedBy = [ "timers.target" ]; timerConfig.OnCalendar = "hourly"; }; nix.gc = { automatic = true; randomizedDelaySec = "6h"; }; }; }