diff --git a/nixos/modules/config/swap.nix b/nixos/modules/config/swap.nix
index 1dc7ebb96af..9a5d6a9fc33 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 device.
+ '';
+ };
+
+ 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 device.
- '';
- };
-
- 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));
};
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index ace2d10ec9c..fe34e822728 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -206,7 +206,7 @@ let
preLVMCommands postDeviceCommands postMountCommands kernelModules;
resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}")
- (filter (sd: sd ? label || hasPrefix "/dev/" sd.device) config.swapDevices);
+ (filter (sd: (sd ? label || hasPrefix "/dev/" sd.device) && !sd.randomEncryption) config.swapDevices);
fsInfo =
let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType fs.options ];
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index 9dd250f140c..dbe0c9c6e03 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -174,7 +174,7 @@ in
# Swap devices.
${flip concatMapStrings config.swapDevices (sw:
- "${sw.device} none swap${prioOption sw.priority}\n"
+ "${sw.realDevice} none swap${prioOption sw.priority}\n"
)}
'';