nix/profiles/backups.nix

151 lines
No EOL
4.8 KiB
Nix

{ pkgs, config, lib, name, ... }:
let
cfg = config.backups;
secrets = config.age.secrets;
postgresql = config.services.postgresql.package;
additionalPackages = [
pkgs.coreutils
pkgs.sudo
pkgs.sqlite
] ++ lib.optionals (builtins.length cfg.postgresqlDatabases > 0) [ postgresql ];
remotes = {
memoragon = {
host = "memoragon.infra.federez.net";
user = "borgmatic";
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINdqX4I1JyvhC6dySHLnW1IioYk1ZqltFlbDCygozrWx";
path = "./${name}";
};
harpagon = {
host = "harpagon.infra.federez.net";
user = "borgmatic";
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH1qDEAEJZ0qDRUq4yeHar5LKFTtsvHJIt2a54TBB/Lz";
path = "./${name}";
};
};
in
{
options.backups = lib.mkOption {
type = lib.types.submodule {
options = {
enable = lib.mkEnableOption "Sauvegardes";
directories = lib.mkOption {
type = lib.types.listOf lib.types.path;
default = [ ];
description = ''
Répertoires à sauvegarder.
'';
};
# FIXME add user ?
postgresqlDatabases = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Nom des bases de données PostgreSQL à sauvegarder.
'';
};
sqliteDatabases = lib.mkOption {
type = lib.types.attrsOf lib.types.path;
default = { };
description = ''
Chemins des bases de données SQLite à sauvegarder.
'';
};
};
};
description = ''
Configuration des sauvegardes.
'';
};
config = lib.mkIf cfg.enable {
age.secrets.borgmatic-passphrase = {
file = ../secrets/borgmatic-passphrase.age;
};
systemd.services.borgmatic = {
path = additionalPackages;
serviceConfig = {
LoadCredential = "pass:${secrets.borgmatic-passphrase.path}";
ExecStartPre = ''
${lib.getExe' pkgs.borgmatic "borgmatic"} init --encryption repokey
'';
# TODO Remove once all hosts are usign NixOS 25.05+
NoNewPrivileges = false;
CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_RAW CAP_SETUID CAP_SETGID";
};
};
environment.systemPackages =
let
# KillMode=process is required to allow the background SSH session
# to persist when FUSE mounting a remote repository
binPath = lib.makeBinPath additionalPackages;
borgmaticWithCreds = pkgs.writeScriptBin "borgmatic-with-creds" ''
#!${pkgs.runtimeShell}
systemd-run --quiet --wait --collect --pipe --pty \
--service-type=exec \
--uid=root --gid=root \
--property=KillMode=none \
--property=LoadCredential=pass:${secrets.borgmatic-passphrase.path} \
--property=Environment=${binPath} \
-- \
${lib.getExe' pkgs.borgmatic "borgmatic"} "$@"
'';
in
[ borgmaticWithCreds ];
services.openssh.knownHosts = lib.mapAttrs
(_: remote: {
hostNames = [ remote.host ];
publicKey = remote.publicKey;
})
remotes;
services.borgmatic = let
version = pkgs.borgmatic.version;
hasCredSupport = builtins.compareVersions version "1.9.10" >= 0;
encryption = if hasCredSupport then
{ encryption_passphrase = "{credential systemd pass}"; }
else
{ encryption_passcommand = "cat \${CREDENTIALS_DIRECTORY}/pass"; };
pgCommand = exe: "${lib.getExe' pkgs.sudo "sudo"} -u postgres ${lib.getExe' postgresql exe}";
in {
enable = true;
# $CREDENTIALS_DIRECTORY does not exist when the config check is run
enableConfigCheck = hasCredSupport;
settings = {
source_directories = cfg.directories;
repositories = lib.mapAttrsToList
(name: remote: {
label = name;
path = "ssh://${remote.user}@${remote.host}/${remote.path}";
})
remotes;
# Required for databases hooks
read_special = true;
# FIXME pertinent de réutiliser celle-là ?
ssh_command = "ssh -i /etc/ssh/ssh_host_ed25519_key";
keep_daily = 26;
keep_weekly = 20;
keep_monthly = 12;
# add checks
postgresql_databases = map
(name: {
inherit name;
username = "postgres";
pg_dump_command = if name == "all" then
pgCommand "pg_dumpall"
else
pgCommand "pg_dump";
pg_restore_command = pgCommand "pg_restore";
psql_command = pgCommand "psql";
})
cfg.postgresqlDatabases;
sqlite_databases = lib.mapAttrsToList
(name: path: { inherit name path; })
cfg.sqliteDatabases;
} // encryption;
};
};
}