remove restic, add borgmatic.
update template update config template update
This commit is contained in:
parent
f96ed50dfa
commit
f5e45209ec
15 changed files with 1697 additions and 180 deletions
|
@ -9,10 +9,12 @@ repos:
|
||||||
- --config-file
|
- --config-file
|
||||||
- .yamllint.yaml
|
- .yamllint.yaml
|
||||||
id: yamllint
|
id: yamllint
|
||||||
|
exclude: "borgmatic-template.yaml"
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v5.0.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
|
exclude: "borgmatic-template.yaml"
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: fix-byte-order-marker
|
- id: fix-byte-order-marker
|
||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
|
|
1456
nixos/hosts/shadowfax/config/borgmatic/borgmatic-template.yaml
Normal file
1456
nixos/hosts/shadowfax/config/borgmatic/borgmatic-template.yaml
Normal file
File diff suppressed because it is too large
Load diff
40
nixos/hosts/shadowfax/config/borgmatic/jellyfin.nix
Normal file
40
nixos/hosts/shadowfax/config/borgmatic/jellyfin.nix
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
mySystem.services.borgmatic = {
|
||||||
|
configurations.jellyfin = {
|
||||||
|
source_directories = [
|
||||||
|
"/nahar/containers/volumes/jellyfin"
|
||||||
|
];
|
||||||
|
|
||||||
|
repositories = [
|
||||||
|
{
|
||||||
|
label = "local";
|
||||||
|
path = "/eru/borg/jellyfin";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
label = "remote";
|
||||||
|
path = "ssh://uy5oy4m3@uy5oy4m3.repo.borgbase.com/./repo";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
ssh_command = "${pkgs.openssh}/bin/ssh -i ${config.sops.secrets."borgmatic/jellyfin/append_key".path}";
|
||||||
|
|
||||||
|
encryption_passcommand = ''${pkgs.coreutils-full}/bin/cat ${config.sops.secrets."borgmatic/jellyfin/encryption_passphrase".path}'';
|
||||||
|
|
||||||
|
# Retention settings
|
||||||
|
keep_daily = 14;
|
||||||
|
exclude_patterns = [
|
||||||
|
"*/Cache/*"
|
||||||
|
];
|
||||||
|
|
||||||
|
zfs = {
|
||||||
|
zfs_command = "${pkgs.zfs}/bin/zfs";
|
||||||
|
mount_command = "${pkgs.util-linux}/bin/mount";
|
||||||
|
umount_command = "${pkgs.util-linux}/bin/umount";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,14 +1,12 @@
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
services.borgmatic = {
|
mySystem.services.borgmatic = {
|
||||||
enable = true;
|
|
||||||
configurations.plex = {
|
configurations.plex = {
|
||||||
source_directories = [
|
source_directories = [
|
||||||
"/mnt/restic_nightly_backup/nahar/containers/volumes/plex/Library/"
|
"/nahar/containers/volumes/plex"
|
||||||
];
|
];
|
||||||
|
|
||||||
repositories = [
|
repositories = [
|
||||||
|
@ -16,14 +14,22 @@
|
||||||
label = "local";
|
label = "local";
|
||||||
path = "/eru/borg/plex";
|
path = "/eru/borg/plex";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
label = "remote";
|
||||||
|
path = "ssh://kvq39z04@kvq39z04.repo.borgbase.com/./repo";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
storage.encryption_passcommand = ''${pkgs.coreutils-full}/bin/cat ${config.sops.secrets."borgmatic/encryption_passphrase".path}'';
|
ssh_command = "${pkgs.openssh}/bin/ssh -i ${config.sops.secrets."borgmatic/plex/append_key".path}";
|
||||||
|
|
||||||
|
encryption_passcommand = ''${pkgs.coreutils-full}/bin/cat ${config.sops.secrets."borgmatic/plex/encryption_passphrase".path}'';
|
||||||
|
|
||||||
# Retention settings
|
# Retention settings
|
||||||
retention.keep_daily = 7;
|
keep_daily = 14;
|
||||||
retention.keep_weekly = 4;
|
exclude_patterns = [
|
||||||
retention.keep_monthly = 6;
|
"*/Cache/*"
|
||||||
|
];
|
||||||
|
|
||||||
zfs = {
|
zfs = {
|
||||||
zfs_command = "${pkgs.zfs}/bin/zfs";
|
zfs_command = "${pkgs.zfs}/bin/zfs";
|
||||||
mount_command = "${pkgs.util-linux}/bin/mount";
|
mount_command = "${pkgs.util-linux}/bin/mount";
|
||||||
|
|
|
@ -205,7 +205,23 @@
|
||||||
mode = "400";
|
mode = "400";
|
||||||
restartUnits = ["unpackerr.service"];
|
restartUnits = ["unpackerr.service"];
|
||||||
};
|
};
|
||||||
"borgmatic/encryption_passphrase" = {
|
# Borgmatic
|
||||||
|
"borgmatic/plex/encryption_passphrase" = {
|
||||||
|
sopsFile = ../secrets.sops.yaml;
|
||||||
|
mode = "400";
|
||||||
|
restartUnits = ["borgmatic.service"];
|
||||||
|
};
|
||||||
|
"borgmatic/plex/append_key" = {
|
||||||
|
sopsFile = ../secrets.sops.yaml;
|
||||||
|
mode = "400";
|
||||||
|
restartUnits = ["borgmatic.service"];
|
||||||
|
};
|
||||||
|
"borgmatic/jellyfin/encryption_passphrase" = {
|
||||||
|
sopsFile = ../secrets.sops.yaml;
|
||||||
|
mode = "400";
|
||||||
|
restartUnits = ["borgmatic.service"];
|
||||||
|
};
|
||||||
|
"borgmatic/jellyfin/append_key" = {
|
||||||
sopsFile = ../secrets.sops.yaml;
|
sopsFile = ../secrets.sops.yaml;
|
||||||
mode = "400";
|
mode = "400";
|
||||||
restartUnits = ["borgmatic.service"];
|
restartUnits = ["borgmatic.service"];
|
||||||
|
|
|
@ -260,6 +260,7 @@ in {
|
||||||
purpose = "Production";
|
purpose = "Production";
|
||||||
# Services
|
# Services
|
||||||
services = {
|
services = {
|
||||||
|
borgmatic.enable = true;
|
||||||
# Misc
|
# Misc
|
||||||
libvirt-qemu.enable = true;
|
libvirt-qemu.enable = true;
|
||||||
podman.enable = true;
|
podman.enable = true;
|
||||||
|
@ -435,15 +436,6 @@ in {
|
||||||
hardening = true;
|
hardening = true;
|
||||||
qbittorrentPort = 50413;
|
qbittorrentPort = 50413;
|
||||||
};
|
};
|
||||||
# ZFS nightly snapshot of container volumes
|
|
||||||
zfs-nightly-snap = {
|
|
||||||
enable = true;
|
|
||||||
mountPath = "/mnt/restic_nightly_backup";
|
|
||||||
zfsDataset = "nahar/containers/volumes";
|
|
||||||
snapshotName = "restic_nightly_snap";
|
|
||||||
#startAt = "*-*-* 06:30:00 America/Chicago";
|
|
||||||
startAt = "*-*-* 00:10:00 America/Chicago";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
# System
|
# System
|
||||||
system = {
|
system = {
|
||||||
|
|
|
@ -12,7 +12,12 @@ postgres:
|
||||||
pushover:
|
pushover:
|
||||||
userKey: ENC[AES256_GCM,data:RYn9OCGaEgu/41kMolmqjYtr8FRmyEOvNStk+7Uz1A==,iv:L4pJJxGPhrmGSJdRDIP/OONibHvIP8KUdXwED29kTJ8=,tag:6TxYaUA6QA1NroBXhQHRlQ==,type:str]
|
userKey: ENC[AES256_GCM,data:RYn9OCGaEgu/41kMolmqjYtr8FRmyEOvNStk+7Uz1A==,iv:L4pJJxGPhrmGSJdRDIP/OONibHvIP8KUdXwED29kTJ8=,tag:6TxYaUA6QA1NroBXhQHRlQ==,type:str]
|
||||||
borgmatic:
|
borgmatic:
|
||||||
encryption_passphrase: ENC[AES256_GCM,data:Rzmb+tNo0IG6Ub3Z5pB+XahW7gtZOPs5Cjvrzw4m47q0D7bErACTzQx7VdrSJcm8+g==,iv:cQsm3MfrY4KCTvByUcQe0n51UVm/kNtTUGORx0r+wjg=,tag:j/n/4TI193ec3/mOJeB1Lg==,type:str]
|
plex:
|
||||||
|
encryption_passphrase: ENC[AES256_GCM,data:y4B7DMDgRRsz6CEL75b+uxNSrKxv/qUB2KZowbDc7PTThsbWwEyONry1QcpZgv2OIg==,iv:vh4s0/6IACrZE90KHtXh6N7LAErFqB5eiX75jjMjSm4=,tag:7v+VgyxJN/AhFQ0z/0PtCA==,type:str]
|
||||||
|
append_key: ENC[AES256_GCM,data:yV+yhmcpubOJU4o08gH/o30ZXBDlvpmj8GNFvUJS+lIq9miWENHQxcnHSdzOwnK8WRSTyiAYvYf8tpVaGDy3DPefHb3sqw7biq1+FEyh76Q9vR9XIiKMPguxRrmu8P5H2F3QJQM7us+6Qvx/xjyTvRQcSpiEATQ1iK6BAbLTbcZ96TrN+GlNUpJcAnhuMYTCzk9qxFpHap53t0jil4BVfGlDAAdWr59gLT87S3tn8YDobtX5LUp4AB8OeOgX6e24CF4LjrfrawwG1y90AoVO0AnhdM7kJ8Mq7JcJE+P0ecUUL5kc1dGdH8E5hrETmmt/iRIbuj/yzPNqrSF/R8JHtHAx0h+zqoiMk6/fjbdVPeTmzdTyLpLE4zVVRAGprdBot0jVuNsqvmJefIQISl83ox2RfbZFPsYvIlptOARI4oA+XuDC4QBiwIFVBTf6VrjsRbd1DbGbiRq6OoXmIqIt/zCEYWaVcI8srlaAHE02QbYOxCSBM2UNuTERajJ1pAJOXrRXPhwXMAT0xSv5rsAJlWzW6RkTYqUqZSqE,iv:XNUWjWEuTcA8HYkEvBuHcEunIm+/GdpOXNmAjBdeM5M=,tag:B/EoaqPXvTBN0H/UxJt5JQ==,type:str]
|
||||||
|
jellyfin:
|
||||||
|
encryption_passphrase: ENC[AES256_GCM,data:sXMIBWQpHxSyFBhvnOzkE8Qd97aWyCsd7zyVYef4WOXF,iv:qZCzQ582/myxyNDLof2RMzHtc8YeajYB1yF3KU/0DSo=,tag:3WhcEJLSxkpup6DsQqfN1Q==,type:str]
|
||||||
|
append_key: ENC[AES256_GCM,data:tgDQFEs1aCBJkWBepA921z+bb8WoLbiUAngOnQdP9vpJszBJNVlmVOPWt7hz4na+LFv4yRuGh22p7g9Dwdjd62BygicU9lc94SxOs593gZWbtgWKG95/wnxgfUTOSCGeV3JB6VjRwRh50IFwPx2DDr1bgoZqDqEJu6Mj+pUjVMCk+r8T/i79kdpryHq2gicnzHL62Deas+BmaHZremhQx4ety28qJb2WMMo7cYhUysJIal2ClOCwqeOo6OsHRGn1ZDpfxASdzXVK2qWArIcyt3XVChVv/znojaOQK9SiXQrdC4pgm8tn5OIlFH/e+f2K/EYzuShJWiOY8fbcx159OU5/OnQSNqHjBvuXulJ8WU4iMMJatOt5OqgNTK/I3e0xntnHozxVzqKSbQO0z2Ul2r4iJXAUI53oMB/iJON2fwEF1KEvW3iCmk0M1/t7AxqECsmAzfaz2lo9YNCS5iAbCYpEmRTHHMEi24/3as2mYwo4D0iKDV7J0988/BOSSXF04wVq+x7FKEOsIiuS70O1k8T75Uvw/I15DZZ2,iv:VMgaAHgipllx8V2i3hicTgxTVVmiy1AUgGICflrA254=,tag:2k9Z6wVbYVou/Vqk6f08+Q==,type:str]
|
||||||
arr:
|
arr:
|
||||||
prowlarr:
|
prowlarr:
|
||||||
apiKey: ENC[AES256_GCM,data:qxm2yp8ReuMgQ0155mKBAWickKusOaa/FeoIopj9l1Z3,iv:pAeDxK6CGap4fKU5xQ5hZR9It6/1uo27dKZBi5Bl3rc=,tag:HZl914AfFU4D5J7cDS3I1g==,type:str]
|
apiKey: ENC[AES256_GCM,data:qxm2yp8ReuMgQ0155mKBAWickKusOaa/FeoIopj9l1Z3,iv:pAeDxK6CGap4fKU5xQ5hZR9It6/1uo27dKZBi5Bl3rc=,tag:HZl914AfFU4D5J7cDS3I1g==,type:str]
|
||||||
|
@ -135,8 +140,8 @@ sops:
|
||||||
aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M
|
aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M
|
||||||
vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA==
|
vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-02-24T21:27:42Z"
|
lastmodified: "2025-02-25T16:50:35Z"
|
||||||
mac: ENC[AES256_GCM,data:5E9adS+q+Vb45MtKDuI65GaKxb/yksqSN73ZFHYhdL+w6Lk4/WPd9n7qTENKfFkYN2qIRP3S4IQUBwobep4wiEQt4v8XdNN7gR7cgI/2u4y/iKptyv/YWyj+YYfFaZjJ6lqxod3MAq92L4xYq+91aKoWEW/ErpDy8N3xOe7GI6U=,iv:WGWCD9pfu7ijiDXhcV26j7XpFl5dVglWZeMVQFyFUSA=,tag:PP4yI+iLaaPLG0YoI19zTQ==,type:str]
|
mac: ENC[AES256_GCM,data:OEEAQJU39Io0yfPyDZTiH0MpIZz6qtEgQLSl02ysnHm3wSoAcD2LVDGadm2nqozCZ8FrYiO1p0iP/zE/WAMB7VPjGB2fkoLgKUcjMX5RP+RHREA5eIPl9anlbXh8uAFNiw/unOH36PlqivpoYoxDoc9EqSX6df14v6+gkr/9/gM=,iv:rQfEeKvJ73dyy/mIpg2QvcV5qZHM9DpHJ7lfsHJw5q8=,tag:fdPsnuHt1/cjgjtZ5UIbtw==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.9.4
|
version: 3.9.4
|
||||||
|
|
|
@ -20,9 +20,9 @@ with lib; rec {
|
||||||
user = existsOrDefault "user" options "568";
|
user = existsOrDefault "user" options "568";
|
||||||
group = existsOrDefault "group" options "568";
|
group = existsOrDefault "group" options "568";
|
||||||
|
|
||||||
enableBackups =
|
# enableBackups =
|
||||||
(lib.attrsets.hasAttrByPath ["persistence" "folder"] options)
|
# (lib.attrsets.hasAttrByPath ["persistence" "folder"] options)
|
||||||
&& (lib.attrsets.attrByPath ["persistence" "enable"] true options);
|
# && (lib.attrsets.attrByPath ["persistence" "enable"] true options);
|
||||||
|
|
||||||
# Security options for containers
|
# Security options for containers
|
||||||
containerExtraOptions =
|
containerExtraOptions =
|
||||||
|
|
|
@ -88,37 +88,6 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets = {
|
|
||||||
"restic/jellyfin/env" = {
|
|
||||||
inherit group;
|
|
||||||
sopsFile = ./secrets.sops.yaml;
|
|
||||||
owner = user;
|
|
||||||
mode = "0400";
|
|
||||||
};
|
|
||||||
"restic/jellyfin/password" = {
|
|
||||||
inherit group;
|
|
||||||
sopsFile = ./secrets.sops.yaml;
|
|
||||||
owner = user;
|
|
||||||
mode = "0400";
|
|
||||||
};
|
|
||||||
"restic/jellyfin/template" = {
|
|
||||||
inherit group;
|
|
||||||
sopsFile = ./secrets.sops.yaml;
|
|
||||||
owner = user;
|
|
||||||
mode = "0400";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Restic backups for `jellyfin-local` and `jellyfin-remote`
|
|
||||||
services.restic.backups = config.lib.mySystem.mkRestic {
|
|
||||||
inherit app user;
|
|
||||||
environmentFile = config.sops.secrets."restic/jellyfin/env".path;
|
|
||||||
excludePaths = [];
|
|
||||||
localResticTemplate = "/eru/restic/jellyfin";
|
|
||||||
passwordFile = config.sops.secrets."restic/jellyfin/password".path;
|
|
||||||
paths = [volumeLocation];
|
|
||||||
remoteResticTemplateFile = config.sops.secrets."restic/jellyfin/template".path;
|
|
||||||
};
|
|
||||||
# TODO add nginx proxy
|
# TODO add nginx proxy
|
||||||
# services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
# services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
# useACMEHost = config.networking.domain;
|
# useACMEHost = config.networking.domain;
|
||||||
|
|
|
@ -41,7 +41,6 @@ in {
|
||||||
${pkgs.podman}/bin/podman rm -f ${app} || true
|
${pkgs.podman}/bin/podman rm -f ${app} || true
|
||||||
rm -f /run/${app}.ctr-id
|
rm -f /run/${app}.ctr-id
|
||||||
''}";
|
''}";
|
||||||
# TODO: mount /config instead of /config/Library/Application Support/Plex Media Server
|
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.podman}/bin/podman run \
|
${pkgs.podman}/bin/podman run \
|
||||||
--rm \
|
--rm \
|
||||||
|
@ -80,38 +79,6 @@ in {
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets = {
|
|
||||||
"restic/plex/env" = {
|
|
||||||
inherit group;
|
|
||||||
sopsFile = ./secrets.sops.yaml;
|
|
||||||
owner = user;
|
|
||||||
mode = "0400";
|
|
||||||
};
|
|
||||||
"restic/plex/password" = {
|
|
||||||
inherit group;
|
|
||||||
sopsFile = ./secrets.sops.yaml;
|
|
||||||
owner = user;
|
|
||||||
mode = "0400";
|
|
||||||
};
|
|
||||||
"restic/plex/template" = {
|
|
||||||
inherit group;
|
|
||||||
sopsFile = ./secrets.sops.yaml;
|
|
||||||
owner = user;
|
|
||||||
mode = "0400";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Restic backups for `plex-local` and `plex-remote`
|
|
||||||
services.restic.backups = config.lib.mySystem.mkRestic {
|
|
||||||
inherit app user;
|
|
||||||
environmentFile = config.sops.secrets."restic/plex/env".path;
|
|
||||||
excludePaths = ["${volumeLocation}/Library/Application Support/Plex Media Server/Cache"];
|
|
||||||
localResticTemplate = "/eru/restic/plex";
|
|
||||||
passwordFile = config.sops.secrets."restic/plex/password".path;
|
|
||||||
paths = ["${volumeLocation}/Library"];
|
|
||||||
remoteResticTemplateFile = config.sops.secrets."restic/plex/template".path;
|
|
||||||
};
|
|
||||||
|
|
||||||
# TODO add nginx proxy
|
# TODO add nginx proxy
|
||||||
# services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
# services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
|
||||||
# useACMEHost = config.networking.domain;
|
# useACMEHost = config.networking.domain;
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
restic:
|
|
||||||
plex:
|
|
||||||
env: ENC[AES256_GCM,data:FwBQ9TJTiDGDEyrJkHo=,iv:pxqdwOPoxYAc+yY2xdNTi08jFNz+PvnZ9HYhmchEfiM=,tag:3uIPLUoZmDogmuShXqnAlw==,type:str]
|
|
||||||
password: ENC[AES256_GCM,data:79FMf5T1gYQX0PYTiEUhPQnHbEIekmH2vJxqwhdCw1MpoA==,iv:n3cQ4cLoEKw7rbCgysc14CMmKtYUfhZW2I6V3qrFp3Q=,tag:ooNflv+TnUOD0JX6NAqxvQ==,type:str]
|
|
||||||
template: ENC[AES256_GCM,data:br+HPd37B3rWYPLIYW8MiIHvR+PmsnBXEYLh8MT/v1rbcNH6ppyhwGMgP1kPkUX3o/0Y7PkW1pet5DRHcKUVnXpi,iv:O4MQQBpYCD8hkdTEroUn9+luUdCyz7MYUugjaYhF3Uc=,tag:db5DQBfPGX9ToQzwn1K7GA==,type:str]
|
|
||||||
sops:
|
|
||||||
kms: []
|
|
||||||
gcp_kms: []
|
|
||||||
azure_kv: []
|
|
||||||
hc_vault: []
|
|
||||||
age:
|
|
||||||
- recipient: age1d9p83j52m2xg0vh9k7q0uwlxwhs3y6tlv68yg9s2h9mdw2fmmsqshddz5m
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCbSs2TFBpbW51aThtcEJL
|
|
||||||
eW80aG50VHJzcWVFSDlTbE40dHZqTnVpWDFBCkUwNVIrZkdyd1dKcjFzMENFdTN5
|
|
||||||
dVBZKzVIYnFJdnkzTlRCT2hITTVsSzgKLS0tIFREVWJENUtoWGR1THlwWXNNV3p4
|
|
||||||
cElGSzFtallzc2xBajRYSGNvOHJnM3cKIdyVG7MySM9caGUXaiTSsz1VVlD7GxRz
|
|
||||||
+5NNPoZgfe1SiptiQl3vO8FcIg5XtutI2nwYqLK5gzxZ7x6+D2Oedw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1m83ups8xn2jy4ayr8gw0pyn34smr0huqc5v76e4887az4vsl4yzsj0dlhd
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3dFAxT3ZCZ1BlV2VSQmlr
|
|
||||||
cW9SbWpLRUE4QlNGN21YdGM2NXhGdm1kVmlZClBORG5Mbmtaait4WXZiYkp3cGxR
|
|
||||||
WGFWT3NwaS9RK0IzN1FDR3ZWUjIyQVkKLS0tIDJYaVRORk94UXYySStUN0lJYlB5
|
|
||||||
L01LdFBzYUhmcENPMGIrYWU0dW91c2sKlraBMZ30AerY2YrGnV1pkeL6xJIGUPlX
|
|
||||||
JzjzPmkvqidCaT+gADxM9xTp9S5ZavLn0sGLapqfx2P7pDndRh74Qg==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age18kj3xhlvgjeg2awwku3r8d95w360uysu0w5ejghnp4kh8qmtge5qwa2vjp
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtanl6bWlrQlM2R1Bud0dk
|
|
||||||
cWJZdjJZUFVMY3BudEdRVVFOMy9IMTNGS1NzCnZHNXYzRVl5akFDYlNWVXZtMzNL
|
|
||||||
UnZEN3ZFUDB6b05Wa3lSc291WXVVeGMKLS0tIGk5ZTJ6d3A4M3ZqTm9KSjVudVBX
|
|
||||||
TzNNemlGc1JOckxERUx5V3VCbHBIZlkK+7+PJhU+4hnOiURvfhQOMh3Njl5E8OCj
|
|
||||||
CCH5feYLIOpfgEKQbhW8LFkakoqlU5ASdralMRq5h4OZt8hGciYgwg==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1lp6rrlvmytp9ka6q89m0e0am26222kwrn7aqd45hu07s3a6jv3gqty86eu
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3VFovdW1UbjlLZnRFZWZh
|
|
||||||
MUg0RkZqckcxcENRSG5aSkdQNkoraXFTbTNrCnlYWWVOdHVxYUwwaWYvOS8xaG9y
|
|
||||||
eS9za000VmR0T0ZZeHp5RXl0c1FUZDgKLS0tIERjY0hrdDlQb29UWC8ybDgwdXQy
|
|
||||||
WEVNVjBYV3RUZUN2SksvWDlzYnJydWcKEzXYhd0GUZNDdQcJ1lc5Ci4TAebQHzdd
|
|
||||||
Nyrf7Xhgb/vNoScFAvLxpJaEP9aJzWOL7wVHgnzFdf9ViRGF0yynnw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1e4sd6jjd4uxxsh9xmhdsnu6mqd5h8c4zz4gwme7lkw9ee949fc9q4px9df
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwU3JKelJlUUZxRi90RmRP
|
|
||||||
VUpoYXZaQlZpaEZiL3orb2Rva3U4TkZ2TDBVCmpwQXFtUHlicHh0S2h3TUN0U2dE
|
|
||||||
MXIrcUdhbWZLdFdhRnB1YkhDL2JkV3cKLS0tIFdCZWVmMytST3dHVG5LL1duckRj
|
|
||||||
alZDNkYxVnljUk9Gc25vVElPL0RXSDQKM84i+oIeivQFSIDBhT9Gg3XHk8GFRbzO
|
|
||||||
IwUrRIkj+yDKepz+r2Lc+yD2BOeFo+CNuReoJd2SGou7e628VysB4g==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age19jm7uuam7gkacm3kh2v7uqgkvmmx0slmm9zwdjhd2ln9r60xzd7qh78c5a
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzRE5UbGxUenRZVjU2NVF6
|
|
||||||
RHNUOXJ5bnJmdm13YTNKV1YwdFdJS3JpMTBrCkRNQWNiMXp4SHZ6bGdJay9pYjgr
|
|
||||||
UW1CSVRNMFFWNjA5YSttTHBGTWpCcE0KLS0tIDBUV25tdUZHbHpIb3Y1U281dGtl
|
|
||||||
bUNHazJDUnEwc015WXlybTdEK1RHL1UKZE/5YGvUN2tR1t7s/Lq1jG3FoMIOmKDK
|
|
||||||
GXwUQb1HG7PDG9V/pKWs9OVoFxv7qVuuBm29rRnI44pEERARtbs55Q==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1nwnqxjuaxlt5g7fe8rnspvn2c36uuef4hzwuwa6cfjfalz2lrd4q4n5fpl
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBWHBEUDNuRDhVMmp4QUYr
|
|
||||||
cCtmZ2RMWVFNWVhVck44U3ROTE8xNm9kV0Y4CktSelh0ckdQZHNTVnVsVXJweUly
|
|
||||||
UmphNzRJU3JOSThQVXB3ZXRlY3BOK1UKLS0tIG1nT09WUm1YcVFJRHZyWFJOKzZx
|
|
||||||
OTFDbExmeXBBWmRjSE5BUnpGY0xLRjAKnLWKZEmlI9SsfZgus7tuCOFzokDobz8F
|
|
||||||
s7zQ078Dv7R55EPoYPfq8rsMvFpELrAqrNLAR9x4W5YledBDJV8s+A==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1a8z3p24v32l9yxm5z2l8h7rpc3nhacyfv4jvetk2lenrvsdstd3sdu2kaf
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNRSttM1NDdFJib2FleTY0
|
|
||||||
UnkrUFhBUFlWNkxEZUNLMjVTUWh4VkhPbkY4CllRY3d0ZXpGRkM0ZG45TVE5SGx3
|
|
||||||
ek9BNW9SUGVLZjRiSkVlT2MrSU85VGsKLS0tIEtlcklOOXZldUJwZmVDaWhNeFh2
|
|
||||||
RDgrMDlLVm9rN2JRZ3gxSCtxOWlhWkEKkXtZtmXnRn1ukRI4CkjkYefyGOuCw+GC
|
|
||||||
HCKKdsASQm4JjcnlUbkL97bC0H+VcLNqHm6NR9dghI9IYuYAeLqMNA==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2024-12-27T09:27:41Z"
|
|
||||||
mac: ENC[AES256_GCM,data:OU23F2vdLKE2aas9xUsx5cmObBmdqybXSfdUT+BGd/mdhThF6vNR3Xwo4PcaK8VPmQ8JmXjOUJ/A9vKvcgz1LuEywgAacayDf6TUu1yXPDm09wFwWGTAYugy2Z54a0VQ8u7Cu/4Ijx0hU0luaYsbCyr7FmKgeO+H+L47JKnrPp8=,iv:dowA2KQqSjNIoPq1A0Yv9g71FSJgey5mMQMuJJMSSWA=,tag:eJrk49soG6dA8UilhuKGaw==,type:str]
|
|
||||||
pgp: []
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.9.1
|
|
|
@ -77,10 +77,10 @@
|
||||||
# - nextcloud-remote: backs up to remote storage (e.g. S3)
|
# - nextcloud-remote: backs up to remote storage (e.g. S3)
|
||||||
lib.mySystem.mkRestic = options: let
|
lib.mySystem.mkRestic = options: let
|
||||||
# excludePaths is optional
|
# excludePaths is optional
|
||||||
excludePaths =
|
# excludePaths =
|
||||||
if builtins.hasAttr "excludePaths" options
|
# if builtins.hasAttr "excludePaths" options
|
||||||
then options.excludePaths
|
# then options.excludePaths
|
||||||
else [];
|
# else [];
|
||||||
# Decide which mutually exclusive options to use
|
# Decide which mutually exclusive options to use
|
||||||
remoteResticTemplateFile =
|
remoteResticTemplateFile =
|
||||||
if builtins.hasAttr "remoteResticTemplateFile" options
|
if builtins.hasAttr "remoteResticTemplateFile" options
|
||||||
|
|
141
nixos/modules/nixos/services/borgmatic/default.nix
Normal file
141
nixos/modules/nixos/services/borgmatic/default.nix
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
myPkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.mySystem.services.borgmatic;
|
||||||
|
settingsFormat = pkgs.formats.yaml {};
|
||||||
|
|
||||||
|
repository = with types;
|
||||||
|
submodule {
|
||||||
|
options = {
|
||||||
|
path = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = ''
|
||||||
|
Path to the repository
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
label = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = ''
|
||||||
|
Label to the repository
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
cfgType = with types;
|
||||||
|
submodule {
|
||||||
|
freeformType = settingsFormat.type;
|
||||||
|
options = {
|
||||||
|
source_directories = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
List of source directories and files to backup. Globs and tildes are
|
||||||
|
expanded. Do not backslash spaces in path names.
|
||||||
|
'';
|
||||||
|
example = [
|
||||||
|
"/home"
|
||||||
|
"/etc"
|
||||||
|
"/var/log/syslog*"
|
||||||
|
"/home/user/path with spaces"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
repositories = mkOption {
|
||||||
|
type = listOf repository;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
A required list of local or remote repositories with paths and
|
||||||
|
optional labels (which can be used with the --repository flag to
|
||||||
|
select a repository). Tildes are expanded. Multiple repositories are
|
||||||
|
backed up to in sequence. Borg placeholders can be used. See the
|
||||||
|
output of "borg help placeholders" for details. See ssh_command for
|
||||||
|
SSH options like identity file or port. If systemd service is used,
|
||||||
|
then add local repository paths in the systemd service file to the
|
||||||
|
ReadWritePaths list.
|
||||||
|
'';
|
||||||
|
example = [
|
||||||
|
{
|
||||||
|
path = "ssh://user@backupserver/./sourcehostname.borg";
|
||||||
|
label = "backupserver";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
path = "/mnt/backup";
|
||||||
|
label = "local";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cfgfile = settingsFormat.generate "config.yaml" cfg.settings;
|
||||||
|
in {
|
||||||
|
options.mySystem.services.borgmatic = {
|
||||||
|
enable = mkEnableOption "borgmatic";
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
description = ''
|
||||||
|
See https://torsion.org/borgmatic/docs/reference/configuration/
|
||||||
|
'';
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr cfgType;
|
||||||
|
};
|
||||||
|
|
||||||
|
configurations = mkOption {
|
||||||
|
description = ''
|
||||||
|
Set of borgmatic configurations, see https://torsion.org/borgmatic/docs/reference/configuration/
|
||||||
|
'';
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf cfgType;
|
||||||
|
};
|
||||||
|
|
||||||
|
enableConfigCheck =
|
||||||
|
mkEnableOption "checking all configurations during build time"
|
||||||
|
// {
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = let
|
||||||
|
configFiles =
|
||||||
|
(optionalAttrs (cfg.settings != null) {"borgmatic/config.yaml".source = cfgfile;})
|
||||||
|
// mapAttrs' (
|
||||||
|
name: value:
|
||||||
|
nameValuePair "borgmatic.d/${name}.yaml" {source = settingsFormat.generate "${name}.yaml" value;}
|
||||||
|
)
|
||||||
|
cfg.configurations;
|
||||||
|
borgmaticCheck = name: f:
|
||||||
|
pkgs.runCommandCC "${name} validation" {} ''
|
||||||
|
${myPkgs.borgmatic}/bin/borgmatic -c ${f.source} config validate
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
mkIf cfg.enable {
|
||||||
|
warnings =
|
||||||
|
[]
|
||||||
|
++ optional (cfg.settings != null && cfg.settings ? location)
|
||||||
|
"`services.borgmatic.settings.location` is deprecated, please move your options out of sections to the global scope"
|
||||||
|
++ optional (catAttrs "location" (attrValues cfg.configurations) != [])
|
||||||
|
"`services.borgmatic.configurations.<name>.location` is deprecated, please move your options out of sections to the global scope";
|
||||||
|
|
||||||
|
environment.systemPackages = [
|
||||||
|
myPkgs.borgmatic
|
||||||
|
pkgs.borgbackup
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.etc = configFiles;
|
||||||
|
|
||||||
|
systemd.packages = [
|
||||||
|
myPkgs.borgmatic
|
||||||
|
pkgs.borgbackup
|
||||||
|
];
|
||||||
|
|
||||||
|
# Workaround: https://github.com/NixOS/nixpkgs/issues/81138
|
||||||
|
systemd.timers.borgmatic.wantedBy = ["timers.target"];
|
||||||
|
|
||||||
|
system.checks = mkIf cfg.enableConfigCheck (mapAttrsToList borgmaticCheck configFiles);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./borgmatic
|
||||||
./bind
|
./bind
|
||||||
./dnsmasq
|
./dnsmasq
|
||||||
./forgejo
|
./forgejo
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
lib,
|
lib,
|
||||||
python3,
|
python3,
|
||||||
fetchFromGitHub,
|
fetchFromGitHub,
|
||||||
|
installShellFiles,
|
||||||
}:
|
}:
|
||||||
python3.pkgs.buildPythonApplication rec {
|
python3.pkgs.buildPythonApplication rec {
|
||||||
pname = "borgmatic";
|
pname = "borgmatic";
|
||||||
|
@ -19,6 +20,8 @@ python3.pkgs.buildPythonApplication rec {
|
||||||
python3.pkgs.setuptools
|
python3.pkgs.setuptools
|
||||||
];
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = [installShellFiles];
|
||||||
|
|
||||||
dependencies = with python3.pkgs; [
|
dependencies = with python3.pkgs; [
|
||||||
jsonschema
|
jsonschema
|
||||||
packaging
|
packaging
|
||||||
|
@ -36,6 +39,13 @@ python3.pkgs.buildPythonApplication rec {
|
||||||
"borgmatic"
|
"borgmatic"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
installShellCompletion --cmd borgmatic \
|
||||||
|
--bash <($out/bin/borgmatic --bash-completion)
|
||||||
|
# installShellCompletion --cmd borgmatic \
|
||||||
|
# --fish <($out/bin/borgmatic --fish-completion | sed '20d)
|
||||||
|
'';
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "Simple, configuration-driven backup software for servers and workstations";
|
description = "Simple, configuration-driven backup software for servers and workstations";
|
||||||
homepage = "https://github.com/borgmatic-collective/borgmatic/";
|
homepage = "https://github.com/borgmatic-collective/borgmatic/";
|
||||||
|
|
Loading…
Add table
Reference in a new issue