Merge pull request #10464 from abbradar/encrypted-swap

nixos/swap: refactor, add randomEncryption option
This commit is contained in:
Nikolay Amiantov 2015-10-30 11:49:46 +03:00
commit 00f79aab90
3 changed files with 104 additions and 67 deletions

View File

@ -3,32 +3,9 @@
with utils;
with lib;
{
let
###### interface
options = {
swapDevices = mkOption {
default = [];
example = [
{ device = "/dev/hda7"; }
{ device = "/var/swapfile"; }
{ label = "bigswap"; }
];
description = ''
The swap devices and swap files. These must have been
initialised using <command>mkswap</command>. Each element
should be an attribute set specifying either the path of the
swap device or file (<literal>device</literal>) or the label
of the swap device (<literal>label</literal>, see
<command>mkswap -L</command>). Using a label is
recommended.
'';
type = types.listOf types.optionSet;
options = {config, options, ...}: {
swapCfg = {config, options, ...}: {
options = {
@ -69,15 +46,65 @@ with lib;
'';
};
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!
'';
};
config = {
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
options = {
swapDevices = mkOption {
default = [];
example = [
{ device = "/dev/hda7"; }
{ device = "/var/swapfile"; }
{ label = "bigswap"; }
];
description = ''
The swap devices and swap files. These must have been
initialised using <command>mkswap</command>. Each element
should be an attribute set specifying either the path of the
swap device or file (<literal>device</literal>) or the label
of the swap device (<literal>label</literal>, see
<command>mkswap -L</command>). Using a label is
recommended.
'';
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 =
''
${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}
mkswap ${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));
};

View File

@ -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 ];

View File

@ -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"
)}
'';