config/modules/services/deployerbot/default.nix

144 lines
4.7 KiB
Nix

{
config,
lib,
pkgs,
...
}: {
options.mj.services.deployerbot.main = with lib.types; {
enable = lib.mkEnableOption "Enable system updater orchestrator";
deployDerivations = lib.mkOption {type = listOf str;};
deployIfPresent = lib.mkOption {
type = listOf (submodule {
options = {
derivationTarget = lib.mkOption {type = str;};
pingTarget = lib.mkOption {type = str;};
};
});
default = [];
};
uidgid = lib.mkOption {type = int;};
repo = lib.mkOption {type = str;};
};
options.mj.services.deployerbot.follower = with lib.types; {
enable = lib.mkEnableOption "Allow system to be deployed with deployerbot";
sshAllowSubnets = lib.mkOption {type = listOf str;};
publicKey = lib.mkOption {type = str;};
uidgid = lib.mkOption {type = int;};
};
config = lib.mkMerge [
(let
cfg = config.mj.services.deployerbot.main;
in
lib.mkIf cfg.enable {
# TODO: git config --global user.email bot@jakstys.lt
users.users.deployerbot-main = {
description = "Deployerbot Main";
home = "/var/lib/deployerbot-main";
shell = "/bin/sh";
group = "deployerbot-main";
isSystemUser = true;
createHome = true;
uid = cfg.uidgid;
};
users.groups.deployerbot-main.gid = cfg.uidgid;
systemd.services.deployerbot = {
description = "Update all known systems";
environment = {TZ = "UTC";};
path = [pkgs.git pkgs.openssh pkgs.nix];
restartIfChanged = false;
serviceConfig = {
Type = "oneshot";
User = "deployerbot-main";
WorkingDirectory = config.users.users.deployerbot-main.home;
LoadCredential = ["ssh-key:/etc/ssh/ssh_host_ed25519_key"];
};
script = let
deployDerivationsStr = builtins.concatStringsSep " " cfg.deployDerivations;
in ''
set -xeuo pipefail
export GIT_SSH_COMMAND="ssh -i ''${CREDENTIALS_DIRECTORY}/ssh-key"
if [[ ! -d config ]]; then
git clone ${cfg.repo} config
cd config
else
cd config
git fetch origin
git reset --hard origin/main
fi
nix flake update --accept-flake-config --commit-lock-file
# TODO --all-systems
nix flake check --accept-flake-config
EXITCODE=0
${pkgs.deploy-rs.deploy-rs}/bin/deploy \
--ssh-opts="-i ''${CREDENTIALS_DIRECTORY}/ssh-key" \
--ssh-user=deployerbot-follower \
--confirm-timeout 60 \
--skip-checks \
--targets ${deployDerivationsStr} -- \
--accept-flake-config || EXITCODE=1
if [[ $EXITCODE != 0 ]]; then
git push origin main
fi
# Optional deployments
${lib.concatLines (map ({
derivationTarget,
pingTarget,
}: ''
if ${pkgs.inetutils}/bin/ping -c 1 ${pingTarget}; then
${pkgs.deploy-rs.deploy-rs}/bin/deploy \
--ssh-opts="-i ''${CREDENTIALS_DIRECTORY}/ssh-key" \
--ssh-user=deployerbot-follower \
--confirm-timeout 60 \
--skip-checks \
--targets ${derivationTarget} -- \
--accept-flake-config || EXITCODE=1
fi
'')
cfg.deployIfPresent)}
exit $EXITCODE
'';
};
systemd.timers.deployerbot = {
description = "deployerbot-main timer";
wantedBy = ["timers.target"];
timerConfig.OnCalendar = "*-*-* 23:30:00 UTC";
};
mj.base.unitstatus.units = ["deployerbot"];
nix.settings.trusted-users = ["deployerbot-main"];
})
(let
cfg = config.mj.services.deployerbot.follower;
in
lib.mkIf cfg.enable {
users.users.deployerbot-follower = {
description = "Deployerbot Follower";
home = "/var/lib/deployerbot-follower";
shell = "/bin/sh";
group = "deployerbot-follower";
extraGroups = ["wheel"];
isSystemUser = true;
createHome = true;
uid = cfg.uidgid;
openssh.authorizedKeys.keys = let
restrictedPubKey = "from=\"${builtins.concatStringsSep "," cfg.sshAllowSubnets}\" " + cfg.publicKey;
in [restrictedPubKey];
};
users.groups.deployerbot-follower.gid = cfg.uidgid;
nix.settings.trusted-users = ["deployerbot-follower"];
})
];
}