🔍 Context
As system administrators and security-conscious developers, encrypting data at rest is a fundamental best practice—especially for laptops, servers in untrusted environments, or sensitive workloads. Full Disk Encryption (FDE) ensures that all data on the disk is encrypted, and can only be accessed after providing a unlocking key, thus safeguarding data even if physical access to the disk is obtained.
By leveraging cloud-init's autoinstall YAML, we can fully automate the provisioning process—including LUKS encryption, LVM setup, and embedding a drive unlocking key into the initramfs.
🛠️ Implementation Overview
Here’s a high-level overview of what we will be doing:
- Use LUKS to encrypt the main data partition.
- Inside the encrypted container, create a LVM volume group to manage the logical volumes.
- Generate a random key file early in the installation process, which is used to unlock the encrypted volume.
- Ensured this key is securely copied into the target system and embedded into the
initramfs
so the system can boot without manual passphrase entry.
đź§Ş Workflow
- Early Commands: Generate a 4KB random keyfile (
root.key
) under/etc/cryptsetup-keys.d
, with appropriate permissions.
early-commands:
- mkdir -p /etc/cryptsetup-keys.d
- dd if=/dev/urandom of=/etc/cryptsetup-keys.d/root.key bs=1024 count=4
- chmod 600 /etc/cryptsetup-keys.d/root.key
- Storage config: The disk was partitioned into:
- An EFI system partition (
/boot/efi
) - An unencrypted
/boot
partition - A third partition for encrypted data.
- An EFI system partition (
Create a LUKS-encrypted volume on the third partition using the key file. On top of that, create a LVM volume group (VolGroup) and allocate a root logical volume (lv_root).
storage:
config:
- ptable: gpt
match:
size: smallest
wipe: superblock-recursive
preserve: false
name: ''
grub_device: true
id: disk-sda
type: disk
- device: disk-sda
size: 536870912 # 512MB
wipe: superblock
flag: boot
number: 1
preserve: false
grub_device: true
id: partition-0
type: partition
- fstype: fat32
volume: partition-0
preserve: false
id: format-0
type: format
- path: /boot/efi
device: format-0
id: mount-0
type: mount
- device: disk-sda
size: 1073741824 # 1GB
wipe: superblock
number: 2
preserve: false
grub_device: false
id: partition-1
type: partition
- fstype: ext4
volume: partition-1
preserve: false
id: format-1
type: format
- path: /boot
device: format-1
id: mount-1
type: mount
- device: disk-sda
size: -1
wipe: superblock
number: 3
preserve: false
grub_device: false
id: partition-2
type: partition
- name: cryptlvm
volume: partition-2
preserve: false
keyfile: /etc/cryptsetup-keys.d/root.key
id: dm_crypt-lvm
type: dm_crypt
- name: VolGroup
devices:
- dm_crypt-lvm
preserve: false
id: lvm_volgroup-0
type: lvm_volgroup
- name: lv_root
volgroup: lvm_volgroup-0
size: -1
wipe: superblock
preserve: false
id: lvm_partition-root
type: lvm_partition
- fstype: ext4
volume: lvm_partition-root
preserve: false
id: format-root
type: format
- path: /
device: format-root
id: mount-root
type: mount
- Late Commands:
- Extract the UUID of the LUKS volume and copy the key file into
/etc/cryptsetup-keys.d
inside the target filesystem, renaming it to match the UUID. - Update
/etc/crypttab
to ensure the system knows how to unlock the encrypted volume during boot. - Add the appropriate hook configuration for
cryptsetup-initramf
s and rebuilt theinitramfs
so the key file will be included and accessible early in the boot process.
- Extract the UUID of the LUKS volume and copy the key file into
late-commands:
- mkdir -p /target/etc/cryptsetup-keys.d /target/etc/cryptsetup-initramfs
- bash -c '
luks_uuid=$(blkid -t TYPE=crypto_LUKS -s UUID -o value);
cp /etc/cryptsetup-keys.d/root.key "/target/etc/cryptsetup-keys.d/${luks_uuid}.key";
chmod 600 "/target/etc/cryptsetup-keys.d/${luks_uuid}.key";
echo "dm_crypt-lvm UUID=${luks_uuid} /etc/cryptsetup-keys.d/${luks_uuid}.key luks" > /target/etc/crypttab;
echo "KEYFILE_PATTERN=/etc/cryptsetup-keys.d/*.key" >> /target/etc/cryptsetup-initramfs/conf-hook;
'
- curtin in-target --target=/target -- update-initramfs -c -k all
âś… Conclusion
With this setup, we successfully created a secure, automated Ubuntu installation with full disk encryption using LUKS and LVM. The system boots without requiring a passphrase, thanks to the securely handled key file integrated into the initramfs
.
This makes the setup highly suitable for hands-off provisioning in secure environments.
Looking ahead, this foundation can be extended to further enhance security by:
- Binding the LUKS key to a TPM after installation to enable secure, passphrase-free unlocks based on hardware identity.
- Integrating with Secure Boot and measured boot for a trusted boot chain.
Top comments (0)