Remove btrbk, add btrfs-backup and use btrbk ssh key for it
This commit is contained in:
parent
a57c99e31e
commit
e6aab76104
6 changed files with 45 additions and 109 deletions
nixos
common
hosts/nuc-server
secrets
|
@ -1,63 +0,0 @@
|
|||
{ hostname, pkgs, ... }: {
|
||||
|
||||
sops.secrets."btrbk/ssh_key" = {
|
||||
sopsFile = ../../../secrets/secrets.yaml;
|
||||
owner = "btrbk";
|
||||
group = "btrbk";
|
||||
};
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
extraRules = [
|
||||
{
|
||||
commands = [
|
||||
{
|
||||
command = "${pkgs.coreutils-full}/bin/test";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
{
|
||||
command = "${pkgs.coreutils-full}/bin/readlink";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
{
|
||||
command = "${pkgs.btrfs-progs}/bin/btrfs";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
];
|
||||
users = [ "btrbk" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Ensure the btrbk snapshot folders are created since btrbk won't do it automatically:
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /.snapshots/btrbk 0755 btrbk btrbk"
|
||||
"d /nix/.snapshots/btrbk 0755 btrbk btrbk"
|
||||
];
|
||||
|
||||
# More info: https://github.com/digint/btrbk/blob/master/btrbk.conf.example
|
||||
# More info: https://digint.ch/btrbk/doc/btrbk.conf.5.html#_btrfs_specific_options
|
||||
services.btrbk = {
|
||||
instances."synology" = {
|
||||
onCalendar = "daily";
|
||||
settings = {
|
||||
snapshot_create = "ondemand";
|
||||
incremental_resolve = "directory";
|
||||
snapshot_preserve_min = "7d";
|
||||
snapshot_preserve = "7d 4w 6m";
|
||||
target_preserve_min = "7d";
|
||||
target_preserve = "7d 4w 6m";
|
||||
ssh_identity = "/run/secrets/btrbk/ssh_key";
|
||||
ssh_user = "root";
|
||||
stream_compress = "gzip";
|
||||
volume."/" = {
|
||||
target = "ssh://synology/volume1/btrbk/hosts/${hostname}";
|
||||
subvolume = {
|
||||
"/" = { snapshot_dir = "/.snapshots/btrbk"; };
|
||||
"/nix" = { snapshot_dir = "/nix/.snapshots/btrbk"; };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,5 +1,22 @@
|
|||
{ lib, pkgs, desktop, ... }: {
|
||||
environment.systemPackages = [ pkgs.snapper ] ++ lib.optional (builtins.isString desktop) pkgs.btrfs-assistant;
|
||||
{ lib, pkgs, desktop, ... }:
|
||||
let
|
||||
btrfs-backup = pkgs.writeScriptBin "btrfs-backup" "${builtins.readFile ../software/cli/scripts/btrfs-backup.sh}";
|
||||
in {
|
||||
environment.systemPackages = [
|
||||
pkgs.snapper
|
||||
btrfs-backup
|
||||
] ++ lib.optional (builtins.isString desktop) pkgs.btrfs-assistant;
|
||||
|
||||
# SSH key for btrfs-backups
|
||||
sops.secrets."btrfs-backups/ssh_key" = {
|
||||
sopsFile = ../../../../secrets/secrets.yaml;
|
||||
owner = "root";
|
||||
};
|
||||
|
||||
sops.secrets."btrfs-backups/gotify_token" = {
|
||||
owner = "root";
|
||||
sopsFile = ../../../../secrets/secrets.yaml;
|
||||
};
|
||||
|
||||
services.snapper = {
|
||||
snapshotRootOnBoot = true;
|
||||
|
@ -8,7 +25,8 @@
|
|||
configs = {
|
||||
root = {
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
NUMBER_LIMIT = 10; # snapshotRootOnBoot cleanup
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
TIMELINE_LIMIT_QUARTERLY = 2;
|
||||
TIMELINE_LIMIT_MONTHLY = 3;
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
clean-hm = pkgs.writeScriptBin "clean-hm" "${builtins.readFile ./scripts/clean-hm.sh}";
|
||||
btrfs-backup = pkgs.writeScriptBin "btrfs-backup" "${builtins.readFile ./scripts/btrfs-backup.sh}";
|
||||
clean-hm = pkgs.writeScriptBin "clean-hm" "${builtins.readFile ./scripts/clean-hm.sh}";
|
||||
in {
|
||||
environment.systemPackages = [
|
||||
clean-hm
|
||||
btrfs-backup
|
||||
];
|
||||
|
||||
sops.secrets."btrfs-backups/gotify_token" = {
|
||||
owner = "albert";
|
||||
sopsFile = ../../../../secrets/secrets.yaml;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# - snapper
|
||||
# - btrfs-progs
|
||||
# - pv
|
||||
# - ssh (configured for remote access)
|
||||
# - ssh configured for remote access)
|
||||
# - curl (for Gotify notifications)
|
||||
#
|
||||
# Usage: ./script.sh SNAPPER_CONFIG
|
||||
|
@ -26,7 +26,7 @@ set -eE
|
|||
if ! command -v snapper >/dev/null 2>&1 || \
|
||||
! command -v btrfs >/dev/null 2>&1 || \
|
||||
! command -v pv >/dev/null 2>&1 || \
|
||||
! command -v ssh >/dev/null 2>&1 || \
|
||||
! command -v ssh >/dev/null 2>&1 || \
|
||||
! command -v curl >/dev/null 2>&1; then
|
||||
echo "ERROR: Missing required dependencies. Please ensure snapper, btrfs-progs, pv, ssh, and curl are installed."
|
||||
exit 1
|
||||
|
@ -224,7 +224,7 @@ verify_snapshot() {
|
|||
|
||||
# Function to verify remote connectivity
|
||||
verify_remote() {
|
||||
if ! ssh -q "$REMOTE_HOST" "exit"; then
|
||||
if ! ssh -i /run/secrets/btrfs-backup/ssh_key -q "$REMOTE_HOST" "exit"; then
|
||||
send_notification "Backup Failed" "Cannot connect to remote host from $HOSTNME" 8
|
||||
log "ERROR: Cannot connect to remote host"
|
||||
exit 1
|
||||
|
@ -233,7 +233,7 @@ verify_remote() {
|
|||
|
||||
# Function to get remote snapshots
|
||||
get_remote_snapshots() {
|
||||
ssh "$REMOTE_HOST" "find '$BASE_DEST_PATH' -maxdepth 1 -type d -name '[0-9]*' | sort -n"
|
||||
ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "find '$BASE_DEST_PATH' -maxdepth 1 -type d -name '[0-9]*' | sort -n"
|
||||
}
|
||||
|
||||
# Function to get local backup snapshots
|
||||
|
@ -255,13 +255,13 @@ cleanup_snapshots() {
|
|||
local snapshot="${local_snapshots[$i]}"
|
||||
|
||||
# Delete remote snapshot first
|
||||
if ssh "$REMOTE_HOST" "[ -d '$BASE_DEST_PATH/$snapshot' ]"; then
|
||||
if ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "[ -d '$BASE_DEST_PATH/$snapshot' ]"; then
|
||||
log "Deleting remote snapshot: $snapshot"
|
||||
if ! ssh "$REMOTE_HOST" "btrfs subvolume delete '$BASE_DEST_PATH/$snapshot/snapshot'"; then
|
||||
if ! ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "btrfs subvolume delete '$BASE_DEST_PATH/$snapshot/snapshot'"; then
|
||||
send_notification "Backup Warning" "Failed to delete remote snapshot $snapshot on $HOSTNME" 6
|
||||
log "WARNING - Failed to delete remote snapshot $snapshot"
|
||||
fi
|
||||
if ! ssh "$REMOTE_HOST" "rm -rf '$BASE_DEST_PATH/$snapshot'"; then
|
||||
if ! ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "rm -rf '$BASE_DEST_PATH/$snapshot'"; then
|
||||
send_notification "Backup Warning" "Failed to cleanup remote snapshot directory $snapshot on $HOSTNME" 6
|
||||
log "WARNING - Failed to cleanup remote snapshot directory $snapshot"
|
||||
fi
|
||||
|
@ -292,7 +292,7 @@ if [ -n "$LAST_TRANSFERRED" ]; then
|
|||
fi
|
||||
|
||||
# Create destination directory if it doesn't exist
|
||||
ssh "$REMOTE_HOST" "mkdir -p '$DEST_PATH'"
|
||||
ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "mkdir -p '$DEST_PATH'"
|
||||
|
||||
# Perform the transfer
|
||||
if [ -z "$LAST_TRANSFERRED" ]; then
|
||||
|
@ -300,7 +300,7 @@ if [ -z "$LAST_TRANSFERRED" ]; then
|
|||
log "Performing full send of snapshot $NEW_SNAPSHOT"
|
||||
sudo btrfs send "$SNAPSHOT_PATH/$NEW_SNAPSHOT/snapshot" | \
|
||||
pv --bytes | \
|
||||
ssh "$REMOTE_HOST" "btrfs receive '$DEST_PATH'" && {
|
||||
ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "btrfs receive '$DEST_PATH'" && {
|
||||
echo "$NEW_SNAPSHOT" | sudo tee "$STATE_FILE"
|
||||
log "Full send completed successfully"
|
||||
} || {
|
||||
|
@ -315,7 +315,7 @@ else
|
|||
sudo btrfs send -p "$SNAPSHOT_PATH/$LAST_TRANSFERRED/snapshot" \
|
||||
"$SNAPSHOT_PATH/$NEW_SNAPSHOT/snapshot" | \
|
||||
pv --bytes | \
|
||||
ssh "$REMOTE_HOST" "btrfs receive '$DEST_PATH'" && {
|
||||
ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "btrfs receive '$DEST_PATH'" && {
|
||||
echo "$NEW_SNAPSHOT" | sudo tee "$STATE_FILE"
|
||||
log "Incremental send completed successfully"
|
||||
} || {
|
||||
|
@ -348,7 +348,7 @@ if [ -n "$LAST_TRANSFERRED" ]; then
|
|||
fi
|
||||
|
||||
# Final verification
|
||||
if ! ssh "$REMOTE_HOST" "btrfs subvolume show '$DEST_PATH/snapshot'" &>/dev/null; then
|
||||
if ! ssh -i /run/secrets/btrfs-backup/ssh_key "$REMOTE_HOST" "btrfs subvolume show '$DEST_PATH/snapshot'" &>/dev/null; then
|
||||
send_notification "Backup Failed" "Final verification failed for $SNAPPER_CONFIG on $HOSTNME" 8
|
||||
log "WARNING - Final verification failed"
|
||||
exit 1
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
{
|
||||
imports = [
|
||||
../../common/services/snapper.nix
|
||||
../../common/services/btrbk.nix
|
||||
];
|
||||
|
||||
# Ensure the btrbk snapshot folders are created since btrbk won't do it automatically:
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /home/.snapshots/btrbk 0755 btrbk btrbk"
|
||||
"d /Local-Storage/.snapshots/btrbk 0755 btrbk btrbk"
|
||||
];
|
||||
services.btrbk.instances."synology".settings.volume."/".subvolume = {
|
||||
"/home" = { snapshot_dir = "/home/.snapshots/btrbk"; };
|
||||
"/Local-Storage" = { snapshot_dir = "/Local-Storage/.snapshots/btrbk"; };
|
||||
};
|
||||
|
||||
# services.cron = {
|
||||
# systemCronJobs = [
|
||||
# "0 0 * * * root btrfs-backup root"
|
||||
# "0 0 * * * root btrfs-backup nix"
|
||||
# "0 0 * * * root btrfs-backup home"
|
||||
# "0 0 * * * root btrfs-backup Local-Storage"
|
||||
# ];
|
||||
# };
|
||||
services.cron = {
|
||||
systemCronJobs = [
|
||||
"0 0 * * * root btrfs-backup root"
|
||||
"0 0 * * * root btrfs-backup nix"
|
||||
"0 0 * * * root btrfs-backup home"
|
||||
"0 0 * * * root btrfs-backup Local-Storage"
|
||||
];
|
||||
};
|
||||
|
||||
# extra configs not present in the standard config above
|
||||
services.snapper.configs.Local-Storage = {
|
||||
|
|
|
@ -4,17 +4,16 @@ services:
|
|||
forgejo_token: ENC[AES256_GCM,data:vAH8v82+WI/P0HhtLDfrK66B3u2H49XA1AglfL1LthM6Dm+znBlx4QaFmNk3ag==,iv:/jqtUejqNC9f9kXdUqxl1+LaxKsjXSZdU+I0u+ssmdQ=,tag:+2oWh6sgc7R1PXYxIz3oVQ==,type:str]
|
||||
btrfs-backups:
|
||||
gotify_token: ENC[AES256_GCM,data:PP8UTJWrDKhonLxN8vEj,iv:hTGWyktK+Ce7hAd0bARztLAQDSvhWgLcKRyGqyfgVKU=,tag:2xboM6Uv8NWld89EUl2jEg==,type:str]
|
||||
btrbk:
|
||||
ssh_key: ENC[AES256_GCM,data:HxT85XlROSSKqPOEToSmrpzc6cutWRDkLxIO8o13AENtAlqEfBtcVTe/XKKbUjx+38FkqznVuHgVxXtnWLfON0yCx2PqoWVsluPfW44QFswQdtM0dYYCFy1hK7pg0xSplIeYdNZC9VFhL+SoBYXfTHKpalPo5LwYVrtQnO9yV/PrYw07oYTEKWGVxpi0KJJ2vo4UwxONzEJJSjJU/M0haQ1mvgTU5kFS5e4cMZOy3cGpGSUOPlUDlQgUlANcK92HFZlFnRyd2r+pjYVkSeixfQ9Zq30nNoaSu1J2VZhkt1KTfAXnuGIjlByvSVE9ZF78rlZfTBmZzJEyB3N3rtWEWUOrLZx8ZCh1YIpp6VK2WNJKtW2SpCpkG0fCoKzJiBvf+GuV4P0vdBHo6/xt12CHx498XUZSP644b1vnUim+RRmDQkVnTJnjY4YilIUME8MEFMzNuGamX/IX+U+UDGYwE+/7rc1BMZyJdzQka272uj66Q+fE7f/wzgtVbtgBBkIi3pDfv3smfFU8xGQoNmGJWIy1edvDJpoxsIaZ,iv:SvcLu1ffduCYj6tEfj6cSZM9CSB9TbGXWz4CixXYnsA=,tag:enn3+zPZbDl7IfivWv82Fg==,type:str]
|
||||
ssh_pub_key: ENC[AES256_GCM,data:ARuXIOnW2x2NceekoRPG/Vy+zj/RdryE9m4MYt6e1NFGOgC2k69ZAmBui0+aIly2kJP4VyKJ/cf70APuv4uBmahAClFFdj5ZNrQnINiQzJF6iWOiaRI=,iv:+TqQ1WWaVRy/Ec8N3WUxSlkfU2me2ncII8smq6RsJr8=,tag:G4+/js93EFWudg9cRigxog==,type:str]
|
||||
ssh_key: ENC[AES256_GCM,data:Nri7+3ZAPIEkYwjeyW0uQCycIxVx+ebOg2zHFHvt5MjootsIBXsQhBiGupP2/0ZQ2Val8VgX0wFnMG89GCCpOwiYe8vVaIeLmLOCAAchu16ftNqSN9zNv0aLPZ/lJhYdtnq79hXA6jbrwYONPaVU/5fqbl3+kWhEJtgjhB+eH0O9sLUAS8s66scov7yYHwYH7cWvJUiOomwCx0a6th2MzU2+PDvFCrr1hqQyS3CJdMrLTAHkg0F74pvmVFQB7Z1m2KWPJkaX1ji3/kyjrOKbq++GF6L7TwH03vMXtrHqExF8KTGfmelhlmlJ0UzaoOTZ9SG+0xIEwb7SjY4DNoUO2rZC3A+vn4g/RsYKhXAHEeRFgkAmcWZR65gbEliN7MMFcpwMkIFWEgM4zRmC4ZmGs3zxSxsQyHKqBtL4cRrlLmwXCwPjv4TbiV2BmlCNgahh+WtVTQnx/GQcaGZ9MT8lhRC7dSy0HS9Efc8uUz8e5aAER8F7z1MhemP92Ma3YsNyEUxcHU6Ruk7NUbgqMIxGbGiqXzW3DSMc6L0+,iv:5zjYDsZrg5hekMl58p0o1znrojke4u1LzUY3sJpInkE=,tag:WlNyfgWGSD2Xf7ualoefxA==,type:str]
|
||||
ssh_pub_key: ENC[AES256_GCM,data:DO9KRWiB5yT3eY28P4QPVV4tho5CpaXEF2hHXubK8iAX/tlxzzztGAEGRo572BXP5T+FYB6jO12chLDNWoYDQ92yrdZGy5k5vPZSehTm6t3005Q0CF7JfeO0bX+biQ==,iv:VP2wx3ZD7RE1zDDRthv2329GXemmMKYl7te69KNGY0s=,tag:78QSISotcsMmi3leNcP5sQ==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2025-01-16T00:34:44Z"
|
||||
mac: ENC[AES256_GCM,data:oG1TahgiYBXqDV9oftlBfhSlUIDwkyPMQncoxq9+443ktXZ4Ze+FpYw3FH4NAR4n59CWfzrwUYWY+YYoRUIUzNrOloygy2z/FAdnyYXs3CDt++4Gilz74P9f5THloXgKF5LMSIyYh091zrEV25nSqdSHQZnXKQOQJAAsitMcAdU=,iv:k7SJ9bnC1eiOSkomIrB1Ou0VoUfRcYI3m0GUKTGATQw=,tag:wfjGh3q7X0EXbx4o37syLQ==,type:str]
|
||||
lastmodified: "2025-01-16T16:08:57Z"
|
||||
mac: ENC[AES256_GCM,data:by/kjCDwQFWkBJPDB/W44w+8VfIm68fGHWuQOpzrnrM4GFfqO4lSbd/Mzy6aZ9sWSkoNO3h4l3lx3RUvpc4nh1JWqfhoKjds9HIqMKcAwFdUtRCZeMc+g5nc5/BLL27duM2F0YaPFNLs2u2hBgMcRME+j80jQ4r7rMhOPIb+DuA=,iv:sYsORoOuvNW/0o4f6TjQe8vGuOQRW02T8ZAO5FApszg=,tag:0PN9MraA+Ozv1ozy7l+Fhw==,type:str]
|
||||
pgp:
|
||||
- created_at: "2025-01-10T20:21:25Z"
|
||||
enc: |-
|
||||
|
|
Loading…
Add table
Reference in a new issue