Difference between revisions of "Full Disk Encryption From Scratch"

From Gentoo Wiki
Jump to:navigation Jump to:search
(→‎Passphrase secured LUKS encryption: add info for adding a passphrase to a keyfile secured luks volume)
(Add info that dracut + systemd requires systemd to have the cryptsetup flag)
Tag: visualeditor-switched
Line 432: Line 432:
 
add_dracutmodules+=" crypt crypt-gpg dm rootfs-block "
 
add_dracutmodules+=" crypt crypt-gpg dm rootfs-block "
 
}}
 
}}
 +
 +
If using systemd for your init, you must also add the '''cryptsetup''' use flag
 +
 +
{{FileBox|filename=/etc/portage/package.use/systemd|1=
 +
sys-apps/systemd cryptsetup
 +
}}
 +
 +
And rebuild
 +
 +
{{RootCmd|emerge --ask --newuse sys-apps/systemd}}
  
 
{{Important|If a smartcard is used to store the private keys for a GPG encrypted key file, {{path|/etc/dracut.conf.d/crypt-public-key.gpg}} must be configured to contain the corresponding public key.}}
 
{{Important|If a smartcard is used to store the private keys for a GPG encrypted key file, {{path|/etc/dracut.conf.d/crypt-public-key.gpg}} must be configured to contain the corresponding public key.}}

Revision as of 05:51, 19 June 2023

Full disk encryption can be used to help protect data integrity and privacy. dm-crypt can be used to to configure drives to be encrypted with LUKS or other formats. This article is a guide which covers the process of configuring a drive to be encrypted using LUKS with LVM. This process can be done as part of a fresh install, or could be performed on a new drive to migrate an existing install.

Installation

Emerge

root #emerge --ask sys-fs/cryptsetup

Additional software

Important
If using LVM, sys-fs/lvm2 must be installed with the lvm USE flag.
root #USE=lvm emerge --ask sys-fs/lvm2

If using GPG to further secure key files:

root #emerge --ask app-crypt/gnupg

System preparation

Important
The kernel must be configured according to: Dm-crypt: Kernel Configuration.

If this is being followed as part of a fresh Gentoo install, the install procedure can be followed until the following step: AMD64 Handbook: Designing a partition scheme

If converting an existing system to an encrypted setup, either new storage must be added, or this procedure could be used to create new partitions using free space, where the data can then be copied after creation.

Warning
Depending on the type of drive, it can be difficult or impossible to truly overwrite portions of the drive where unencrypted, but de-referenced data exists. It is best to do a secure erase using the drive's firmware before re-using it.
Tip
If migrating an existing install to an encrypted root filesystem, the existing bootloader partition itself does not need to be modified (unless desired), but the bootloader configuration will need modification to boot from the new encrypted partitions.

Disk preparation

Important
Partitioning typically does not involve modification of any of the data in partitions. If a drive is re-partitioned then encrypted, old data may remain in an unencrypted form until it is overwritten.
Note
Modern storage devices may not be securely erased with something like dd if=/dev/urandom of=/dev/sdX.
See also
For more information, see: Secure wipe.

This example will use GPT as disk partition schema and GRUB as boot loader. parted will be used as the partitioning tool though any partitioning utility will work.

See also
For more information about GPT and EFI, see Disks (AMD64 Handbook).

Create disk partitions

A common setup for a basic system with a single drive may contain a partition for the boot files, and a partition for the system root.

Note
This is technically not "Full Disk Encryption" but it makes much more sense to sign than encrypt boot files.
CODE
'"`UNIQ--pre-00000004-QINU`"'
Tip
Any filesystem type can be used for the LVM partitions, in most cases, FAT32 must be used for the EFI/boot partitions.

For proper full disk encryption, using a separate boot drive:

CODE
'"`UNIQ--pre-00000007-QINU`"'
Tip
Using an external storage device, such as a USB drive, may make sense to use as a boot drive.
Note
The size of the EFI partition is somewhat important, some devices will not boot using partitions which are too small (typically due to sector sizes[1]) , 512MB typically works.

