feat(fuchsia): implement backup strategy with explicit home paths

Add snapper and borgbackup for fuchsia home directory backups:

Snapper Configuration:
- Hourly snapshots of /home/sajenim
- Retention: 24 hourly, 7 daily, 4 weekly, 12 monthly
- Stored in nested .snapshots subvolume

Borgbackup Onsite:
- Backup to viridian over SSH (local network)
- Target: ssh://viridian/srv/borg-repo/fuchsia
- Hourly backups, unencrypted, deduplicated
- Same retention as snapper

Borgbackup Offsite:
- Backup to borgbase (internet)
- Target: li9kg944@li9kg944.repo.borgbase.com:repo
- Daily backups, encrypted (repokey-blake2), deduplicated
- Retention: 7 daily, 4 weekly, 12 monthly

Explicit Home Paths (valuable user data only):
- Documents, Pictures, Videos, Music, Downloads, Academics, Notes
- Dotfiles: .ssh, .gnupg

System Persist Data:
- SSH host keys, machine-id, nixos state
- Bluetooth, NetworkManager configurations

Intentionally Excluded:
- .config (managed declaratively via home-manager)
- .repositories (cloneable from GitHub)
- .cache and build artifacts

Treats viridian as central backup server, maintaining 3-2-1 strategy
(3 copies, 2 locations, 1 offsite).

chore(viridian): remove unused inputs parameter from borgbackup offsite
This commit is contained in:
♥ Minnie ♥ 2025-10-07 19:14:11 +08:00
parent f24a7476a7
commit a6fa8866ac
Signed by: jasmine
GPG key ID: 8563E358D4E8040E
6 changed files with 200 additions and 1 deletions

View file

@ -0,0 +1,6 @@
{...}: {
imports = [
./offsite.nix
./onsite.nix
];
}

View file

@ -0,0 +1,86 @@
{
config,
pkgs,
...
}: {
# Encrypted passphrase for offsite borgbackup repository
age.secrets.borgbackup = {
rekeyFile = ./passphrase.age;
};
# Create staging directory before borg service starts
systemd.tmpfiles.rules = [
"d /.staging-offsite 0755 root root -"
];
services.borgbackup.jobs."offsite" = {
# Allow writing to staging directory
readWritePaths = [ "/.staging-offsite" ];
# Create staging snapshots before backup (independent from onsite)
preHook = ''
# Create read-only staging snapshots for home directory
${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r \
"/home/sajenim" "/.staging-offsite/home"
'';
# Backup explicit home directories and persistent files
paths = [
# Home directories (valuable user data only)
"/.staging-offsite/home/Documents"
"/.staging-offsite/home/Pictures"
"/.staging-offsite/home/Videos"
"/.staging-offsite/home/Music"
"/.staging-offsite/home/Downloads"
"/.staging-offsite/home/Academics"
"/.staging-offsite/home/Notes"
# Dotfiles (critical user configuration)
"/.staging-offsite/home/.ssh"
"/.staging-offsite/home/.gnupg"
# Files from persist.nix (restore to /persist)
"/etc/machine-id"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
# Directories from persist.nix (restore to /persist)
"/var/lib/bluetooth"
"/var/lib/nixos"
"/var/lib/private"
"/etc/NetworkManager/system-connections"
];
# Remove staging snapshots after backup completes
postHook = ''
${pkgs.btrfs-progs}/bin/btrfs subvolume delete \
"/.staging-offsite/home"
'';
# Remote repository configuration
repo = "li9kg944@li9kg944.repo.borgbase.com:repo";
encryption = {
mode = "repokey-blake2";
passCommand = "cat ${config.age.secrets.borgbackup.path}";
};
environment.BORG_RSH = "ssh -i /etc/ssh/ssh_host_ed25519_key";
compression = "zstd,9";
startAt = "daily";
# Retention policy for daily remote backups
prune.keep = {
daily = 7; # Keep 7 daily backups (1 week)
weekly = 4; # Keep 4 weekly backups (1 month)
monthly = 12; # Keep 12 monthly backups (1 year)
};
};
# SSH host keys for borgbase.com
programs.ssh.knownHostsFiles = [
./borgbase_hosts
];
}

View file

@ -0,0 +1,84 @@
{
config,
pkgs,
...
}: let
hostname = config.networking.hostName;
in {
# Create staging directory before borg service starts
systemd.tmpfiles.rules = [
"d /.staging-onsite 0755 root root -"
];
services.borgbackup.jobs."onsite" = {
# Allow writing to staging directory
readWritePaths = [ "/.staging-onsite" ];
# Create staging snapshots before backup (independent from offsite)
preHook = ''
# Create read-only staging snapshots for home directory
${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r \
"/home/sajenim" "/.staging-onsite/home"
'';
# Backup explicit home directories and persistent files
paths = [
# Home directories (valuable user data only)
"/.staging-onsite/home/Documents"
"/.staging-onsite/home/Pictures"
"/.staging-onsite/home/Videos"
"/.staging-onsite/home/Music"
"/.staging-onsite/home/Downloads"
"/.staging-onsite/home/Academics"
"/.staging-onsite/home/Notes"
# Dotfiles (critical user configuration)
"/.staging-onsite/home/.ssh"
"/.staging-onsite/home/.gnupg"
# Files from persist.nix (restore to /persist)
"/etc/machine-id"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
# Directories from persist.nix (restore to /persist)
"/var/lib/bluetooth"
"/var/lib/nixos"
"/var/lib/private"
"/etc/NetworkManager/system-connections"
];
# Remove staging snapshots after backup completes
postHook = ''
${pkgs.btrfs-progs}/bin/btrfs subvolume delete \
"/.staging-onsite/home"
'';
# Onsite repository configuration (backup to viridian over SSH)
repo = "ssh://viridian/srv/borg-repo/${hostname}";
# No encryption for onsite backups (physical security assumed)
encryption.mode = "none";
environment.BORG_RSH = "ssh -i /etc/ssh/ssh_host_ed25519_key";
compression = "zstd,9";
startAt = "hourly";
# Match snapper retention policy
prune.keep = {
hourly = 24;
daily = 7;
weekly = 4;
monthly = 12;
};
};
# SSH host keys for viridian
programs.ssh.knownHostsFiles = [
./viridian_hosts
];
}

View file

@ -1,10 +1,12 @@
{...}: {
imports = [
./amdgpu-clocks
./borgbackup
./flatpak
./libinput
./pipewire
./printing
./snapper
./udev
./xserver
];

View file

@ -0,0 +1,22 @@
{...}: {
# Configure snapper for automated snapshots
# Snapshots stored in nested .snapshots subvolume within home directory
services.snapper = {
configs = {
# Home directory for user sajenim
home = {
SUBVOLUME = "/home/sajenim";
ALLOW_USERS = ["sajenim"];
TIMELINE_CREATE = true;
TIMELINE_CLEANUP = true;
# Tiered retention: 24h + 7d + 4w + 12m = ~1 year of snapshots
TIMELINE_LIMIT_HOURLY = 24;
TIMELINE_LIMIT_DAILY = 7;
TIMELINE_LIMIT_WEEKLY = 4;
TIMELINE_LIMIT_MONTHLY = 12;
TIMELINE_LIMIT_YEARLY = 0;
};
};
};
}

View file

@ -1,7 +1,6 @@
{
config,
pkgs,
inputs,
...
}: {
# Encrypted passphrase for offsite borgbackup repository