From 80ef71e9958d0effe0ea1e1fb39b7200e02eff70 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Thu, 16 Dec 2021 19:49:23 -0500 Subject: feat(ops/auto-deploy): Support auto-deploy Automatically rebuild the current system's NixOS config from the latest checkout of depot. Change-Id: I23aa7af50e16e985ac34df214e0905e770316e5e Reviewed-on: https://cl.tvl.fyi/c/depot/+/4390 Reviewed-by: wpcarro Reviewed-by: zseri Reviewed-by: grfn Autosubmit: wpcarro Tested-by: BuildkiteCI --- ops/modules/auto-deploy.nix | 92 +++++++++++++++++++++++++++++++++++++++++ ops/modules/default-imports.nix | 1 + 2 files changed, 93 insertions(+) create mode 100644 ops/modules/auto-deploy.nix (limited to 'ops/modules') diff --git a/ops/modules/auto-deploy.nix b/ops/modules/auto-deploy.nix new file mode 100644 index 000000000000..8ffc0afbc695 --- /dev/null +++ b/ops/modules/auto-deploy.nix @@ -0,0 +1,92 @@ +# Defines a service for automatically and periodically calling depot's +# rebuild-system on a NixOS machine. +{ 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 + + 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 = [ + pkgs.bash + pkgs.git + ]; + 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; + }; + }; + }; +} diff --git a/ops/modules/default-imports.nix b/ops/modules/default-imports.nix index acd70bd05f01..11514a437a42 100644 --- a/ops/modules/default-imports.nix +++ b/ops/modules/default-imports.nix @@ -8,6 +8,7 @@ { imports = [ ./automatic-gc.nix + ./auto-deploy.nix ./tvl-cache.nix ]; } -- cgit 1.4.1