Add curacao backup stuff

This commit is contained in:
Geoffrey Frogeye 2023-12-16 22:22:14 +01:00
parent 740e103730
commit a3552634b6
Signed by: geoffrey
GPG key ID: C72403E7F82E6AD8
5 changed files with 149 additions and 2 deletions

View file

@ -17,7 +17,7 @@ function help {
echo " -h: Display this help message."
}
while getopts "hvb" OPTION
while getopts "h" OPTION
do
case "$OPTION" in
h)

83
curacao/backup/backup.sh Executable file
View file

@ -0,0 +1,83 @@
#!/usr/bin/env bash
set -euxo pipefail
# Parse arguments
function help {
echo "Usage: $0 [-h|-i] volume"
echo "Backup BTRFS subvolume on rapido to razmo."
echo
echo "Arguments:"
echo " volume: Name of the subvolume to backup"
echo
echo "Options:"
echo " -h: Display this help message."
echo " -i: Don't fail if the receiving subvolume doesn't exist."
}
init=false
while getopts "hi" OPTION
do
case "$OPTION" in
h)
help
exit 0
;;
i)
init=true
;;
?)
help
exit 2
;;
esac
done
shift "$((OPTIND - 1))"
if [ "$#" -ne 1 ]
then
help
exit 2
fi
volume="$1"
# Assertions
[ -d "/mnt/rapido/${volume}" ]
[ -d "/mnt/rapido/${volume}.bkp" ] || "$init"
[ ! -d "/mnt/rapido/${volume}.new" ]
[ -d "/mnt/razmo/${volume}.bkp" ] || "$init"
[ -d "/mnt/razmo/${volume}" ] || "$init"
[ ! -d "/mnt/razmo/${volume}.new" ]
[ ! -d "/mnt/razmo/${volume}.snapshots" ]
# Taking a snapshot of the running subvolume
btrfs subvolume snapshot -r "/mnt/rapido/${volume}" "/mnt/rapido/${volume}.new"
# Sending (the difference with) the last backup to the backup disk
function error_handler() {
btrfs subvolume delete "/mnt/rapido/${volume}.new" || true
btrfs subvolume delete "/mnt/razmo/${volume}.new" || true
}
trap error_handler ERR
if [ -d "/mnt/rapido/${volume}.bkp" ]
then
btrfs send -p "/mnt/rapido/${volume}.bkp" "/mnt/rapido/${volume}.new" | btrfs receive /mnt/razmo
else
btrfs send "/mnt/rapido/${volume}.new" | btrfs receive /mnt/razmo
fi
trap - ERR
# Removing old backups and putting the new one in place
[ ! -d "/mnt/rapido/${volume}.bkp" ] || btrfs subvolume delete "/mnt/rapido/${volume}.bkp"
mv "/mnt/rapido/${volume}.new" "/mnt/rapido/${volume}.bkp"
[ ! -d "/mnt/razmo/${volume}.bkp" ] || btrfs subvolume delete "/mnt/razmo/${volume}.bkp"
mv "/mnt/razmo/${volume}.new" "/mnt/razmo/${volume}.bkp"
# Create a writeable clone in case we need to boot on the HDD
# Needs to move away then back the .snapshots folder
[ ! -d "/mnt/razmo/${volume}/.snapshots" ] || mv "/mnt/razmo/${volume}/.snapshots" "/mnt/razmo/${volume}.snapshots"
[ ! -d "/mnt/razmo/${volume}" ] || btrfs subvolume delete "/mnt/razmo/${volume}"
btrfs subvolume snapshot "/mnt/razmo/${volume}.bkp" "/mnt/razmo/${volume}"
[ ! -d "/mnt/razmo/${volume}.snapshots" ] || mv "/mnt/razmo/${volume}.snapshots" "/mnt/razmo/${volume}/.snapshots"
sync

View file

@ -0,0 +1,64 @@
{ pkgs, lib, ... }:
# MANU Snapper is not able to create the snapshot directory, so you'll need to do this after eventually running the backup script:
# sudo btrfs subvol create /mnt/razmo/$subvolume/.snapshots
let
backup_subvolumes = [ "nixos" "home.rapido" ];
backup_app = pkgs.writeShellApplication {
name = "backup-subvolume";
runtimeInputs = with pkgs; [ coreutils btrfs-progs ];
text = builtins.readFile ./backup.sh;
};
snapper_subvolumes = [ "nixos" "home.rapido" "home.razmo" ];
in
{
services =
let
default = {
# filesystem type
FSTYPE = "btrfs";
# run daily number cleanup
NUMBER_CLEANUP = true;
NUMBER_MIN_AGE = 1800;
NUMBER_LIMIT = 25;
# create hourly snapshots
TIMELINE_CREATE = true;
# cleanup hourly snapshots after some time
TIMELINE_CLEANUP = true;
TIMELINE_MIN_AGE = 1800;
TIMELINE_LIMIT_HOURLY = 24;
TIMELINE_LIMIT_DAILY = 31;
TIMELINE_LIMIT_WEEKLY = 8;
TIMELINE_LIMIT_MONTHLY = 0;
TIMELINE_LIMIT_YEARLY = 0;
# cleanup empty pre-post-pairs
EMPTY_PRE_POST_CLEANUP = true;
};
in
{
snapper.configs = lib.attrsets.mergeAttrsList (map (s: { "${s}" = default // { SUBVOLUME = "/mnt/razmo/${s}"; }; }) snapper_subvolumes);
};
systemd = {
services.bkp_rapido = {
description = "Make a snapshot of the SSD to the HDD";
before = [ "snapper-timeline.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = map (s: "${backup_app}/bin/backup-subvolume ${s}") backup_subvolumes;
};
# TODO Harden
};
timers.bkp_rapido = {
description = "Regular snapshot of SSD to HDD";
timerConfig = {
OnCalendar = "hourly";
};
wantedBy = [ "timers.target" ];
};
};
}

View file

@ -1,5 +1,4 @@
{ passwordFile ? "/should_not_be_needed_in_this_context", ... }:
# FIXME Subvolumes for backup. If they're not created with the script. Add the script btw.
# TODO Not relatime everywhere, thank you
# TODO Default options
let

View file

@ -5,6 +5,7 @@
./options.nix
./hardware.nix
./dk.nix
./backup
];
networking.hostName = "curacao";