containerd doesn’t actually encrypt your container images on disk itself. Instead, it relies on the underlying filesystem or block device to provide encryption.
Here’s how you can make that happen:
Let’s say you’re running containerd on a Linux system. The most straightforward way to encrypt your container images at rest is by encrypting the entire storage device that containerd uses for its data. This is typically /var/lib/containerd.
The kernel module dm-crypt combined with LUKS (Linux Unified Key Setup) is the standard way to achieve this. You’ll be creating an encrypted block device and then mounting a filesystem on top of it, which will house your containerd data.
Setting Up LUKS Encryption
First, you need a dedicated block device. This could be a spare partition, a whole disk, or even a loop device backed by a file for testing. For this example, let’s assume you have a partition at /dev/sdb1.
-
Create a LUKS container:
sudo cryptsetup luksFormat /dev/sdb1This will prompt you to enter a passphrase twice. Choose a strong passphrase! This is the key to your encrypted data.
-
Open the LUKS container:
sudo cryptsetup luksOpen /dev/sdb1 encrypted_containerd_storageYou’ll be prompted for the passphrase you just set. This creates a new block device at
/dev/mapper/encrypted_containerd_storage. -
Format the new block device: Now, format this newly opened device with a filesystem like
ext4orxfs.sudo mkfs.ext4 /dev/mapper/encrypted_containerd_storage -
Mount the encrypted filesystem: Create a mount point and mount the filesystem.
sudo mkdir /mnt/encrypted_containerd sudo mount /dev/mapper/encrypted_containerd_storage /mnt/encrypted_containerd
Configuring containerd to Use the Encrypted Storage
Now, you need to tell containerd to use this new, encrypted directory for its data.
-
Stop containerd:
sudo systemctl stop containerd -
Move existing data (if any): If you have existing container images, you’ll want to move them to the new location.
sudo rsync -avP /var/lib/containerd/ /mnt/encrypted_containerd/Important: Ensure
rsynccompletes successfully before proceeding. -
Update containerd’s configuration: The
containerdconfiguration file is typically located at/etc/containerd/config.toml. You need to change therootdirectory. Find the[root]section and modify it:[root] path = "/mnt/encrypted_containerd" # ... other optionsIf the
[root]section doesn’t exist, you can add it. -
Automate mounting on boot: To ensure your encrypted storage is mounted every time the system boots, you need to add an entry to
/etc/crypttaband/etc/fstab.-
/etc/crypttab: This file tells the system how to set up encrypted devices. Add this line:encrypted_containerd_storage /dev/sdb1 /etc/cryptsetup-keys/containerd.key luksNote: For true automation without manual passphrase entry on boot, you’d typically use a key file. This example uses a key file for demonstration, but be extremely careful about securing this key file. A more secure approach for production might involve TPM-backed keys or manual passphrase entry.
To create a key file (for testing, ensure it’s kept secure!):
sudo mkdir /etc/cryptsetup-keys sudo dd if=/dev/urandom of=/etc/cryptsetup-keys/containerd.key bs=512 count=4 sudo chmod 0400 /etc/cryptsetup-keys/containerd.key sudo cryptsetup luksAddKey /dev/sdb1 /etc/cryptsetup-keys/containerd.keyYou’ll be prompted for your LUKS passphrase to add the key.
-
/etc/fstab: This file tells the system how to mount filesystems. Add this line:/dev/mapper/encrypted_containerd_storage /var/lib/containerd ext4 defaults 0 2Self-correction: The previous step mounted to
/mnt/encrypted_containerd. It’s more conventional to mount the final filesystem directly to/var/lib/containerdafter the encrypted device is opened. Let’s adjust.Revised Steps:
-
Create a LUKS container:
sudo cryptsetup luksFormat /dev/sdb1Enter passphrase.
-
Add a key file (secure it!):
sudo mkdir /etc/cryptsetup-keys sudo dd if=/dev/urandom of=/etc/cryptsetup-keys/containerd.key bs=512 count=4 sudo chmod 0400 /etc/cryptsetup-keys/containerd.key sudo cryptsetup luksAddKey /dev/sdb1 /etc/cryptsetup-keys/containerd.keyEnter LUKS passphrase.
-
Update
/etc/crypttab:encrypted_containerd_storage /dev/sdb1 /etc/cryptsetup-keys/containerd.key luks -
Update
/etc/fstab:/dev/mapper/encrypted_containerd_storage /var/lib/containerd ext4 defaults 0 2 -
Stop containerd:
sudo systemctl stop containerd -
Move existing data:
sudo mv /var/lib/containerd/* /mnt/encrypted_containerd/ # Temporary mount pointWait, this is getting complicated. Let’s simplify the flow. The goal is for
/var/lib/containerdto be the encrypted path.
Let’s try this again, focusing on
/var/lib/containerdas the final destination:-
Prepare a block device:
/dev/sdb1(or a file for testing:dd if=/dev/zero of=containerd.img bs=1G count=10) -
Format with LUKS:
sudo cryptsetup luksFormat /dev/sdb1Enter passphrase.
-
Create an encryption key file (optional but recommended for automation):
sudo mkdir -p /etc/cryptsetup-keys sudo dd if=/dev/urandom of=/etc/cryptsetup-keys/containerd.key bs=512 count=4 sudo chmod 0400 /etc/cryptsetup-keys/containerd.key sudo cryptsetup luksAddKey /dev/sdb1 /etc/cryptsetup-keys/containerd.keyEnter LUKS passphrase.
-
Add to
/etc/crypttab:containerd_data UUID=$(blkid -s UUID -o value /dev/sdb1) /etc/cryptsetup-keys/containerd.key luks(Using UUID is more robust than device names)
-
Add to
/etc/fstab:/dev/mapper/containerd_data /var/lib/containerd ext4 defaults 0 2 -
Stop containerd:
sudo systemctl stop containerd -
Prepare the mount point:
- If
/var/lib/containerdalready exists and has data, you need to move it before mounting the new encrypted volume. - If
/var/lib/containerdis empty or doesn’t exist, you can proceed. - Let’s assume it has data and we need to move it temporarily.
sudo mkdir /mnt/containerd_backup sudo mv /var/lib/containerd/* /mnt/containerd_backup/ - If
-
Mount the encrypted volume:
sudo systemctl daemon-reload # Reload systemd units after crypttab changes sudo systemctl start systemd-cryptsetup@containerd_data.service # Manually open encrypted device sudo mount /var/lib/containerd # Mount the filesystem -
Restore data:
sudo mv /mnt/containerd_backup/* /var/lib/containerd/ sudo rmdir /mnt/containerd_backup # Clean up -
Update containerd config (if not using default): Ensure
/etc/containerd/config.tomlpoints to/var/lib/containerdfor itsrootpath. If you’re using the default, you don’t need to change this. -
Start containerd:
sudo systemctl start containerd -
Reboot and verify: Reboot your system and check if containerd starts correctly and if your images are accessible.
sudo systemctl status containerd sudo cryptsetup status containerd_data
-
-
This setup encrypts the block device containing your containerd images. When the system boots, systemd-cryptsetup (triggered by crypttab) will prompt for the passphrase (or use the key file if configured) to unlock the device, and then fstab will mount the decrypted filesystem at /var/lib/containerd. Any data written to /var/lib/containerd by containerd will be automatically encrypted by dm-crypt/LUKS before being written to disk.
The next error you’ll likely encounter is a "Permission denied" error when containerd tries to access its data directory if the LUKS volume isn’t unlocked or mounted correctly during system startup.