Safe Storage
The Yubikey LUKS section covered full disk encryption for the desktop itself. This page covers a different but related need: encrypted removable storage for sensitive material that needs to exist offline and physically separate from the machine.
The primary use case in this series is the offline root CA key material. The root CA private key must never touch a network-connected machine, must be physically secured, and must be accessible only with a strong passphrase. An encrypted USB drive satisfies all of these requirements. The same approach works for GPG key backups, KeePassXC database backups, Borg repository key exports, and any other material that needs to exist offline in a form that cannot be read if the drive is lost or stolen.
LUKS is the Linux standard for disk encryption. It is the same technology used for full disk encryption at install time, applied here to removable media. LUKS2 is the current version and is used throughout.
Encrypted USB drives
An encrypted USB drive is the recommended storage for offline key material. It provides strong encryption at rest, is accessible from any Linux system, and is straightforward to create and manage.
Creating an encrypted USB drive
Insert the USB drive. Identify the device:
lsblk
Find the device for the USB drive, something like /dev/sdb. Everything on it will be overwritten. Be certain of the device before continuing.
Open GNOME Disks or KDE’s Disk Manager for a graphical approach, or use the command line.
Command line approach:
Wipe the existing partition table and create a new one:
sudo wipefs -a /dev/sdX
sudo parted /dev/sdX mklabel gpt
sudo parted /dev/sdX mkpart primary 1MiB 100%
Create the LUKS2 encrypted container on the partition:
sudo cryptsetup luksFormat \
--type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--pbkdf argon2id \
--label "SafeStorage" \
/dev/sdX1
Enter and confirm a strong passphrase when prompted. Use a six-word Diceware passphrase as covered in the passphrases section. Store it in KeePassXC.
Open the encrypted container:
sudo cryptsetup open /dev/sdX1 safe-storage
Create a filesystem inside the encrypted container:
sudo mkfs.ext4 -L "SafeStorage" /dev/mapper/safe-storage
Close the container:
sudo cryptsetup close safe-storage
The drive is now ready. It will prompt for the passphrase each time it is inserted.
Using an encrypted USB drive on Kubuntu
When you insert the encrypted drive, KDE Plasma’s device notifier will detect it and prompt for the passphrase. Enter it and the drive mounts automatically at /media/$USER/SafeStorage or similar.
To mount manually from the command line:
sudo cryptsetup open /dev/sdX1 safe-storage
sudo mount /dev/mapper/safe-storage /media/${USER}/SafeStorage
To unmount and close:
sudo umount /media/${USER}/SafeStorage
sudo cryptsetup close safe-storage
Always close the LUKS container after use. Removing the USB drive while the container is open does not encrypt the data; only closing the container does.
Setting correct permissions
After first mounting, set the directory ownership so your user can write to it without sudo:
sudo chown ${USER}:${USER} /media/${USER}/SafeStorage
Directory structure for offline key material
Establish a consistent directory structure on the encrypted drive so material is easy to find without having to explore the filesystem under pressure:
mkdir -p /media/${USER}/SafeStorage/{OpenPGP,BorgBackup,Certificates,CA}
The suggested layout:
SafeStorage/
├── OpenPGP/ # GPG private key exports, revocation certificates
├── BorgBackup/ # Borg repository keyfile exports
├── Certificates/ # TLS certificate private keys, PEM exports
├── CA/ # Root CA key material (offline root CA only)
│ ├── root-ca/ # Root CA private key and certificate
│ └── revocation/ # CRL and revocation certificates
The CA directory is the most sensitive. If the drive is used exclusively for CA operations, consider a second separate drive for non-CA key material to keep them physically segregated.
LUKS containers as files
An alternative to encrypting an entire partition is a LUKS container file: a fixed-size file that acts as an encrypted block device. This is useful when you want encrypted storage on an existing filesystem, or when you want a portable encrypted container that can be copied and backed up as a file.
Create a 1GB LUKS container file:
# Create a file filled with random data
dd if=/dev/urandom of=~/encrypted-container.luks bs=1M count=1024 status=progress
# Format it as LUKS2
cryptsetup luksFormat \
--type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
~/encrypted-container.luks
# Open the container
cryptsetup open ~/encrypted-container.luks my-container
# Create a filesystem
mkfs.ext4 /dev/mapper/my-container
# Mount it
mkdir -p /mnt/my-container
mount /dev/mapper/my-container /mnt/my-container
To close:
umount /mnt/my-container
cryptsetup close my-container
Container files are useful for encrypted vaults that live in your home directory and are included in the Borg backup automatically. The encrypted container file is backed up as an opaque blob: Borg backs up the ciphertext, which is safe to store on the NAS since it cannot be read without the passphrase.
Multiple passphrases and keyslots
LUKS supports up to 32 keyslots per device, each of which can unlock the volume independently. This is how Yubikey enrollment works alongside a passphrase: both unlock the same volume key.
For offline USB drives, adding a second passphrase allows a trusted person to access the drive in an emergency without knowing your primary passphrase:
sudo cryptsetup luksAddKey /dev/sdX1
Enter the existing passphrase to authenticate, then set the new passphrase. View the current keyslots:
sudo cryptsetup luksDump /dev/sdX1 | grep -A2 "Keyslot"
To remove a keyslot (for example, to rotate a passphrase):
sudo cryptsetup luksKillSlot /dev/sdX1 <slot-number>
Checking LUKS volume status
Inspect a LUKS volume at any time:
sudo cryptsetup luksDump /dev/sdX1
This shows the LUKS version, cipher, key size, and all keyslot states. Use it to verify a volume was created correctly and to check keyslot status before removing any.
For an open volume:
sudo cryptsetup status safe-storage
KDE integration
KDE Plasma handles encrypted drives cleanly. When an encrypted drive is inserted, the device notifier prompts for the passphrase via a KDE dialog. The drive mounts automatically on success and appears in Dolphin.
For drives that are used regularly (such as a frequently accessed key backup), you can configure KDE to remember the passphrase in KWallet so it unlocks automatically when inserted. This is a convenience trade-off: it makes access easier but means anyone who unlocks your KWallet session can also access the encrypted drive. For day-to-day encrypted backups this is reasonable. For the offline root CA drive, always enter the passphrase manually.
Physical security
Encryption protects data at rest. It does not protect a drive that is inserted and unlocked. Physical access to the drive while it is mounted is access to the plaintext.
For offline CA key material specifically:
- Store the drive somewhere physically secure when not in use, a locked safe or a location separate from the machine
- Do not leave it inserted in the machine when not actively needed
- Do not insert it into a machine that may be compromised
- Use it only under Tails with networking disabled for CA operations, as covered in the Tails section
The combination of strong encryption, a strong passphrase stored in KeePassXC, and sensible physical handling makes this a practical and robust offline key storage solution.
LUKS encryption is only as strong as the passphrase protecting it. A six-word Diceware passphrase on an offline key storage device is appropriate. Do not reuse the same passphrase across multiple volumes. Each encrypted volume should have its own unique passphrase stored separately in KeePassXC.