It took me about 6 hours to find out all of this, but after reading a ton of man pages, initram scripts, and bug reports, I got a working result that takes about 2' to set up...
The point is to have a SWAP partition encrypted with LUKS, and it should be decypted during boot.
When using SysV, initram hooks and scripts in Debian worked like a charm but then, Systemd came and it's not yet fully implemented so this kind of crap happens. Systemd's cryptsetup doesn't support parameters in /etc/crypttab
so using a script there is ignored:
/* Options Debian's crypttab knows we don't:
precheck=
check=
checkargs=
noearly=
loud=
keyscript=
*/
Trying to decrypt SWAP partition via /etc/crypttab
ends up usable but it can't resume from hibernation because Systemd tries to open it way too late, so the kernel gives up looking for a SWAP. To make it work, you need to pass parameters to the kernel, which Systemd will elegantly take.
Here's the whole deal (read everything first before starting doing things):
Let's say that your encrypted root partition is at /dev/disk/by-partlabel/root
and your SWAP, /dev/disk/by-partlabel/swap
(here I used GPT partition labels, you can also use UUID). I'll be naming cryptoroot
and cryptoswap
to the opened devices (accesible via /dev/mapper/...
).
1- Edit or create /etc/initramfs-tools/conf.d/resume
:
RESUME=/dev/mapper/cryptoswap
2- Remove references to SWAP in /etc/crypttab
, i.e. a line like cryptoswap /dev/disk... /dev/urandom swap
must be commented out or deleted.
3- Edit /etc/default/grub
to set the kernel parameters for resume device and encryption:
GRUB_CMDLINE_LINUX="resume=/dev/mapper/cryptoswap cryptopts=source=/dev/disk/by-partlabel/root,target=cryptoroot cryptopts=source=/dev/disk/by-partlabel/swap,target=cryptoswap"
4- Update initramfs and grub: sudo update-initramfs -u && sudo update-grub
Up to this point, you will need a password to open both devices, which is horribly anoying. However, a neat script, provided by cryptsetup, can be used: decypt_derived
, which derives a key from an opened device (say, the root device). So, here's what you need to do (skip previous 3rd and 4th steps):
3- Add derived key to SWAP: sudo cryptsetup luksAddKey /dev/disk/by-partlabel/swap <(/lib/cryptsetup/scripts/decrypt_derived cryptoroot)
Verify that it worked: cryptsetup -v --test-passphrase -d <(/lib/cryptsetup/scripts/decrypt_derived cryptoroot) luksOpen /dev/disk/by-partlabel/swap
4- Edit /etc/default/grub
:
GRUB_CMDLINE_LINUX="resume=/dev/mapper/cryptoswap cryptopts=source=/dev/disk/by-partlabel/root,target=cryptoroot cryptopts=source=/dev/disk/by-partlabel/swap,target=cryptoswap,keyscript=/lib/cryptsetup/scripts/decrypt_derived,key=cryptoroot"
Double-check device and partition names!
5- Add an initram hook to copy decypt_derived binary to the initramfs, create the file /etc/initramfs-tools/hooks/cp_decrypt_derived
:
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
# Begin real processing below this line
copy_exec /lib/cryptsetup/scripts/decrypt_derived /lib/cryptsetup/scripts/ >&2
6- Update initramfs and grub: sudo update-initramfs -u && sudo update-grub
That's it! You can hibernate with systemctl hibernate
(no need for sudo). If you use a keyfile for the root partition, the same can be done by pointing the kernel to an appropriate keyscript that reads and pushes the key, and a hook that copies said script into initramfs.
Sources
- https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1451032
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=618862
- https://news.ycombinator.com/item?id=8477913
- http://manpages.ubuntu.com/manpages/zesty/man8/initramfs-tools.8.html
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=475838
- http://www.matthew.ath.cx/articles/cryptkey
Hi,
Yes - swap and root on different partitions. For me (can't speak for @HacKanCuBa ). I wanted a separated swap partition because I was sharing the swap between multiple distros on the same drive and also my root was zfsonlinux, which at the time didn't play nice with native swap encryption. I believe lvm on luks will also work (swap, root etc being on the lvm) with this method, but it may not be necessary as I think lvm on luks is the "standard" encyption method and just setting your RESUME variable and including the drive in crypttab would tke care of things (assuming you have lvm2 installed and the module loaded at boot which I think deb takes care of for you). Anyway - haven't tried that for a while - pretty sure there are lots of tutorial on this. I'm no longer using this boot method, but incase you're interested... how about this for one massive mouthful of a boot line (fyi - I'd also encrypted the boot partition on this machine!):