Configure Full-Disk Encryption (FDE)#
This guide walks you through enabling full-disk encryption (FDE) for your target OS image using ICT. ICT encrypts the partitions you select with LUKS2 during the image build, and the encrypted volumes are unlocked at boot.
Prerequisites#
Linux environment
ICT tool configured
A
rawimage template (target.imageType: raw) with defined disk partitionscryptsetup-binin the package list (present in the default OS package sets)Basic understanding of Image Templates and your image’s partition IDs
How It Works#
FDE is applied in two phases:
Build time: After the OS is installed, ICT encrypts each selected partition in place with LUKS2 (using
cryptsetup reencrypt), reopens it as a/dev/mapper/<id>device, and continues the build against the decrypted volume.Boot time: ICT wires the boot configuration so the encrypted volumes are unlocked. The root volume is unlocked from the kernel command line (
rd.luks.*); additional volumes are unlocked from/etc/crypttab.
Configuration Structure#
The fde section is placed under systemConfig in your image template YAML
file, alongside other system configuration options:
systemConfig:
name: my-image
# ... other system configuration
fde:
enabled: true
passphraseFile: "/path/to/fde-passphrase.txt"
unlock: auto
partitions:
- rootfs
Field Reference#
Field |
Type |
Required |
Description |
|---|---|---|---|
|
bool |
Yes |
Enable full-disk encryption. Default: |
|
string |
Yes (when |
Absolute or template-relative local file path containing passphrase material. File must be non-empty. |
|
string[] |
No |
Disk partition IDs to encrypt (for example |
|
string |
No |
Boot unlock mode: |
The partition IDs must exist in the merged disk configuration (OS defaults plus
your template). The ESP (boot) is never encrypted, and dm-verity hash
partitions must stay plaintext (see below).
Example: FDE Only#
A minimal FDE template encrypts the root filesystem:
systemConfig:
name: edge
fde:
enabled: true
passphraseFile: "/run/secrets/fde-passphrase.txt"
unlock: auto
partitions:
- rootfs
packages:
- ubuntu-minimal
- systemd-boot
- dracut-core
- systemd
- cryptsetup-bin
See image-templates/ubuntu24-x86_64-fde.yml
for a complete working example.
Example: FDE with Immutability (dm-verity)#
FDE can coexist with the dm-verity immutable root (see Configure Secure Boot for the related Secure Boot setup). In this mode LUKS is opened first, then dm-verity runs over the decrypted mapper.
The default raw layout contains a plaintext ESP, the root filesystem, a verity hash partition, and a mutable data partition:
flowchart LR
boot["boot (ESP, plaintext)"]
rootfs["rootfs (LUKS)"]
hash["roothashmap (plaintext)"]
userdata["userdata (LUKS, optional)"]
verity["dm-verity root"]
mounts["/var /home /opt"]
boot --> rootfs
rootfs --> verity
hash --> verity
userdata --> mounts
To encrypt both the root and the mutable data partition:
systemConfig:
name: edge
immutability:
enabled: true
fde:
enabled: true
passphraseFile: "/run/secrets/fde-passphrase.txt"
unlock: manual
partitions:
- rootfs
- userdata
Key rules for FDE with immutability:
Encrypt
rootfs(required to protect the root) anduserdatawhen you want the mutable state (/var,/home,/opt) encrypted as well.Do not list
roothashmap(or any hash partition withmountPoint: none) underfde.partitions. It must stay plaintext for the verityroothash=parameter; encrypting it results in a boot into emergency mode.At runtime the order is: LUKS opens the root, dm-verity stacks on
/dev/mapper/rootfs, and any additional volumes (such asuserdata) are unlocked from/etc/crypttab.
Unlock Modes#
Mode |
Boot experience |
Security note |
|---|---|---|
|
No prompt. A shared keyfile at |
Convenient, but the secret ships on the ESP/initramfs, so this is not strong confidentiality against an attacker with physical access. |
|
The passphrase is entered interactively at boot. The root volume prompts via |
The passphrase is not stored in the initramfs. Expect one prompt per encrypted volume. |
When auto unlock adds the keyfile, the passphrase keyslot is retained as a
fallback, so you can still unlock interactively for recovery.
Validate and Build#
Validate the template before building:
image-composer-tool validate your-template.yml
Then build the image as usual. Validation fails if fde.enabled is true but
no non-empty passphraseFile is provided.
Verify on the Device#
After booting, confirm the selected partitions are encrypted with lsblk. Each
encrypted partition ID appears as a crypt mapper, while the ESP and any verity
hash partition remain plaintext:
lsblk
sda
├─sda1 part /boot/efi
├─sda2 part
│ └─rootfs 252:0 crypt
│ └─root 252:1 crypt /
├─sda3 part # roothashmap (plaintext)
└─sda4 part
└─userdata 252:2 crypt /opt # only if listed in fde.partitions
In manual mode, expect one passphrase prompt per encrypted volume.
Security Best Practices#
Never commit real passphrases to version control. Use a placeholder in the template path only, and provide the real secret in a local file during build.
Prefer
manualunlock when a stronger boot policy is required; the passphrase is not embedded in the image.Treat
autounlock as a convenience feature: the keyfile lives on the ESP and in the initramfs, so it does not protect against physical extraction.Plan for recovery: the passphrase keyslot is kept as a fallback even in
automode.
Note: When ICT logs the merged template at debug level, the
systemConfig.fde.passphraseFileand resolved passphrase values are redacted as[REDACTED], so they do not leak into build logs.
Limitations#
FDE applies to
rawimages with defineddisk.partitionsIDs.The in-place reencryption path currently supports ext4 filesystems only.
The ESP (
boot) is not encrypted by design.
Troubleshooting#
Common Issues:
Validation error about a missing passphrase file: Set a non-empty
passphraseFilewhenfde.enabledistrue.Build fails with “partition has no device in the disk map”: The partition ID under
fde.partitionsdoes not exist in the merged disk configuration. Use IDs from the disk layout (for examplerootfs,userdata).Boot drops into emergency mode with immutability: Make sure the verity hash partition (
roothashmap) is not listed underfde.partitions.Data partition is still unencrypted: With immutability, the mutable
userdatapartition is only encrypted when you add it explicitly tofde.partitions.