Create partitions using parted

To create the a partition table like the first example, the following commands can be used:

root@localhost #parted -a optimal /dev/sda
Note
-a optimal tells parted to align partitions to physical blocks to optimize performance.

To set the default unit to mebibytes:

(parted)unit mib

To create a GPT partition table:

(parted)mklabel gpt

To create the boot partition, which will contain boot files, such as the bootloader, kernel, and initramfs:

(parted)mkpart primary fat32 1 513
(parted)name 1 boot
(parted)set 1 esp on
(parted)set 1 boot on
Important
Many, but not all systems will not EFI boot a partition without the esp and boot flags set.
Warning
Setting the partition type in the partition table is mostly superficial, this does not format the partition and is helpful but not required information. Some tools may use this information, but it is not universally respected.
(parted)mkpart primary 513 -1
(parted)name 2 luks
Note
Parted does not have a partition type for luks partitions, none should be set.

The disk partitioning is done. To exit, writing changes, use parted:

(parted)quit

Create partitions using fdisk

To create a partition layout like the second example (true full disk encryption) using fdisk, start by creating a fresh partition table on the root disk:

root #fdisk /dev/nvme0n1
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x81391dbc.

Command (m for help): g
Created a new GPT disklabel (GUID: 8D91A3C1-8661-2940-9076-65B815B36906).

With a partition table crated, a new partition spanning the drive can be created by using n and then accepting the defaults:

Command (m for help):n
Partition number (1-128, default 1): 
First sector (2048-1953525134, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1953525134, default 1953523711): 

Created a new partition 1 of type 'Linux filesystem' and of size 931.5 GiB.

Finally, the changes can be written with w:

Command (m for help):w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

The boot disk can be setup using a similar process, the main difference is the boot flags will be set as a final step:

root #fdisk /dev/sda1
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x81391dbc.

Command (m for help): g

Created a new GPT disklabel (GUID: 3E57DFCE-CDD9-6F42-8418-F0B6B4A08294).

With a fresh partition table, a 512mb partition can be created using:

Command (m for help):n
Partition number (1-128, default 1): 
First sector (2048-121008094, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-121008094, default 121006079): +512M

Created a new partition 1 of type 'Linux filesystem' and of size 512 MiB.

Finally, the ESP properties can be set using t:

Command (m for help):t
Selected partition 1
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.

Changes can be written with w:

Command (m for help):Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Create the LUKS encrypted partition

To prepare the encrypted filesystem, dm-crypt can be used:

Note
To ensure the dm-crypt module is loaded, the following command can be used:
root #modprobe dm-crypt

The status of the module can be checked with:

user $lsmod | grep dm-crypt
Tip
More advanced usage information is available in man cryptsetup-luksFormat.
Tip
dm-crypt can do far more than LUKS configuration, more usage information is available on the wiki page.
Important
Only specify arguments like --cipher if certain that it improves security beyond the sane defaults.

Passphrase secured LUKS encryption

The most basic way to configure an encrypted volume is to use:

root #cryptsetup luksFormat --key-size 512 /dev/nvme0n1p1
WARNING!
========
This will overwrite data on /dev/nvme0n1p1 irrevocably.

Are you sure? (Type 'yes' in capital letters): 
YES
Enter passphrase for /dev/sda2:
Note
For a bit of additional security, the key size can be increased to 512 bits with --key-size 512.
Warning
A keyfile is typically considered to be more secure than a password, but should be password protected. An attacker must have the keyfile and know the password to break the drive's encryption.
Tip
Luks can allow multiple keys/passwords to be used to decrypt a partition. This can potentially decrease security, if password is wanted to recovery purposes, consider using a long passphrase and writing it down, or storing it offline.
Adding a Passphrase to Volume Using GPG Secured Key Files

