summary refs log tree commit diff
path: root/nixos/modules/config/swap.nix
diff options
context:
space:
mode:
authorNikolay Amiantov <ab@fmap.me>2015-10-18 21:20:46 +0300
committerNikolay Amiantov <ab@fmap.me>2015-10-20 15:56:12 +0300
commitde8b8b35a41b2f1611be5da4697ab39a6d2fa2e3 (patch)
tree5c51d32185eea335f341ea51ad35315ac450e60c /nixos/modules/config/swap.nix
parent5c56b7e526db1865ffd5a3d5040774e308267132 (diff)
downloadnixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.tar
nixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.tar.gz
nixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.tar.bz2
nixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.tar.lz
nixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.tar.xz
nixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.tar.zst
nixlib-de8b8b35a41b2f1611be5da4697ab39a6d2fa2e3.zip
nixos/swap: refactor, add randomEncryption option
Diffstat (limited to 'nixos/modules/config/swap.nix')
-rw-r--r--nixos/modules/config/swap.nix167
1 files changed, 102 insertions, 65 deletions
diff --git a/nixos/modules/config/swap.nix b/nixos/modules/config/swap.nix
index 1dc7ebb96aff..9a5d6a9fc333 100644
--- a/nixos/modules/config/swap.nix
+++ b/nixos/modules/config/swap.nix
@@ -3,6 +3,84 @@
 with utils;
 with lib;
 
+let
+
+  swapCfg = {config, options, ...}: {
+
+    options = {
+
+      device = mkOption {
+        example = "/dev/sda3";
+        type = types.str;
+        description = "Path of the device.";
+      };
+
+      label = mkOption {
+        example = "swap";
+        type = types.str;
+        description = ''
+          Label of the device.  Can be used instead of <varname>device</varname>.
+        '';
+      };
+
+      size = mkOption {
+        default = null;
+        example = 2048;
+        type = types.nullOr types.int;
+        description = ''
+          If this option is set, ‘device’ is interpreted as the
+          path of a swapfile that will be created automatically
+          with the indicated size (in megabytes) if it doesn't
+          exist.
+        '';
+      };
+
+      priority = mkOption {
+        default = null;
+        example = 2048;
+        type = types.nullOr types.int;
+        description = ''
+          Specify the priority of the swap device. Priority is a value between 0 and 32767.
+          Higher numbers indicate higher priority.
+          null lets the kernel choose a priority, which will show up as a negative value.
+        '';
+      };
+
+      randomEncryption = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Encrypt swap device with a random key. This way you won't have a persistent swap device.
+
+          WARNING: Don't try to hibernate when you have at least one swap partition with
+          this option enabled! We have no way to set the partition into which hibernation image
+          is saved, so if your image ends up on an encrypted one you would lose it!
+        '';
+      };
+
+      deviceName = mkOption {
+        type = types.str;
+        internal = true;
+      };
+
+      realDevice = mkOption {
+        type = types.path;
+        internal = true;
+      };
+
+    };
+
+    config = rec {
+      device = mkIf options.label.isDefined
+        "/dev/disk/by-label/${config.label}";
+      deviceName = escapeSystemdPath config.device;
+      realDevice = if config.randomEncryption then "/dev/mapper/${deviceName}" else config.device;
+    };
+
+  };
+
+in
+
 {
 
   ###### interface
@@ -26,58 +104,7 @@ with lib;
         recommended.
       '';
 
-      type = types.listOf types.optionSet;
-
-      options = {config, options, ...}: {
-
-        options = {
-
-          device = mkOption {
-            example = "/dev/sda3";
-            type = types.str;
-            description = "Path of the device.";
-          };
-
-          label = mkOption {
-            example = "swap";
-            type = types.str;
-            description = ''
-              Label of the device.  Can be used instead of <varname>device</varname>.
-            '';
-          };
-
-          size = mkOption {
-            default = null;
-            example = 2048;
-            type = types.nullOr types.int;
-            description = ''
-              If this option is set, ‘device’ is interpreted as the
-              path of a swapfile that will be created automatically
-              with the indicated size (in megabytes) if it doesn't
-              exist.
-            '';
-          };
-
-          priority = mkOption {
-            default = null;
-            example = 2048;
-            type = types.nullOr types.int;
-            description = ''
-              Specify the priority of the swap device. Priority is a value between 0 and 32767.
-              Higher numbers indicate higher priority.
-              null lets the kernel choose a priority, which will show up as a negative value.
-            '';
-          };
-
-        };
-
-        config = {
-          device = mkIf options.label.isDefined
-            "/dev/disk/by-label/${config.label}";
-        };
-
-      };
-
+      type = types.listOf (types.submodule swapCfg);
     };
 
   };
@@ -95,27 +122,37 @@ with lib;
 
         createSwapDevice = sw:
           assert sw.device != "";
-          let device' = escapeSystemdPath sw.device; in
-          nameValuePair "mkswap-${escapeSystemdPath sw.device}"
-          { description = "Initialisation of Swapfile ${sw.device}";
-            wantedBy = [ "${device'}.swap" ];
-            before = [ "${device'}.swap" ];
-            path = [ pkgs.utillinux ];
+          let realDevice' = escapeSystemdPath sw.realDevice;
+          in nameValuePair "mkswap-${sw.deviceName}"
+          { description = "Initialisation of swap device ${sw.device}";
+            wantedBy = [ "${realDevice'}.swap" ];
+            before = [ "${realDevice'}.swap" ];
+            path = [ pkgs.utillinux ] ++ optional sw.randomEncryption pkgs.cryptsetup;
             script =
               ''
-                if [ ! -e "${sw.device}" ]; then
-                  fallocate -l ${toString sw.size}M "${sw.device}" ||
-                    dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
-                  chmod 0600 ${sw.device}
-                  mkswap ${sw.device}
-                fi
+                ${optionalString (sw.size != null) ''
+                  if [ ! -e "${sw.device}" ]; then
+                    fallocate -l ${toString sw.size}M "${sw.device}" ||
+                      dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
+                    chmod 0600 ${sw.device}
+                    ${optionalString (!sw.randomEncryption) "mkswap ${sw.realDevice}"}
+                  fi
+                ''}
+                ${optionalString sw.randomEncryption ''
+                  echo "secretkey" | cryptsetup luksFormat --batch-mode ${sw.device}
+                  echo "secretkey" | cryptsetup luksOpen ${sw.device} ${sw.deviceName}
+                  cryptsetup luksErase --batch-mode ${sw.device}
+                  mkswap ${sw.realDevice}
+                ''}
               '';
             unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
             unitConfig.DefaultDependencies = false; # needed to prevent a cycle
             serviceConfig.Type = "oneshot";
+            serviceConfig.RemainAfterExit = sw.randomEncryption;
+            serviceConfig.ExecStop = optionalString sw.randomEncryption "cryptsetup luksClose ${sw.deviceName}";
           };
 
-      in listToAttrs (map createSwapDevice (filter (sw: sw.size != null) config.swapDevices));
+      in listToAttrs (map createSwapDevice (filter (sw: sw.size != null || sw.randomEncryption) config.swapDevices));
 
   };