tvl-depot/ops/modules/auto-deploy.nix
Vincent Ambo 7cac51a995 feat(ops/auto-deploy): Support emergency stops via stop file
Adds a feature to emergency-stop deploys by simply running `touch
/var/lib/auto-deploy/stop`.

This can be useful in some situations, especially if there is a
process that reconciles service state (so that e.g. stopping the
unit's timer would be undone).

Change-Id: I233dfac365a578bfa4110eb605b50be079974ba4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/4827
Autosubmit: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: wpcarro <wpcarro@gmail.com>
2022-01-07 17:17:33 +00:00

103 lines
2.8 KiB
Nix

# Defines a service for automatically and periodically calling depot's
# rebuild-system on a NixOS machine.
#
# Deploys can be stopped in emergency situations by creating an empty
# file called `stop` in the state directory of the auto-deploy service
# (typically /var/lib/auto-deploy).
{ depot, config, lib, pkgs, ... }:
let
cfg = config.services.depot.auto-deploy;
description = "to automatically rebuild the current system's NixOS config from the latest checkout of depot";
rebuild-system = depot.ops.nixos.rebuildSystemWith "$STATE_DIRECTORY/deploy";
deployScript = pkgs.writeShellScript "auto-deploy" ''
set -ueo pipefail
if [[ $EUID -ne 0 ]]; then
echo "Oh no! Only root is allowed to run auto-deploy!" >&2
exit 1
fi
if [[ -f $STATE_DIRECTORY/stop ]]; then
echo "stop file exists in $STATE_DIRECTORY, not deploying!" >&2
exit 1
fi
readonly depot=$STATE_DIRECTORY/depot.git
readonly deploy=$STATE_DIRECTORY/deploy
readonly git="git -C $depot"
# find-or-create depot
if [ ! -d $depot ]; then
# cannot use $git here because $depot doesn't exist
git clone --bare ${cfg.git-remote} $depot
fi
function cleanup() {
$git worktree remove $deploy
}
trap cleanup EXIT
$git fetch origin
$git worktree add --force $deploy FETCH_HEAD
# unsure why, but without this switch-to-configuration attempts to install
# NixOS in $STATE_DIRECTORY
(cd / && ${rebuild-system}/bin/rebuild-system)
'';
in {
options.services.depot.auto-deploy = {
enable = lib.mkEnableOption description;
git-remote = lib.mkOption {
type = lib.types.str;
default = "https://cl.tvl.fyi/depot.git";
description = ''
The (possibly remote) repository from which to clone as specified by the
GIT URLS section of `man git-clone`.
'';
};
interval = lib.mkOption {
type = lib.types.str;
example = "1h";
description = ''
Interval between Nix builds, specified in systemd.time(7) format.
'';
};
};
config = lib.mkIf cfg.enable {
systemd.services.auto-deploy = {
inherit description;
script = "${deployScript}";
path = with pkgs; [
bash
git
gnutar
gzip
];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
# We need to prevent NixOS from interrupting us while it attempts to
# restart systemd units.
restartIfChanged = false;
serviceConfig = {
Type = "oneshot";
StateDirectory = "auto-deploy";
};
};
systemd.timers.auto-deploy = {
inherit description;
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnActiveSec = "1";
OnUnitActiveSec = cfg.interval;
};
};
};
}