diff --git a/flake.nix b/flake.nix index 32d093f..e3a750c 100644 --- a/flake.nix +++ b/flake.nix @@ -101,8 +101,10 @@ }; flake.nixosModules = { + k8s-gitlab-borg = import ./k8s-gitlab-borg.nix; + default = {config, ...}: { - imports = with self.nixosModules; []; + imports = with self.nixosModules; [k8s-gitlab-borg]; config.nixpkgs.overlays = [self.overlays.default]; }; diff --git a/k8s-gitlab-borg.nix b/k8s-gitlab-borg.nix new file mode 100644 index 0000000..9ef0492 --- /dev/null +++ b/k8s-gitlab-borg.nix @@ -0,0 +1,134 @@ +# SPDX-FileCopyrightText: 2023 Gregor Kleen +# +# SPDX-License-Identifier: GPL-3.0-or-later +{ + config, + pkgs, + lib, + flakeInputs, + hostName, + ... +}: +with lib; let + cfg = config.services.k8s-gitlab-borg; + + toml = pkgs.formats.toml {}; +in { + options = { + services.k8s-gitlab-borg = { + enable = mkEnableOption "k8s-gitlab-borg service"; + + package = mkOption { + type = types.package; + default = pkgs.k8s-gitlab-borg; + defaultText = "pkgs.k8s-gitlab-borg"; + }; + + execInterval = mkOption { + type = types.str; + default = "*-*-* *:00"; + }; + + target = mkOption { + type = types.str; + }; + + archive-prefix = mkOption { + type = types.str; + default = "${config.networking.hostName}.gitlab."; + defaultText = '' + "''${config.networking.hostName}.gitlab." + ''; + }; + + verbosity = mkOption { + type = types.int; + default = 2; + }; + + sshConfig = mkOption { + type = with types; nullOr str; + default = null; + }; + + keyfile = mkOption { + type = with types; nullOr str; + default = null; + }; + + unknownUnencryptedRepoAccessOk = mkOption { + type = types.bool; + default = false; + }; + hostnameIsUnique = mkOption { + type = types.bool; + default = true; + }; + borgBaseDir = mkOption { + type = types.nullOr types.str; + default = "/var/lib/borg"; + }; + + config = mkOption { + type = toml.type; + default = {}; + }; + + extraArgs = mkOption { + type = with types; listOf str; + default = []; + }; + }; + }; + + config = mkIf cfg.enable { + services.k8s-gitlab-borg.config = { + k8s-gitlab-borg.timezone = mkIf (config.time.timeZone != null) config.time.timeZone; + + keep."4h".count = 6; + keep.daily.count = 7; + + copy.daily.count = 1; + }; + + systemd.services."k8s-gitlab-borg" = { + description = "Copy GitLab backups to borg"; + after = optional config.services.k3s.enable "k3s.service"; + bindsTo = optional config.services.k3s.enable "k3s.service"; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${cfg.package}/bin/k8s-gitlab-borg ${escapeShellArgs ([ + "--verbosity=${toString cfg.verbosity}" + "--target=${cfg.target}" + "--archive-prefix=${cfg.archive-prefix}" + (toml.generate "k8s-gitlab-borg.toml" cfg.config) + ] + ++ cfg.extraArgs)}"; + + LogRateLimitIntervalSec = 0; + Environment = + optionals (!(isNull cfg.borgBaseDir)) [ + "BORG_BASE_DIR=${cfg.borgBaseDir}" + "BORG_CONFIG_DIR=${cfg.borgBaseDir}/config" + "BORG_CACHE_DIR=${cfg.borgBaseDir}/cache" + "BORG_SECURITY_DIR=${cfg.borgBaseDir}/security" + "BORG_KEYS_DIR=${cfg.borgBaseDir}/keys" + ] + ++ optional cfg.unknownUnencryptedRepoAccessOk "BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes" + ++ optional cfg.hostnameIsUnique "BORG_HOSTNAME_IS_UNIQUE=yes" + ++ optional (!(isNull cfg.sshConfig)) "BORG_RSH=\"${pkgs.openssh}/bin/ssh -F ${pkgs.writeText "config" cfg.sshConfig}\"" + ++ optional (!(isNull cfg.keyfile)) "BORG_KEY_FILE=${cfg.keyfile}"; + + LoadCredential = optional config.services.k3s.enable "k8s.yaml:/etc/rancher/k3s/k3s.yaml"; + }; + }; + systemd.timers."k8s-gitlab-borg" = { + wantedBy = ["timers.target"]; + timerConfig = { + OnCalendar = cfg.execInterval; + Persistent = true; + }; + }; + }; +}