To add a passphrase to a volume which is already secured using key files, a named pipe must be used for the key file contents:

root #mkfifo key_pipe

Then the key can be decrypted to this pipe:

root #gpg --decrypt key_file > key_pipe &

A passphrase can be added with:

root #cryptsetup luksAddKey --key-file key_pipe /dev/nvme0n1p1

The named pipe can be cleaned up with:

root #rm key_pipe

Key File Secured Encryption

Tip
cryptsetup --help reveals the builtin key size and character size limit. The default is 8388608, or 8192 * 1024 (2^23).
Important
Key files should be stored some place other than the devices they encrypt. A key file is a possession security factor, while passwords or passphrases are knowledge factors. What good is a lock if the keys are attached to it?
Warning
Take great care of this key file, if it is lost, the entire encrypted partition will be inaccessible, if it is stolen, the data is no longer safe.
Tip
Using GPG to encrypt the key file can help keep it safe, adding a knowledge factor to it.
Key File Creation

A basic key file can be created using dd and /dev/urandom:

/tmp/ #dd bs=8388608 count=1 if=/dev/urandom of=crypt_key.luks
1+0 records in
1+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.014407 s, 582 MB/s
Important
Take great care when storing this key file. If it is ever written to unencrypted storage, it can be difficult to ensure it cannot be recovered, even if deleted.
GPG Symmetrically Encrypted Key File

For increased security, the key file can be immediately encrypted with GPG.

Warning
Symmetric encryption, using a password, is a simple method that works on most systems, but is vulnerable to keylogging, similarly to simple password/passphrase based protection.
Important
If using the Gentoo install ISO, it may be necessary to run
root #export GPG_TTY=$(tty)
to GPG encrypt data directly from stdout. Alternatively, --pinentry-mode loopback can be added as an argument to use stdin pintentry, however, this does not confirm the entry.
/media/sda1/ #dd bs=8388608 count=1 if=/dev/urandom | gpg --symmetric --cipher-algo AES256 --output crypt_key.luks.gpg
1+0 records in
1+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 7.50139 s, 1.1 MB/s
GPG Asymmetrically Encrypted Key File

A key file can be protected using public key cryptography using a smartcard such as a YubiKey. This YubiKey GPG guide can be used to generate GPG keys on a YubiKey. With the public keys loaded, keys can be encrypted with they key holder as the recipient:

/media/sda1/ #dd bs=8388608 count=1 if=/dev/urandom | gpg --recipient larry@gentoo.org --output crypt_key.luks.gpg --encrypt
1+0 records in
1+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 7.50139 s, 1.1 MB/s
Important
Dracut must be configured to use the corresponding public key, this is covered in the Dracut section.

When booting, ensure the smartcard is inserted. Dracut will prompt for the PIN, and depending on the configuration, the device may need to be tapped to complete presence detection.

luksFormat Using a Key File

To encrypt the partition using this key file:

/media/sda1/ #cryptsetup --key-size 512 luksFormat /dev/nvme0n1p1 crypt_key.luks
WARNING!
========
This will overwrite data on /dev/nvme0n1p1 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES

To add this keyfile to an already encrypted partition:

/media/sda1/ #cryptsetup luksAddKey /dev/nvme0n1p1 crypt_key.luks
Enter any existing passphrase: 
luksFormat Using a GPG protected keyfile

To encrypt the partition for the LVM container using the GPG protected key file:

/media/sda1/ #gpg --decrypt crypt_key.luks.gpg | cryptsetup luksFormat --key-size 512 /dev/nvme0n1p1 -
gpg: AES256.CFB encrypted data
WARNING!
========
This will overwrite data on /dev/nvme0n1p1 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES

To add the GPG encrypted keyfile to an already encrypted partition, named pipes must be used to avoid decrypting the key to disk, as both gpg and cryptsetup and expecting input from stdin:

