Setting up encrypted volumes with LUKS: Difference between revisions

From Alpine Linux
(Updated the links and formatted them in a list)
(Add section about decrypting root with a keydisk)
 
(14 intermediate revisions by 8 users not shown)
Line 1: Line 1:
See:
[https://en.wikipedia.org/wiki/Linux%20Unified%20Key%20Setup LUKS] allows encrypting a partition and mapping it as a virtual block device, which can then be used as a normal partition. Guides for other Linux distributions should serve as a general references for installing Alpine onto a LUKS encrypted disk.
 
The following approaches are known to work:
 
* Plain LUKS
* [[LVM on LUKS]]
* [[LVM on LUKS]]
The installer has built-in support for encryption, and will automatically enable LVM to encrypt swap partitions, but it will not encrypt the boot partition. The [[Bootloaders#GRUB|GRUB]] bootloader supports BIOS and EFI boot with an encrypted boot partition.
== mkinitfs and LUKS ==
For those familiar with setting up FDE on other Linux distributions, this section contains only Alpine-specific knowledge required and understanding [[mkinitfs]].
First of all, the <code>cryptsetup</code> feature needs to be added to {{path|/etc/mkinitfs/mkinitfs.conf}}. Additionally, the following kernel parameters are required:
* <code>cryptroot</code> kernel parameter should point to the encrypted block device.
* <code>cryptdm</code>: the name that will be given to the device.
* <code>root</code> kernel parameter should point to the mapped block device: <code>/dev/mapper/<name used in cryptdm></code>.
* <code>rootfstype</code>: the filesystem type of the root partition (e.g.: <code>btrfs</code>).
For example, if you use grub with GPT partition table using ext4 without LVM the {{path|/etc/default/grub}} file will be as follows:{{Cat|/etc/default/grub|<nowiki>GRUB_TIMEOUT=2
GRUB_DISABLE_SUBMENU=y
GRUB_DISABLE_RECOVERY=true
GRUB_CMDLINE_LINUX_DEFAULT="modules=sd-mod,usb-storage,ext4 quiet rootfstype=ext4 cryptroot=UUID=a7dc90c4-6746-417e-b25b-cb8769ee6334 cryptdm=alpine-rootfs  root=/dev/mapper/alpine-rootfs"
GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt"
GRUB_ENABLE_CRYPTODISK=y
</nowiki>}}
== Decrypting non-root volumes during boot ==
{{Main|LVM on LUKS#Mounting additional encrypted filesystems at boot}}
To have an encrypted non-root volume be decrypted prior to automatically mounting it somewhere via <code>/etc/fstab</code>,  configure <code>dmcrypt</code> in the {{path|/etc/conf.d/dmcrypt}} file. The comments inside that file should guide you, but as a simple example, here's what you should include in that file to decrypt and map a partition to some volume named, say, “<code>myvolume</code>”, given its UUID (here represented using a series of <code>X</code>s), using a passphrase {{Cat|/etc/conf.d/dmcrypt|<nowiki>...
target=myvolume
source=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX
key=/etc/keys/myvolume.key  #not needed as passphrase is used in this example
...</nowiki>}}
In {{path|/etc/fstab}} file, then, you would include the following line as follows:{{Cat|/etc/fstab|<nowiki>...
/dev/mapper/myvolume <path> <fstype> <options>
...</nowiki>}}
substituting in the proper parameters.
Do not forget to enable the <code>localmount</code> service:
<code>rc-update add localmount</code>
Otherwise they will not be mounted automatically.
== Decrypting root with a removable device ==
The [[Initramfs init|initramfs]] can be configured to read the disk decryption key from a storage device inserted at boot time. While [https://wiki.archlinux.org/title/Dm-crypt/System_configuration#cryptkey Arch's cryptkey] is able to read the key from a regular file on an external disk, our [https://manned.org/man/alpine-3.23/mkinitfs-bootparam.7 cryptkey syntax] is currently limited to the bitstream format — i.e. raw data.
The syntax is <code><var>device</var>:<var>offset</var>:<var>size</var></code>.
* <var>device</var> is an fstab-style identifier (e.g. <code>UUID=<var>uuid</var></code>, <code>/dev/disk/by-label/<var>label</var></code>).
* <var>offset</var> is the exact location on the disk where the keyfile begins, expressed in bytes.
* <var>size</var> is the size of the keyfile, in bytes.
=== Generate the keyfile ===
Create an empty file and set its permissions.
{{Cmd|touch keyfile.bin && chmod 600 keyfile.bin}}
In this example, the key will be 256 bytes long, generated from {{path|/dev/urandom}}.
{{Cmd|<nowiki>dd if=/dev/urandom of=keyfile.bin bs=256 count=1</nowiki>}}
Add the keyfile as a new slot to the LUKS volume.
{{Cmd|cryptsetup luksAddKey <var>device</var> keyfile.bin}}
=== Prepare the keydisk ===
Choose a removable storage device to use as a key; and, if needed, securely erase it.
Because we will need to refer to the device using an fstab-style identifier, '''it will have to be formatted with any filesystem'''. Something simple, like FAT32, will do. But beware: '''do not ever mount this filesystem'''. Its only purpose is to provide an identifier.
Pick a location (in bytes) where the key will be written. As we're using a 256-byte key, it's easier to choose a multiple of 256 (e.g. <code>256 bytes * 100,000 = 25,600,000 bytes</code> — about 25 MB into the disk).
{{Cmd|<nowiki>dd if=keyfile.bin of=device obs=25600000 seek=1</nowiki>}}
Because writing raw data like this over an existing filesystem has a risk of corrupting it, it's a good idea to run a <code>fsck</code> right now. If it finds errors, reformat and pick another location to write the keyfile.
Now verify that you can retrieve the key from the disk.
{{Cmd|<nowiki>dd if=device of=keyfile_check.bin bs=256 count=1 skip=100000
# Compare the checksums
sha256sum keyfile.bin
sha256sum keyfile_check.bin
</nowiki>}}
=== Configure the initramfs ===
Add the feature <code>cryptkey</code> to {{Path|/etc/mkinitfs/mkinitfs.conf}}.
{{Cat|/etc/mkinitfs/mkinitfs.conf|<nowiki>features="... cryptsetup cryptkey"
</nowiki>}}
Set the kernel command-line option <code>cryptkey</code> in your bootloader.
e.g. <code>cryptkey=UUID=<var>keydisk_uuid</var>:25600000:256</code>
Finally, [[Initramfs_init#Usage|regenerate the initramfs]].
== See also ==
* [[LVM on LUKS]]
* [[mkinitfs|Initramfs init]]
* [[Full disk encryption secure boot]]
* [[Setting up a laptop|Setting up a secured laptop]]
* [https://wiki.archlinux.org/index.php/Dm-crypt dm-crypt on ArchWiki]
* [https://wiki.archlinux.org/index.php/Dm-crypt dm-crypt on ArchWiki]


[[Category:Storage]]
[[Category:Storage]]
[[Category:Security]]
[[Category:Security]]

Latest revision as of 03:41, 4 May 2026

LUKS allows encrypting a partition and mapping it as a virtual block device, which can then be used as a normal partition. Guides for other Linux distributions should serve as a general references for installing Alpine onto a LUKS encrypted disk.

The following approaches are known to work:

The installer has built-in support for encryption, and will automatically enable LVM to encrypt swap partitions, but it will not encrypt the boot partition. The GRUB bootloader supports BIOS and EFI boot with an encrypted boot partition.

mkinitfs and LUKS

For those familiar with setting up FDE on other Linux distributions, this section contains only Alpine-specific knowledge required and understanding mkinitfs.

First of all, the cryptsetup feature needs to be added to /etc/mkinitfs/mkinitfs.conf. Additionally, the following kernel parameters are required:

  • cryptroot kernel parameter should point to the encrypted block device.
  • cryptdm: the name that will be given to the device.
  • root kernel parameter should point to the mapped block device: /dev/mapper/<name used in cryptdm>.
  • rootfstype: the filesystem type of the root partition (e.g.: btrfs).

For example, if you use grub with GPT partition table using ext4 without LVM the /etc/default/grub file will be as follows:

Contents of /etc/default/grub

GRUB_TIMEOUT=2 GRUB_DISABLE_SUBMENU=y GRUB_DISABLE_RECOVERY=true GRUB_CMDLINE_LINUX_DEFAULT="modules=sd-mod,usb-storage,ext4 quiet rootfstype=ext4 cryptroot=UUID=a7dc90c4-6746-417e-b25b-cb8769ee6334 cryptdm=alpine-rootfs root=/dev/mapper/alpine-rootfs" GRUB_PRELOAD_MODULES="luks cryptodisk part_gpt" GRUB_ENABLE_CRYPTODISK=y

Decrypting non-root volumes during boot

To have an encrypted non-root volume be decrypted prior to automatically mounting it somewhere via /etc/fstab, configure dmcrypt in the /etc/conf.d/dmcrypt file. The comments inside that file should guide you, but as a simple example, here's what you should include in that file to decrypt and map a partition to some volume named, say, “myvolume”, given its UUID (here represented using a series of Xs), using a passphrase

Contents of /etc/conf.d/dmcrypt

... target=myvolume source=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX key=/etc/keys/myvolume.key #not needed as passphrase is used in this example ...

In /etc/fstab file, then, you would include the following line as follows:

Contents of /etc/fstab

... /dev/mapper/myvolume <path> <fstype> <options> ...

substituting in the proper parameters.

Do not forget to enable the localmount service:

rc-update add localmount

Otherwise they will not be mounted automatically.

Decrypting root with a removable device

The initramfs can be configured to read the disk decryption key from a storage device inserted at boot time. While Arch's cryptkey is able to read the key from a regular file on an external disk, our cryptkey syntax is currently limited to the bitstream format — i.e. raw data.

The syntax is device:offset:size.

  • device is an fstab-style identifier (e.g. UUID=uuid, /dev/disk/by-label/label).
  • offset is the exact location on the disk where the keyfile begins, expressed in bytes.
  • size is the size of the keyfile, in bytes.

Generate the keyfile

Create an empty file and set its permissions.

touch keyfile.bin && chmod 600 keyfile.bin

In this example, the key will be 256 bytes long, generated from /dev/urandom.

dd if=/dev/urandom of=keyfile.bin bs=256 count=1

Add the keyfile as a new slot to the LUKS volume.

cryptsetup luksAddKey device keyfile.bin

Prepare the keydisk

Choose a removable storage device to use as a key; and, if needed, securely erase it.

Because we will need to refer to the device using an fstab-style identifier, it will have to be formatted with any filesystem. Something simple, like FAT32, will do. But beware: do not ever mount this filesystem. Its only purpose is to provide an identifier.

Pick a location (in bytes) where the key will be written. As we're using a 256-byte key, it's easier to choose a multiple of 256 (e.g. 256 bytes * 100,000 = 25,600,000 bytes — about 25 MB into the disk).

dd if=keyfile.bin of=device obs=25600000 seek=1

Because writing raw data like this over an existing filesystem has a risk of corrupting it, it's a good idea to run a fsck right now. If it finds errors, reformat and pick another location to write the keyfile.

Now verify that you can retrieve the key from the disk.

dd if=device of=keyfile_check.bin bs=256 count=1 skip=100000 # Compare the checksums sha256sum keyfile.bin sha256sum keyfile_check.bin

Configure the initramfs

Add the feature cryptkey to /etc/mkinitfs/mkinitfs.conf.

Contents of /etc/mkinitfs/mkinitfs.conf

features="... cryptsetup cryptkey"

Set the kernel command-line option cryptkey in your bootloader.

e.g. cryptkey=UUID=keydisk_uuid:25600000:256

Finally, regenerate the initramfs.

See also