summaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-08-08 03:53:33 -0600
committerAlejandro Soto <alejandro@34project.org>2022-08-08 03:55:09 -0600
commit829102167e61ece218c33b83141b81b78cdf6087 (patch)
treec904377da29368698be9edfbf5f3d23332533648 /sys/fs
parentf86be644309028046732c254fb5d0e80bc58dfff (diff)
sys/fs: move fs config out of sys/default.nix
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/btrfs.nix111
-rw-r--r--sys/fs/default.nix21
-rw-r--r--sys/fs/layout.nix77
3 files changed, 209 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;
+ };
+}
diff --git a/sys/fs/default.nix b/sys/fs/default.nix
new file mode 100644
index 0000000..9f2f646
--- /dev/null
+++ b/sys/fs/default.nix
@@ -0,0 +1,21 @@
+{ lib, config, ... }:
+with lib; let
+ cfg = config.local;
+in {
+ imports = [ ./btrfs.nix ./layout.nix ];
+
+ options.local.fs.boot.device = with lib.types; mkOption {
+ type = str;
+ };
+
+ config = {
+ # !!!
+ boot.tmpOnTmpfs = true;
+
+ fileSystems."/boot" = {
+ inherit (cfg.fs.boot) device;
+ fsType = "vfat";
+ options = [ "noatime" "umask=027" ];
+ };
+ };
+}
diff --git a/sys/fs/layout.nix b/sys/fs/layout.nix
new file mode 100644
index 0000000..999492d
--- /dev/null
+++ b/sys/fs/layout.nix
@@ -0,0 +1,77 @@
+{ lib, config, ... }:
+with lib; let
+ cfg = config.local;
+in {
+ options.local.fs.layout = with lib.types; {
+ sysHddBtrfs = mkOption {
+ default = null;
+
+ type = nullOr (submodule {
+ options = {
+ sys = {
+ device = mkOption {
+ type = str;
+ };
+
+ ssd = mkOption {
+ type = bool;
+ };
+
+ root = mkOption {
+ type = str;
+ };
+
+ toplevel = mkOption {
+ type = str;
+ };
+ };
+
+ hdd = {
+ device = mkOption {
+ type = str;
+ };
+
+ home = mkOption {
+ type = str;
+ };
+ };
+ };
+ });
+ };
+ };
+
+ config = {
+ local.fs.btrfs = let
+ sysHddBtrfs = layout: {
+ "/" = {
+ inherit (layout.sys) device ssd;
+ subvol = layout.sys.root;
+ };
+
+ "/toplevel" = {
+ inherit (layout.sys) device ssd;
+ subvol = layout.sys.toplevel;
+ };
+
+ "/hdd" = {
+ inherit (layout.hdd) device;
+ subvol = "/";
+ ssd = false;
+ };
+
+ "/home" = {
+ inherit (layout.hdd) device;
+ subvol = layout.hdd.home;
+ ssd = false;
+ snapper = "home";
+ };
+ };
+
+ inherit (cfg.fs) layout;
+
+ layoutMaps = [ sysHddBtrfs ];
+ layoutOpts = [ layout.sysHddBtrfs ];
+ valid = filter ({ snd, ... }: snd != null) (zipLists layoutMaps layoutOpts);
+ in optionalAttrs (valid != []) ((head valid).fst (head valid).snd);
+ };
+}