/media/sda1/ #mkfifo crypt_key
/media/sda1/ #mkfifo cryptsetup_pass

Once the files are created, the key must be decrypted to crypt_key, and the recovery passhprase must be passed to cryptsetup_pass:

/media/sda1/ #gpg --decrypt crypt_key.luks.gpg > crypt_key &
/media/sda1/ #read -s -r -p 'LUKS passphrase: ' CRYPT_PASS; echo "$CRYPT_PASS" > cryptsetup_pass &

Finally, cat can be used to pass this information to cryptsetup:

/media/sda1/ #cat cryptsetup_pass crypt_key | cryptsetup luksAddKey /dev/nvme0n1p1 -
gpg: AES256.CFB encrypted data
gpg: encrypted with 1 passphrase
[1]-  Done                    read -s -r -p 'LUKS passphrase: ' CRYPT_PASS; echo "$CRYPT_PASS" > cryptsetup_pass
[2]+  Done                    gpg -d crypt_key.luks.gpg > crypt_key
Tip
LUKS key status can be checked with cryptsetup luksDump {device}, ex. cryptsetup luksDump /dev/nvme0n1p1.
Note
The named pipes can now be deleted.

LUKS Header Backup

Important
Do not forget this step, keys/passwords are used to decrypt the LUKS header, if it is destroyed for some reason, the remaining data will only be recoverable with the header file.

The headers can be backed up with:

root #cryptsetup luksHeaderBackup /dev/nvme0n1p1 --header-backup-file crypt_headers.img

Open the LUKS volume

The encrypted device must be opened and mapped before it can be used, this can be done with:

root #cryptsetup luksOpen /dev/nvme0n1p1 crypt

If using a key file:

/media/sda1/ #cryptsetup --key-file=crypt_key.luks open /dev/nvme0n1p1 crypt

If using a GPG encrypted key file:

/media/sda1/ #gpg --decrypt crypt_key.luks.gpg | cryptsetup --key-file=- open /dev/nvme0n1p1 crypt
Note
This command opens /dev/nvme0n1p1 and maps it under /dev/mapper/ with the name crypt.

Configure LVM inside of the LUKS volume

Tip
LVM is not required, if not used, LUKS partitions for each mount point, such as /, /home, and /var in this example, can be created. If no disk quotas are being enforced, there is no issue in using a single root partition. For more information about LVM, see the LVM page
Note
One advantage of using LVM inside of LUKS is that the entire partition is encrypted, which doesn't reveal any information about how the underlying data is structured. LUKS volumes being any size but the size of the entire disk can possibly indicate the type of data contained.

To create the LVM structure used in this example, with logical volumes for (/root, /var, and /home):

The physical volume can be created on the opened LUKS volume with:

root #lvm pvcreate /dev/mapper/crypt

The volume group vg0 can be created wtih:

root #vgcreate vg0 /dev/mapper/crypt

The logical volumes for /root, /var, and /home can be created with:

root #lvcreate -L 64G -n root vg0
root #lvcreate -L 64G -n var vg0
root #lvcreate -l 100%FREE -n home vg0

Format the Filesystems

Create a filesystem for /dev/sda1, the boot partition which will contain GRUB and kernel files. This partition is read by UEFI. Most motherboards can read only a FAT32 filesystem:

root #mkfs.vfat -F32 /dev/sda1

If LVM is not being used, the LUKS volume can be formatted with btrfs using:

root #mkfs.btrfs -L rootfs /dev/mapper/crypt

If LVM is being used, to format each logical volume with the btrfs filesystem:

root #mkfs.btrfs -L rootfs /dev/mapper/vg0-root
root #mkfs.btrfs -L var /dev/mapper/vg0-var
root #mkfs.btrfs -L homedir /dev/mapper/vg0-home
Note
The labels are optional, but helpful. They allow for easy mounting without a UUID.

Initramfs configuration

