remove restic, add borgmatic.

update template

update config template

update
This commit is contained in:
Joseph Hanson 2025-02-25 12:33:35 -06:00
parent f96ed50dfa
commit f5e45209ec
Signed by: jahanson
SSH key fingerprint: SHA256:vy6dKBECV522aPAwklFM3ReKAVB086rT3oWwiuiFG7o
15 changed files with 1697 additions and 180 deletions

View file

@ -9,10 +9,12 @@ repos:
- --config-file
- .yamllint.yaml
id: yamllint
exclude: "borgmatic-template.yaml"
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
exclude: "borgmatic-template.yaml"
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending

File diff suppressed because it is too large Load diff

View 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";
};
};
};
}

View file

@ -1,14 +1,12 @@
{
config,
lib,
pkgs,
...
}: {
services.borgmatic = {
enable = true;
mySystem.services.borgmatic = {
configurations.plex = {
source_directories = [
"/mnt/restic_nightly_backup/nahar/containers/volumes/plex/Library/"
"/nahar/containers/volumes/plex"
];
repositories = [
@ -16,14 +14,22 @@
label = "local";
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.keep_daily = 7;
retention.keep_weekly = 4;
retention.keep_monthly = 6;
keep_daily = 14;
exclude_patterns = [
"*/Cache/*"
];
zfs = {
zfs_command = "${pkgs.zfs}/bin/zfs";
mount_command = "${pkgs.util-linux}/bin/mount";

View file

@ -205,7 +205,23 @@
mode = "400";
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;
mode = "400";
restartUnits = ["borgmatic.service"];

View file

@ -260,6 +260,7 @@ in {
purpose = "Production";
# Services
services = {
borgmatic.enable = true;
# Misc
libvirt-qemu.enable = true;
podman.enable = true;
@ -435,15 +436,6 @@ in {
hardening = true;
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 = {

View file

@ -12,7 +12,12 @@ postgres:
pushover:
userKey: ENC[AES256_GCM,data:RYn9OCGaEgu/41kMolmqjYtr8FRmyEOvNStk+7Uz1A==,iv:L4pJJxGPhrmGSJdRDIP/OONibHvIP8KUdXwED29kTJ8=,tag:6TxYaUA6QA1NroBXhQHRlQ==,type:str]
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:
prowlarr:
apiKey: ENC[AES256_GCM,data:qxm2yp8ReuMgQ0155mKBAWickKusOaa/FeoIopj9l1Z3,iv:pAeDxK6CGap4fKU5xQ5hZR9It6/1uo27dKZBi5Bl3rc=,tag:HZl914AfFU4D5J7cDS3I1g==,type:str]
@ -135,8 +140,8 @@ sops:
aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M
vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-24T21:27:42Z"
mac: ENC[AES256_GCM,data:5E9adS+q+Vb45MtKDuI65GaKxb/yksqSN73ZFHYhdL+w6Lk4/WPd9n7qTENKfFkYN2qIRP3S4IQUBwobep4wiEQt4v8XdNN7gR7cgI/2u4y/iKptyv/YWyj+YYfFaZjJ6lqxod3MAq92L4xYq+91aKoWEW/ErpDy8N3xOe7GI6U=,iv:WGWCD9pfu7ijiDXhcV26j7XpFl5dVglWZeMVQFyFUSA=,tag:PP4yI+iLaaPLG0YoI19zTQ==,type:str]
lastmodified: "2025-02-25T16:50:35Z"
mac: ENC[AES256_GCM,data:OEEAQJU39Io0yfPyDZTiH0MpIZz6qtEgQLSl02ysnHm3wSoAcD2LVDGadm2nqozCZ8FrYiO1p0iP/zE/WAMB7VPjGB2fkoLgKUcjMX5RP+RHREA5eIPl9anlbXh8uAFNiw/unOH36PlqivpoYoxDoc9EqSX6df14v6+gkr/9/gM=,iv:rQfEeKvJ73dyy/mIpg2QvcV5qZHM9DpHJ7lfsHJw5q8=,tag:fdPsnuHt1/cjgjtZ5UIbtw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.4

View file

@ -20,9 +20,9 @@ with lib; rec {
user = existsOrDefault "user" options "568";
group = existsOrDefault "group" options "568";
enableBackups =
(lib.attrsets.hasAttrByPath ["persistence" "folder"] options)
&& (lib.attrsets.attrByPath ["persistence" "enable"] true options);
# enableBackups =
# (lib.attrsets.hasAttrByPath ["persistence" "folder"] options)
# && (lib.attrsets.attrByPath ["persistence" "enable"] true options);
# Security options for containers
containerExtraOptions =

View file

@ -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
# services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
# useACMEHost = config.networking.domain;

View file

@ -41,7 +41,6 @@ in {
${pkgs.podman}/bin/podman rm -f ${app} || true
rm -f /run/${app}.ctr-id
''}";
# TODO: mount /config instead of /config/Library/Application Support/Plex Media Server
ExecStart = ''
${pkgs.podman}/bin/podman run \
--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
# services.nginx.virtualHosts."${app}.${config.networking.domain}" = {
# useACMEHost = config.networking.domain;

View file

@ -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

View file

@ -77,10 +77,10 @@
# - nextcloud-remote: backs up to remote storage (e.g. S3)
lib.mySystem.mkRestic = options: let
# excludePaths is optional
excludePaths =
if builtins.hasAttr "excludePaths" options
then options.excludePaths
else [];
# excludePaths =
# if builtins.hasAttr "excludePaths" options
# then options.excludePaths
# else [];
# Decide which mutually exclusive options to use
remoteResticTemplateFile =
if builtins.hasAttr "remoteResticTemplateFile" options

View 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);
};
}

View file

@ -1,5 +1,6 @@
{
imports = [
./borgmatic
./bind
./dnsmasq
./forgejo

View file

@ -2,6 +2,7 @@
lib,
python3,
fetchFromGitHub,
installShellFiles,
}:
python3.pkgs.buildPythonApplication rec {
pname = "borgmatic";
@ -19,6 +20,8 @@ python3.pkgs.buildPythonApplication rec {
python3.pkgs.setuptools
];
nativeBuildInputs = [installShellFiles];
dependencies = with python3.pkgs; [
jsonschema
packaging
@ -36,6 +39,13 @@ python3.pkgs.buildPythonApplication rec {
"borgmatic"
];
postInstall = ''
installShellCompletion --cmd borgmatic \
--bash <($out/bin/borgmatic --bash-completion)
# installShellCompletion --cmd borgmatic \
# --fish <($out/bin/borgmatic --fish-completion | sed '20d)
'';
meta = {
description = "Simple, configuration-driven backup software for servers and workstations";
homepage = "https://github.com/borgmatic-collective/borgmatic/";