From 92fcc3cd4fc50bba1b2b2d95f8bed4e0a5a03136 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Mon, 9 Apr 2018 12:24:09 +0200 Subject: lvm snapshots --- custom/btrfs-snapshots.nix | 4 ++ custom/lvm-snapshots.nix | 95 ++++++++++++++++++++++++++++++++++++++++++++++ odin.nix | 10 +++++ 3 files changed, 109 insertions(+) create mode 100644 custom/lvm-snapshots.nix diff --git a/custom/btrfs-snapshots.nix b/custom/btrfs-snapshots.nix index 44b08740..9dc3f1f8 100644 --- a/custom/btrfs-snapshots.nix +++ b/custom/btrfs-snapshots.nix @@ -40,6 +40,10 @@ in { config = mkIf cfg.enable { + system.activationScripts."btrfs-snapshots" = '' + mkdir -p ${mountPoint} + ''; + systemd.services."btrfs-snapshot@" = { enable = true; diff --git a/custom/lvm-snapshots.nix b/custom/lvm-snapshots.nix new file mode 100644 index 00000000..67ee2cbd --- /dev/null +++ b/custom/lvm-snapshots.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.lvm-snapshots; + + snapshotMount = name: "${cfg.mountPoint}/${if isNull cfg.snapshots."${name}".mountName then name else cfg.snapshots."${name}".mountName}"; + + snapshotConfig = { + options = { + LV = mkOption { + type = types.str; + }; + + VG = mkOption { + type = types.str; + }; + + mountName = mkOption { + type = types.nullOr types.str; + default = null; + }; + + cowSize = mkOption { + type = types.str; + default = "-l20%ORIGIN"; + }; + + readOnly = mkOption { + type = types.bool; + default = true; + }; + + persist = mkOption { + type = types.bool; + default = false; + }; + }; + }; +in { + options = { + + services.lvm-snapshots = { + snapshots = mkOption { + type = types.attrsOf (types.submodule snapshotConfig); + default = {}; + }; + + mountPoint = mkOption { + type = types.path; + default = "/mnt"; + }; + }; + }; + + + config = mkIf (cfg != {}) { + + system.activationScripts = mapAttrs' (name: scfg: nameValuePair (lvm-mountpoint + name) '' + mkdir -p ${snapshotMount name} + '') cfg.snapshots; + + systemd.services = mapAttrs' (name: scfg: nameValuePair ("lvm-snapshot@" + name) { + enable = true; + + unitConfig = { + StopWhenUnneeded = true; + }; + + serviceConfig = with pkgs; { + Type = "oneshot"; + ExecStart = "${devicemapper}/bin/lvcreate -s ${cfg.cowSize} --name ${name} ${scfg.VG}/${scfg.LV}"; + ExecStop = "${devicemapper}/bin/lvremove ${scfg.VG}/${name}"; + RemainAfterExit = true; + }; + }) cfg.snapshots; + + systemd.mounts = mapAttrsToList (name: scfg: { + enable = true; + + unitConfig = { + AssertPathIsDirectory = snapshotMount name; + StopWhenUnneeded = !scfg.persist; + }; + + bindsTo = "lvm-snapshot@" + name; + + options = mkIf scfg.readOnly "ro"; + + where = snapshotMount name; + what = "/dev/" + scfg.VG + "/" + name; + }) cfg.snapshots; + }; +} diff --git a/odin.nix b/odin.nix index 437810b0..50fd557a 100644 --- a/odin.nix +++ b/odin.nix @@ -11,6 +11,7 @@ ./users.nix ./custom/uucp.nix ./custom/uucp-mediaserver.nix + ./custom/lvm-snapshots.nix ]; # Use the GRUB 2 boot loader. @@ -147,6 +148,15 @@ networks = ["127.0.0.0/8" "[::ffff:127.0.0.0]/104" "[::1]/128" "10.141.0.0/16"]; }; + services.lvm-snapshots = { + snapshots = { + snapshot-mail = { + LV = "mail"; + VG = "raid6"; + }; + }; + }; + system.autoUpgrade.enable = true; system.stateVersion = "18.09"; -- cgit v1.2.3