An initramfs must be used to decrypt and mount the root partition. This can be accomplished using a minimal custom one, using a few commands, or using a tool like dracut to decrypt using parameters passed in the kernel command line.

Dracut

Note
This configuration should be done while chrooted, or on a live system.

The following modules must be added to the add_dracutmodules directive in /etc/dracut.conf:

FILE /etc/dracut.confMinimum required components to decrypt LUKS volumes using dracut
add_dracutmodules+=" crypt dm rootfs-block "

If GPG keys are being used, the following module must also be added: crypt-gpg

FILE /etc/dracut.confMinimum required components to decrypt LUKS volumes using dracut
add_dracutmodules+=" crypt crypt-gpg dm rootfs-block "

If using systemd for your init, you must also add the cryptsetup use flag

FILE /etc/portage/package.use/systemd
sys-apps/systemd cryptsetup

And rebuild

root #emerge --ask --newuse sys-apps/systemd
Important
If a smartcard is used to store the private keys for a GPG encrypted key file, /etc/dracut.conf.d/crypt-public-key.gpg must be configured to contain the corresponding public key.
Important
The spacing for Dracut configuration directives is very important. Ensure there are no spaces between add_dracutmodules and +=", parameters in add_dracutmodules must be padded with spaces.

Once Dracut is configured, a new initramfs can be generated by running:

root #dracut
Important
Dracut writes the file to /boot by default, this must be mounted.

If the initramfs is being generated for a kernel other than the currently active one, --kver must be used:

root #dracut --kver 6.1.28-gentoo

This can happen in a situation when the kernel version in the Gentoo Live CD differs from the emerged sys-kernel/gentoo-sources in the kernel compilation process.

Tip
Possible kernel versions can be found by using ls /lib/modules.

Dracut has now generated an initramfs, but configuration is not complete. Command line parameters must be set, either by manually adding them to the kernel, or by configuring them into the bootloader.

Tip
Most dracut configuration is described in man dracut.cmdline.

Extracting the initramfs

It's possible to use dracut to generate an initramfs image, then extract this to be built into the kernel.

/usr/src/initramfs #/usr/lib/dracut/skipcpio /boot/initramfs-6.1.28-gentoo-initramfs.img | zcat | cpio -ivd

Embedding the initramfs

With the initramfs extracted to /usr/src/initramfs, the kernel can be configured to embed it:

KERNEL Embed the initramfs into the kernel
General Setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
    (/usr/src/initramfs) Initramfs source file(s)
[*]   Support initial ramdisk/ramfs compressed using gzip

.config equivalent:

CODE .config configuration for an embedded initramfs
CONFIG_INITRAMFS_SOURCE="/usr/src/initramfs"
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
CONFIG_RD_GZIP=y
CONFIG_INITRAMFS_COMPRESSION_GZIP=y

With this configuration, the kernel will automatically embed whatever exists under /usr/src/initramfs into the kernel when it is built, and attempt to use it on boot. This is especially useful when Secure Booting.

Note
If using a kernel which requires modules to boot, the initramfs must be recreated after the kernel is built once, extracted, then the kernel must be rebuilt to embed the latest initramfs. The rebuild should be very quick unless using make clean.
Important
If using this method with GRUB, be sure to delete or move the dracut generate initramfs img if using GRUB so grub-mkconfig does not get confused.

Bootloader configuration

The Linux cmdline parameters must be updated to support LVM and an encrypted root, the partition uuid may be used. This can be obtained with:

root #lsblk -o name,uuid
NAME        UUID
sda
└─sda1      044502df-6f
nvme0n1         
└─nvme0n1p1 5e0022f4-e1c9-4b58-b53e-25d3cd417451
Note
In this example sda1 is any other storage used to store the key files/bootloader. The key files and bootloader do not need to be on the same storage.

GRUB Configuration

Important
This configuration must be done in the later portions of a fresh Gentoo install, typically as one of the final steps.
FILE /etc/default/grubEncrypted root with dracut initramfs and a GPG encrypted key file crypt_key.luks.gpg on /dev/sda1
'"`UNIQ--pre-00000026-QINU`"'

