122 lines
3.5 KiB
Nix
122 lines
3.5 KiB
Nix
|
|
{ config, lib, pkgs, ... }:
|
||
|
|
|
||
|
|
let
|
||
|
|
cfg = config.gortium.temp16tb;
|
||
|
|
luksName = cfg.luksName;
|
||
|
|
in
|
||
|
|
with lib;
|
||
|
|
|
||
|
|
{
|
||
|
|
options.gortium.temp16tb = {
|
||
|
|
enable = mkEnableOption "16TB temp storage disk (btrfs + LUKS + btrbk snapshots)";
|
||
|
|
|
||
|
|
luksUuid = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
description = ''
|
||
|
|
UUID of the LUKS partition on the 16TB disk.
|
||
|
|
|
||
|
|
Find this by running as root when the disk is connected:
|
||
|
|
blkid /dev/sdb # or wherever the disk appears
|
||
|
|
lsblk -o NAME,SIZE,FSTYPE,UUID
|
||
|
|
|
||
|
|
Since btrfs is inside LUKS, the FS UUID is hidden — use the
|
||
|
|
LUKS partition UUID from blkid (it'll show TYPE=\"crypto_LUKS\").
|
||
|
|
'';
|
||
|
|
example = "00000000-0000-0000-0000-000000000000";
|
||
|
|
};
|
||
|
|
|
||
|
|
luksName = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
default = "temp_16tb";
|
||
|
|
description = "Name for the LUKS /dev/mapper/ mapping";
|
||
|
|
};
|
||
|
|
|
||
|
|
mountPoint = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
default = "/mnt/temp_16tb";
|
||
|
|
description = "Mount point for the 16TB disk";
|
||
|
|
};
|
||
|
|
|
||
|
|
btrfsOptions = mkOption {
|
||
|
|
type = types.listOf types.str;
|
||
|
|
default = [ "defaults" "noatime" "compress=zstd:3" "nofail" ];
|
||
|
|
description = "Mount options for the btrfs filesystem. 'nofail' ensures boot succeeds when disk is disconnected.";
|
||
|
|
};
|
||
|
|
|
||
|
|
btrbk = {
|
||
|
|
enable = mkOption {
|
||
|
|
type = types.bool;
|
||
|
|
default = true;
|
||
|
|
description = "Enable btrbk snapshot management on this volume";
|
||
|
|
};
|
||
|
|
|
||
|
|
schedule = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
default = "daily";
|
||
|
|
description = "systemd calendar event for btrbk (e.g. 'daily', 'hourly', '*-*-* 00:00:00')";
|
||
|
|
};
|
||
|
|
|
||
|
|
preserveMin = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
default = "2d";
|
||
|
|
description = "btrbk snapshot_preserve_min — minimum age before pruning";
|
||
|
|
};
|
||
|
|
|
||
|
|
preserve = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
default = "14d 4w 3m";
|
||
|
|
description = "btrbk snapshot_preserve — retention policy (daily, weekly, monthly)";
|
||
|
|
};
|
||
|
|
|
||
|
|
snapshotDir = mkOption {
|
||
|
|
type = types.str;
|
||
|
|
default = ".snapshots";
|
||
|
|
description = "Directory name for snapshots relative to volume root";
|
||
|
|
};
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
config = mkIf cfg.enable {
|
||
|
|
# Enable btrfs kernel support (no DKMS needed — it's in-tree)
|
||
|
|
boot.supportedFilesystems = [ "btrfs" ];
|
||
|
|
|
||
|
|
# Install btrfs administration tools
|
||
|
|
environment.systemPackages = with pkgs; [
|
||
|
|
btrfs-progs # mkfs.btrfs, btrfs, fsck, balance, scrub
|
||
|
|
btrbk # Snapshot management + rotation
|
||
|
|
];
|
||
|
|
|
||
|
|
# LUKS2 unlock at boot (uses keyfile or prompts if unavailable)
|
||
|
|
# Since the disk may be disconnected, initrd times out gracefully (~30s)
|
||
|
|
boot.initrd.luks.devices.${luksName} = {
|
||
|
|
device = "/dev/disk/by-uuid/${cfg.luksUuid}";
|
||
|
|
preLVM = false;
|
||
|
|
allowDiscards = true;
|
||
|
|
};
|
||
|
|
|
||
|
|
# Mount the unlocked mapper device as btrfs
|
||
|
|
fileSystems.${cfg.mountPoint} = {
|
||
|
|
device = "/dev/mapper/${luksName}";
|
||
|
|
fsType = "btrfs";
|
||
|
|
options = cfg.btrfsOptions;
|
||
|
|
};
|
||
|
|
|
||
|
|
# btrbk — automated snapshot creation and rotation
|
||
|
|
services.btrbk = mkIf cfg.btrbk.enable {
|
||
|
|
instances.temp16tb = {
|
||
|
|
onCalendar = cfg.btrbk.schedule;
|
||
|
|
settings = {
|
||
|
|
snapshot_preserve_min = cfg.btrbk.preserveMin;
|
||
|
|
snapshot_preserve = cfg.btrbk.preserve;
|
||
|
|
|
||
|
|
volume.${cfg.mountPoint} = {
|
||
|
|
snapshot_create = "always";
|
||
|
|
snapshot_dir = cfg.btrbk.snapshotDir;
|
||
|
|
subvolume = ".";
|
||
|
|
};
|
||
|
|
};
|
||
|
|
};
|
||
|
|
};
|
||
|
|
};
|
||
|
|
}
|