summaryrefslogtreecommitdiff
path: root/sys/fs/btrfs.nix
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/btrfs.nix')
-rw-r--r--sys/fs/btrfs.nix111
1 files changed, 111 insertions, 0 deletions
diff --git a/sys/fs/btrfs.nix b/sys/fs/btrfs.nix
new file mode 100644
index 0000000..87c9fca
--- /dev/null
+++ b/sys/fs/btrfs.nix
@@ -0,0 +1,111 @@
+{ lib, config, pkgs, ... }:
+with lib; let
+ cfg = config.local;
+in {
+ options.local = with lib.types; {
+ snapperSubvols = mkOption {
+ type = attrsOf str;
+ default = {};
+ };
+
+ fs.btrfs = mkOption {
+ default = [];
+
+ type = attrsOf (submodule {
+ options = {
+ device = mkOption {
+ type = str;
+ };
+
+ subvol = mkOption {
+ type = str;
+ };
+
+ ssd = mkOption {
+ type = bool;
+ };
+
+ snapper = mkOption {
+ type = nullOr str;
+ default = null;
+ };
+ };
+ });
+ };
+ };
+
+ config = {
+ environment.systemPackages = optional (cfg.snapperSubvols != {}) pkgs.local.btclone;
+
+ fileSystems = let
+ inherit (cfg) fs;
+ btrfs = { device, subvol, ssd, ... }: {
+ inherit device;
+ fsType = "btrfs";
+ options = [ "noatime" "compress=zstd" "subvol=${subvol}" ] ++ optional ssd "ssd";
+ };
+ in mapAttrs (_: btrfs) cfg.fs.btrfs;
+
+ local.snapperSubvols = let
+ snapperEntry = path: opts: { name = opts.snapper; value = path; };
+ validEntry = _: opts: opts.snapper != null;
+ in mapAttrs' snapperEntry (filterAttrs validEntry cfg.fs.btrfs);
+
+ services.snapper.configs = let
+ snapperConfig = _: subvolume: {
+ inherit subvolume;
+
+ extraConfig = ''
+ # btrfs qgroup for space aware cleanup algorithms
+ QGROUP=""
+
+ # fraction of the filesystems space the snapshots may use
+ SPACE_LIMIT="0.5"
+
+ # fraction of the filesystems space that should be free
+ FREE_LIMIT="0.2"
+
+ # users and groups allowed to work with config
+ ALLOW_USERS=""
+ ALLOW_GROUPS=""
+
+ # sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots
+ # directory
+ SYNC_ACL="no"
+
+ # start comparing pre- and post-snapshot in background after creating
+ # post-snapshot
+ BACKGROUND_COMPARISON="yes"
+
+ # run daily number cleanup
+ NUMBER_CLEANUP="yes"
+
+ # limit for number cleanup
+ NUMBER_MIN_AGE="1800"
+ NUMBER_LIMIT="100"
+ NUMBER_LIMIT_IMPORTANT="10"
+
+ # create hourly snapshots
+ TIMELINE_CREATE="yes"
+
+ # cleanup hourly snapshots after some time
+ TIMELINE_CLEANUP="yes"
+
+ # limits for timeline cleanup
+ TIMELINE_MIN_AGE="1800"
+ TIMELINE_LIMIT_HOURLY="24"
+ TIMELINE_LIMIT_DAILY="7"
+ TIMELINE_LIMIT_WEEKLY="4"
+ TIMELINE_LIMIT_MONTHLY="12"
+ TIMELINE_LIMIT_YEARLY="10"
+
+ # cleanup empty pre-post-pairs
+ EMPTY_PRE_POST_CLEANUP="yes"
+
+ # limits for empty pre-post-pair cleanup
+ EMPTY_PRE_POST_MIN_AGE="1800"
+ '';
+ };
+ in mapAttrs snapperConfig cfg.snapperSubvols;
+ };
+}