With this configuration adjustment, the EFI System Partition must be mounted, where new GRUB configuration can be generated:

root #grub-mkconfig --output /boot/grub/grub.cfg
Tip
More detailed information on installation and configuration is available on the GRUB page.

EFI Stub

If using an EFI stub with an embedded initramfs command line arguments can be configured with:

Example kernel commandline configuration:

KERNEL Embed the Kernel command line
'"`UNIQ--pre-00000029-QINU`"'

.config equivalent:

CODE .config configuration for an embedded kernel command line
'"`UNIQ--pre-0000002C-QINU`"'

Once the kernel has been compiled and installed, efibootmgr can be used to add it to the boot list with:

root #efibootmgr --create --disk /dev/sda --label "Signed Gentoo EFI Stub" --loader vmlinuz-6.3.4-gentoo-r1-initramfs.signed
Note
This example uses a signed EFI stub for Secure Boot.

Gentoo installation

If this procedure is being followed during a Gentoo install (in place of Handbook:AMD64/Full/Installation#Designing_a_partition_scheme through Handbook:AMD64/Full/Installation#Mounting_the_root_partition), the following steps can be used to mount the created partition, to continue with the install.

Mount the root partition

The logical volume for the root file system can be mounted at this created location with:

root #mount /dev/mapper/vg0-root /mnt/gentoo

fstab configuration

Important
The correct fstab file must be edited, if this is being done before chrooting, ensure the correct path is being used. More information exists in the filesystem portion of the install guide.

For consistent volume mounting, labels and UUIDs must be used.

Block devices and their associated partition IDs can be viewed with:

root #lsblk -o name,uuid
NAME        UUID
sda
└─sda1      044502df-6f
nvme0n1         
└─nvme0n1p1 5e0022f4-e1c9-4b58-b53e-25d3cd417451

With the partition UUIDs and labels identified, /etc/fstab can be edited to add relevant mounts:

FILE /mnt/gentoo/etc/fstab
'"`UNIQ--pre-00000030-QINU`"'

Mount the var partition

Mount points for /var must be created with:

root #mkdir /mnt/gentoo/var

Once created, the logical volume can be mounted with:

root #mount /dev/mapper/vg0-var /mnt/gentoo/var

Mount the home partition (optional)

Note
If you are making changes to the home partition (like adding a user) in the chroot, that volume can be mounted with:
root #mkdir /mnt/gentoo/home
root #mount /dev/mapper/vg0-home /mnt/gentoo/home/

Finalizing the Gentoo install

Important
The general install guide should apply. A few considerations must be made, the initial RAM filesystem must be built with support for decrypting the root partition, and dmcrypt must be configured to mount other partitions.

At this point, the Gentoo install can be continued normally: Installing a stage tarball

Additional information

SSD tricks

Warning
Using SSDs and also hybrid drives sacrifices some cryptographic security for speed-improvement and lower power consumption. See FAQs of cryptsetup for the details. Plan with drive's degradation and loss of space over time. With or without trim physical destruction of the drive is necessary. There are no guarantees that overwriting really changes bits in the drive's memory chips. This is not a problem of cryptsetup, LUKS or the kernel but caused by the firmware/ hardware/ vendor- and model-specific algorithms.

SSD trim allows an operating system to inform a solid-state drive (SSD) which blocks of data are no longer considered in use and can be wiped internally. Because low-level operation of SSDs differs significantly from hard drives, the typical way in which operating systems handle operations like deletes and formats resulted in unanticipated progressive performance degradation of write operations on SSDs. Trimming enables the SSD to more efficiently handle garbage collection, which would otherwise slow future write operations to the involved blocks. To enable SSD trim of encrypted root filesystem on LVM, edit the /etc/default/grub file if using genkernel:

FILE /etc/default/grub
GRUB_CMDLINE_LINUX="...root_trim=yes"

If using dracut to generate the intiramfs the use:

FILE /etc/default/grub
GRUB_CMDLINE_LINUX="...rd.luks.allow-discards"

If using systemd-based initramfs the use:

FILE /etc/default/grub
GRUB_CMDLINE_LINUX="...rd.luks.options=discard"

This will notify the kernel to enable trim on roots.

Edit the /etc/lvm/lvm.conf configuration file:

FILE /etc/lvm/lvm.conf
issue_discards = 1

This will notify LVM layer to enable SSD trim.

When using SSDs and UEFI-boot the boot sequence might be too fast. When entering the correct passphrase, the kernel will complain about missing modules or no root device. Try to add rootdelay=3 to GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub, or directly append it in edit mode of the GRUB menu when booting.

Automatically mount an encrypted volume at boot

At boot, the service dmcrypt reads the configuration file /etc/conf.d/dmcrypt and gets a list of targets (devices) that should be mapped. After succesfully mapping and creating a mapped device at /dev/mapper/*, fstab will mount the device from /dev/mapper/* to some mount point.

First, create the directory that will contain the keys for encryption and decryption of the devices:

root@localhost:/#mkdir /etc/keyfiles
root@localhost:/#chmod 0400 /etc/keyfiles

Create 4KiB keyfile with name /etc/keyfiles/main:

root@localhost:/#dd if=/dev/urandom of=/etc/keyfiles/main bs=1024 count=4
root@localhost:/#chmod 0400 /etc/keyfiles/main

Add the /etc/keyfiles/main keyfile to the list of keys, that can decrypt the disk (technically: add the keyfile to the LUKS slot):

root@localhost:/#cryptsetup luksAddKey /dev/sdX /etc/keyfiles/main

Find the UUID of the encrypted disk with the blkid command. For example, blkid can return the following output:

root@localhost:/#blkid
/dev/sda1: UUID="91d7fd8f-fa64-42f3-8491-ba9464c0c064" TYPE="crypto_LUKS" PARTLABEL="media" PARTUUID="2e1aa997-7295-4e00-b03d-de0317c25342"
/dev/sda5: UUID="281c3e94-f195-47fc-b604-7b3d8c38a513" TYPE="crypto_LUKS" PARTLABEL="data" PARTUUID="7c41cc1a-b68b-4eae-97a9-9a28be10c6c3"
/dev/sdb1: UUID="4F20-B9DB" TYPE="vfat" PARTLABEL="grub" PARTUUID="70b1627b-57e7-4559-877a-355184f0ab9d"
/dev/sdb2: UUID="DB1D-89C5" TYPE="vfat" PARTLABEL="boot" PARTUUID="b2a61809-4c19-4685-8875-e7fdf645eec5"
/dev/sdb3: UUID="6a7a642a-3262-4f87-9540-bcd53969343b" TYPE="crypto_LUKS" PARTLABEL="lvm" PARTUUID="be8e6694-b39c-4d2f-9f42-7ca455fdd64f"
/dev/mapper/root: UUID="HL32bg-ZjrZ-RBo9-PcFM-DmaQ-QbrC-9HkNMk" TYPE="LVM2_member"
/dev/mapper/vg0-root: UUID="6bedbbd8-cea9-4734-9c49-8e985c61c120" TYPE="ext4"
/dev/mapper/vg0-var: UUID="61e4cc83-a1ee-4190-914b-4b62b49ac77f" TYPE="ext4"
/dev/mapper/vg0-home: UUID="5d6ff087-50ce-400f-91c4-e3378be23c00" TYPE="ext4"
/dev/mapper/data: UUID="4be7f323-3f7e-47c7-91a3-b37d04e951aa" TYPE="ext4"
/dev/mapper/media: UUID="943629b6-391d-441a-adf1-13fcb0471fd3" TYPE="ext4"

Note the filesystem labeled as crypto_LUKS type.

In this example, /dev/sda1 is encrypted with the /etc/keys/main key.

Configure the dmcrypt service. The dmcrypt service opens the LUKS encrypted device with /etc/keys/main key and maps it with some name. For example:

Edit file /etc/conf.d/dmcrypt:

FILE /etc/conf.d/dmcrypt
target='data'
source=UUID='91d7fd8f-fa64-42f3-8491-ba9464c0c064'
key='/etc/keyfiles/main'

In this example, dmcrypt will open the block device with UUID 91d7fd8f-fa64-42f3-8491-ba9464c0c064 with key /etc/keys/main and create a mapped mount point at /dev/mapper/data.

Check that dmcrypt works fine. Start the service manually:

root@localhost:/#/etc/init.d/dmcrypt start

If dmcrypt started without problems, there are no errors in /var/log/messages, and the mapped device /dev/mapper/data exists, then everything is fine and the dmcrypt service may be added to be started at the boot step.

Add dmcrypt to be started at boot:

root@localhost:/#rc-update add dmcrypt boot

Add to fstab where and how the mapped device should be mounted.

Find the UUID of the mapped devices. Execute the blkid command and find the UUID of mapped device /dev/mapper/data:

root@localhost:/#blkid
/dev/sda1: UUID="91d7fd8f-fa64-42f3-8491-ba9464c0c064" TYPE="crypto_LUKS" PARTLABEL="media" PARTUUID="2e1aa997-7295-4e00-b03d-de0317c25342"
/dev/sda5: UUID="281c3e94-f195-47fc-b604-7b3d8c38a513" TYPE="crypto_LUKS" PARTLABEL="data" PARTUUID="7c41cc1a-b68b-4eae-97a9-9a28be10c6c3"
/dev/sdb1: UUID="4F20-B9DB" TYPE="vfat" PARTLABEL="grub" PARTUUID="70b1627b-57e7-4559-877a-355184f0ab9d"
/dev/sdb2: UUID="DB1D-89C5" TYPE="vfat" PARTLABEL="boot" PARTUUID="b2a61809-4c19-4685-8875-e7fdf645eec5"
/dev/sdb3: UUID="6a7a642a-3262-4f87-9540-bcd53969343b" TYPE="crypto_LUKS" PARTLABEL="lvm" PARTUUID="be8e6694-b39c-4d2f-9f42-7ca455fdd64f"
/dev/mapper/root: UUID="HL32bg-ZjrZ-RBo9-PcFM-DmaQ-QbrC-9HkNMk" TYPE="LVM2_member"
/dev/mapper/vg0-root: UUID="6bedbbd8-cea9-4734-9c49-8e985c61c120" TYPE="ext4"
/dev/mapper/vg0-var: UUID="61e4cc83-a1ee-4190-914b-4b62b49ac77f" TYPE="ext4"
/dev/mapper/vg0-home: UUID="5d6ff087-50ce-400f-91c4-e3378be23c00" TYPE="ext4"
/dev/mapper/data: UUID="4be7f323-3f7e-47c7-91a3-b37d04e951aa" TYPE="ext4"
/dev/mapper/media: UUID="943629b6-391d-441a-adf1-13fcb0471fd3" TYPE="ext4"

In the example below, the UUID of the mapped device /dev/mappper/data is 4be7f323-3f7e-47c7-91a3-b37d04e951aa.

Important
Don't forget to start dmcrypt before this step.

Add those mapped devices to /etc/fstab. Edit /etc/fstab and add a row with the UUID, mount point, and filesystem type of the mapped device. For example:

FILE /etc/fstab
# encrypted devices
UUID=4be7f323-3f7e-47c7-91a3-b37d04e951aa       /mnt/data     ext4      defaults        0 2

Here UUID is the identifyer of the mapped device /dev/mapper/data, /mnt/data is the mount point, and ext4 is the filesystem type of the mapped device.

See also