@@ -1,16 +0,0 @@
|
||||
_backup_completion() {
|
||||
local options=(
|
||||
'-m[Partition to mount for backup]:partition:($(_partitions))'
|
||||
'-b[Backup directory]:backup directory:_files -/'
|
||||
)
|
||||
local curcontext="$curcontext" state line
|
||||
typeset -A opt_args
|
||||
|
||||
_partitions() {
|
||||
lsblk -rno NAME | sed 's/^/\/dev\//'
|
||||
}
|
||||
|
||||
_arguments -s $options
|
||||
}
|
||||
|
||||
compdef _backup_completion backup
|
@@ -1,67 +0,0 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
echo "Please run the script as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [-m partition] [-b backup_location]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if [ -d "/persist/user.bak" ]; then btrfs -q subvolume delete "/persist/user.bak"; fi
|
||||
if [ -n "$backup_location" ]; then rm -f "$backup_location.tmp"; fi
|
||||
|
||||
if [ -n "$mount_location" ]; then
|
||||
if mount | grep -q "$mount_location"; then umount "$mount_location"; fi
|
||||
if [ -d "$mount_location" ]; then rmdir "$mount_location"; fi
|
||||
fi
|
||||
}
|
||||
|
||||
partition=""
|
||||
backup_location=""
|
||||
mount_location=""
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
while getopts "m:b:" opt; do
|
||||
case "$opt" in
|
||||
m) partition="$OPTARG" ;;
|
||||
b) backup_location="$OPTARG" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -n "$partition" ]; then
|
||||
mkdir -p "/mnt"
|
||||
mount_location=$(mktemp -d /mnt/backup.XXXXXX)
|
||||
echo "Mounting $partition at $mount_location..."
|
||||
mount "$partition" "$mount_location"
|
||||
fi
|
||||
|
||||
if [ -z "$mount_location" ]; then
|
||||
if [[ "$backup_location" != /* ]]; then
|
||||
backup_location="$(realpath "$backup_location")"
|
||||
fi
|
||||
else
|
||||
if [[ "$backup_location" = /* ]]; then
|
||||
echo "Error: When a partition is mounted, backup_location must be relative."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
backup_location="$(realpath "$mount_location/$backup_location")"
|
||||
fi
|
||||
|
||||
backup_location="$backup_location/$(hostname)-$(date +%Y-%m-%d-%H-%M-%S).btrfs.gz"
|
||||
|
||||
echo "Creating /persist/user snapshot..."
|
||||
btrfs -q subvolume snapshot -r "/persist/user" "/persist/user.bak"
|
||||
|
||||
echo "Creating backup at $backup_location..."
|
||||
btrfs -q send "/persist/user.bak" > "$backup_location.tmp"
|
||||
|
||||
mv "$backup_location.tmp" "$backup_location"
|
||||
|
||||
echo "Backup completed successfully!"
|
@@ -1,18 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "backup";
|
||||
runtimeInputs = with pkgs; [
|
||||
btrfs-progs
|
||||
coreutils
|
||||
util-linux
|
||||
];
|
||||
text = builtins.readFile ./backup.sh;
|
||||
})
|
||||
];
|
||||
|
||||
home-manager.sharedModules = [
|
||||
{ programs.zsh.initContent = builtins.readFile ./backup.completion.zsh; }
|
||||
];
|
||||
}
|
33
hosts/common/configs/system/btrbk/default.nix
Normal file
33
hosts/common/configs/system/btrbk/default.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{ ... }:
|
||||
{
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /persist/user.bak 0755 root root"
|
||||
"d /persist/state.bak 0755 root root"
|
||||
];
|
||||
|
||||
services.btrbk = {
|
||||
ioSchedulingClass = "idle";
|
||||
niceness = 19;
|
||||
instances = {
|
||||
persist-user = {
|
||||
onCalendar = "hourly";
|
||||
settings.volume."/persist" = {
|
||||
subvolume = "user";
|
||||
snapshot_dir = "user.bak";
|
||||
snapshot_preserve_min = "latest";
|
||||
snapshot_preserve = "48h 14d 4w 6m";
|
||||
};
|
||||
};
|
||||
|
||||
persist-state = {
|
||||
onCalendar = "daily";
|
||||
settings.volume."/persist" = {
|
||||
subvolume = "state";
|
||||
snapshot_dir = "state.bak";
|
||||
snapshot_preserve_min = "latest";
|
||||
snapshot_preserve = "7d 4w 3m";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@@ -129,7 +129,10 @@ in
|
||||
"directory"
|
||||
];
|
||||
default = "none";
|
||||
description = "Whether to create the file or directory in persistence if it does not exist.";
|
||||
description = ''
|
||||
Whether to create the file or directory
|
||||
in persistence if it does not exist.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -13,11 +13,22 @@ mount "$DEVICE" /mnt/btrfs
|
||||
|
||||
if [[ -e /mnt/btrfs/@ ]]; then
|
||||
mkdir -p /mnt/btrfs/@.bak
|
||||
timestamp=$(date --date="@$(stat -c %Y /mnt/btrfs/@)" "+%Y-%m-%d_%H:%M:%S")
|
||||
mv /mnt/btrfs/@ "/mnt/btrfs/@.bak/$timestamp"
|
||||
timestamp=$(date --date="@$(stat -c %Y /mnt/btrfs/@)" "+%Y%m%dT%H%M")
|
||||
base="@.$timestamp"
|
||||
|
||||
target="/mnt/btrfs/@.bak/$base"
|
||||
if [[ -e "$target" ]]; then
|
||||
i=1
|
||||
while [[ -e "/mnt/btrfs/@.bak/${base}_$i" ]]; do
|
||||
(( i++ ))
|
||||
done
|
||||
target="/mnt/btrfs/@.bak/${base}_$i"
|
||||
fi
|
||||
|
||||
mv /mnt/btrfs/@ "$target"
|
||||
fi
|
||||
|
||||
find /mnt/btrfs/@.bak/ -maxdepth 1 -mtime +14 | while IFS= read -r i; do
|
||||
find /mnt/btrfs/@.bak/ -maxdepth 1 -mtime +7 | while IFS= read -r i; do
|
||||
delete_subvolume_recursively "$i"
|
||||
done
|
||||
|
||||
|
@@ -8,10 +8,10 @@
|
||||
|
||||
./hardware
|
||||
|
||||
../common/configs/system/backup
|
||||
../common/configs/system/bluetooth
|
||||
../common/configs/system/boot
|
||||
../common/configs/system/brightnessctl
|
||||
../common/configs/system/btrbk
|
||||
../common/configs/system/btrfs
|
||||
../common/configs/system/cloudflared
|
||||
../common/configs/system/cpu
|
||||
|
@@ -89,7 +89,7 @@ in
|
||||
(import ./configs/gui/vscode { inherit user home; })
|
||||
];
|
||||
|
||||
# echo "password" | mkpasswd -s
|
||||
# mkpasswd -s
|
||||
sops.secrets."${user}-password" = {
|
||||
sopsFile = ../../../../secrets/sas/secrets.yaml;
|
||||
key = "password";
|
||||
|
@@ -6,10 +6,10 @@
|
||||
|
||||
./hardware
|
||||
|
||||
../common/configs/system/backup
|
||||
../common/configs/system/bluetooth
|
||||
../common/configs/system/boot
|
||||
../common/configs/system/brightnessctl
|
||||
../common/configs/system/btrbk
|
||||
../common/configs/system/btrfs
|
||||
../common/configs/system/cpu
|
||||
../common/configs/system/documentation
|
||||
|
@@ -89,7 +89,7 @@ in
|
||||
(import ./configs/gui/vscode { inherit user home; })
|
||||
];
|
||||
|
||||
# echo "password" | mkpasswd -s
|
||||
# mkpasswd -s
|
||||
sops.secrets."${user}-password" = {
|
||||
sopsFile = ../../../../secrets/personal/secrets.yaml;
|
||||
key = "password";
|
||||
|
@@ -37,7 +37,7 @@ in
|
||||
(import ./configs/console/ssh { inherit user home; })
|
||||
];
|
||||
|
||||
# echo "password" | mkpasswd -s
|
||||
# mkpasswd -s
|
||||
sops.secrets."${user}-password" = {
|
||||
sopsFile = ../../../../secrets/personal/secrets.yaml;
|
||||
key = "password";
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
../common/configs/system/boot
|
||||
../common/configs/system/brightnessctl
|
||||
../common/configs/system/btrbk
|
||||
../common/configs/system/btrfs
|
||||
../common/configs/system/cpu
|
||||
../common/configs/system/documentation
|
||||
|
@@ -35,7 +35,7 @@ in
|
||||
(import ./configs/console/podman { inherit user home; })
|
||||
];
|
||||
|
||||
# echo "password" | mkpasswd -s
|
||||
# mkpasswd -s
|
||||
sops.secrets."${user}-password" = {
|
||||
sopsFile = ../../../../secrets/personal/secrets.yaml;
|
||||
key = "password";
|
||||
|
@@ -19,7 +19,7 @@ in
|
||||
(import ./configs/console/podman { inherit user home; })
|
||||
];
|
||||
|
||||
# echo "password" | mkpasswd -s
|
||||
# mkpasswd -s
|
||||
sops.secrets."${user}-password" = {
|
||||
sopsFile = ../../../../secrets/personal/secrets.yaml;
|
||||
key = "password";
|
||||
|
Reference in New Issue
Block a user