feat(viridian): implement comprehensive 3-2-1 backup strategy
Add automated snapshot and backup system with three independent tiers: Snapper (hourly local snapshots): - Configure snapper for all srv-* subvolumes - Tiered retention: 24 hourly, 7 daily, 4 weekly, 12 monthly - Snapshots stored at /.snapshots on viridian drive - Provides fast operational rollback for user errors Borgbackup onsite (hourly local backups): - Independent staging snapshots at /.staging-onsite - Repository on data drive at /srv/borg-repo - Unencrypted (physical security assumed) - Matches snapper retention policy - Fast local disaster recovery Borgbackup offsite (daily remote backups): - Independent staging snapshots at /.staging-offsite - Encrypted backups to borgbase repository - Retention: 7 daily, 4 weekly, 12 monthly - Remote disaster recovery with prune policy Architecture decisions: - Separate staging directories prevent job conflicts - Staging snapshots decouple borg jobs from snapper - Consistent zstd,9 compression across both borg jobs - Special case handling for containers subvolume path
This commit is contained in:
parent
b0bfb37d3c
commit
c05598d9e0
5 changed files with 231 additions and 36 deletions
90
nixos/viridian/services/snapper/default.nix
Normal file
90
nixos/viridian/services/snapper/default.nix
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
{config, ...}: let
|
||||
hostname = config.networking.hostName;
|
||||
in {
|
||||
# Mount snapshots subvolume at /.snapshots for snapshot storage
|
||||
fileSystems."/.snapshots" = {
|
||||
device = "/dev/disk/by-label/${hostname}";
|
||||
fsType = "btrfs";
|
||||
options = [
|
||||
"subvol=snapshots"
|
||||
"compress=zstd"
|
||||
];
|
||||
};
|
||||
|
||||
# Configure snapper for automated snapshots
|
||||
services.snapper = {
|
||||
# Enable snapper globally
|
||||
configs = {
|
||||
# Minecraft server data
|
||||
minecraft = {
|
||||
SUBVOLUME = "/srv/minecraft";
|
||||
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;
|
||||
};
|
||||
|
||||
# Container data (jellyfin, arr services, etc)
|
||||
containers = {
|
||||
SUBVOLUME = "/srv/multimedia/containers";
|
||||
ALLOW_USERS = ["sajenim"];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
|
||||
TIMELINE_LIMIT_HOURLY = 24;
|
||||
TIMELINE_LIMIT_DAILY = 7;
|
||||
TIMELINE_LIMIT_WEEKLY = 4;
|
||||
TIMELINE_LIMIT_MONTHLY = 12;
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
};
|
||||
|
||||
# Forgejo git forge data
|
||||
forgejo = {
|
||||
SUBVOLUME = "/srv/forgejo";
|
||||
ALLOW_USERS = ["sajenim"];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
|
||||
TIMELINE_LIMIT_HOURLY = 24;
|
||||
TIMELINE_LIMIT_DAILY = 7;
|
||||
TIMELINE_LIMIT_WEEKLY = 4;
|
||||
TIMELINE_LIMIT_MONTHLY = 12;
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
};
|
||||
|
||||
# OpenGist pastebin data
|
||||
opengist = {
|
||||
SUBVOLUME = "/srv/opengist";
|
||||
ALLOW_USERS = ["sajenim"];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
|
||||
TIMELINE_LIMIT_HOURLY = 24;
|
||||
TIMELINE_LIMIT_DAILY = 7;
|
||||
TIMELINE_LIMIT_WEEKLY = 4;
|
||||
TIMELINE_LIMIT_MONTHLY = 12;
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
};
|
||||
|
||||
# Lighttpd website data
|
||||
lighttpd = {
|
||||
SUBVOLUME = "/srv/lighttpd";
|
||||
ALLOW_USERS = ["sajenim"];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
|
||||
TIMELINE_LIMIT_HOURLY = 24;
|
||||
TIMELINE_LIMIT_DAILY = 7;
|
||||
TIMELINE_LIMIT_WEEKLY = 4;
|
||||
TIMELINE_LIMIT_MONTHLY = 12;
|
||||
TIMELINE_LIMIT_YEARLY = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue