nixos/services/deployment.nix

78 lines
2.9 KiB
Nix
Raw Permalink Normal View History

# One protected activation path for manual, UI and nightly server deployments.
{ config, lib, pkgs, ... }:
let
worker = pkgs.writeShellApplication {
name = "fred-deploy-worker";
runtimeInputs = [
# Nix invokes git when refreshing the git+https flake. Transient units
# do not inherit the interactive shell's package PATH.
config.nix.package pkgs.git pkgs.systemd pkgs.iproute2 pkgs.iputils
pkgs.nftables pkgs.dig pkgs.curl
];
text = ''
export FRED_DEPLOY_RUNNER="$0"
exec ${pkgs.python3}/bin/python3 ${../scripts/deploy.py} "$@"
'';
};
command = pkgs.writeShellApplication {
name = "fred-deploy";
text = ''
if [ "''${1-}" = recover ]; then
shift
if [ -x /nix/var/nix/gcroots/fred-deploy/runner/bin/fred-deploy-worker ]; then
exec /nix/var/nix/gcroots/fred-deploy/runner/bin/fred-deploy-worker launch-recovery "$@"
fi
exec ${worker}/bin/fred-deploy-worker launch-recovery "$@"
fi
exec ${worker}/bin/fred-deploy-worker launch "$@"
'';
};
in {
config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") {
environment.systemPackages = [ command ];
system.build.deploy = command;
systemd.services.nixos-upgrade = {
description = "Build, verify and commit the nightly server deployment";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
restartIfChanged = false;
unitConfig.X-StopOnRemoval = false;
serviceConfig = {
Type = "oneshot";
ExecStart = "${command}/bin/fred-deploy --reboot";
TimeoutStartSec = "105min";
};
};
systemd.timers.nixos-upgrade = {
wantedBy = [ "timers.target" ];
timerConfig = { OnCalendar = "05:15"; Persistent = true; };
};
# Transient rollback timers do not survive reboot. Recover unfinished
# transactions from durable state using the pinned transaction runner.
systemd.services.fred-deploy-recover = {
description = "Recover an interrupted server deployment";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
before = [ "wan-watchdog.service" "nixos-upgrade.service" ];
restartIfChanged = false;
unitConfig.X-StopOnRemoval = false;
# A oneshot WantedBy=multi-user would hold up that target while the
# activation script waits for target start jobs: use exec so boot can
# finish while recovery holds the shared deployment lock.
serviceConfig = {
Type = "exec";
RuntimeMaxSec = "15min";
TimeoutStopSec = "10s";
};
script = ''
if [ -x /nix/var/nix/gcroots/fred-deploy/runner/bin/fred-deploy-worker ]; then
exec /nix/var/nix/gcroots/fred-deploy/runner/bin/fred-deploy-worker recover --boot
fi
exec ${worker}/bin/fred-deploy-worker recover --boot
'';
};
};
}