Introduction
Most of us have a small pile of files that are too sensitive to leave sitting around as plaintext, but too infrequently used to justify encrypting an entire drive for. Private keys, password manager backups, recovery codes. A LUKS container solves this cleanly: a single encrypted file that behaves like a portable, lockable vault.
Why a File-Based Container
Full-disk encryption makes sense for something like a laptop, where everything on it needs protection. But for a handful of specific files, encrypting an entire drive is overkill. A file-based LUKS container gives you the same strong encryption, scoped to exactly what you need, and portable enough to copy anywhere: cloud storage, a USB drive, wherever. When it's closed, it's just an opaque binary blob sitting on disk. Nothing about it hints at what's inside.
A LUKS container works well for exactly this kind of material: private keys, password manager backups, SSH keys, recovery codes. Anything sensitive, static, and infrequently touched. Rather than scattering these across individual encrypted files or trusting a single tool to protect all of it, a container gives you one deliberate, portable vault, protected independently of wherever it happens to be stored.
One thing worth flagging upfront: LUKS is a Linux-native format. If you need the container accessible on Windows or macOS as well, VeraCrypt is the better choice. Everything here assumes a Linux-only workflow.
Creating the Container
First, we'll create an empty file. The size can be changed to whatever you need.
Using fallocate:
fallocate -l 512M container.img
Using dd:
dd if=/dev/urandom of=container.img bs=1M count=512
fallocate is fastest since it just reserves space without writing anything, but the file can end up sparse, meaning the filesystem technically knows which blocks are empty versus written. A minor, mostly theoretical risk of metadata leakage.
If you'd rather not have that at all, dd with /dev/urandom writes real data the whole way through instead. Slower, especially on spinning rust or a slow USB drive, but there's no "empty vs written" distinction left behind anywhere. Use it unless you've got a good reason not to.
Encrypting the Container
Next, set up LUKS encryption on it:
cryptsetup luksFormat container.img
Follow the instructions, set a strong 5-7 random word passphrase. Memorize it. If you lose it, the data is gone.
Open the container and give it a name, it will map to a virtual block device:
cryptsetup open container.img mycontainer
Format the mapped device with a filesystem:
mkfs.ext4 -m 1 /dev/mapper/mycontainer
The -m 1 flag reduces the space ext4 reserves for root from its default 5% down to 1%. That reservation exists to stop a full root filesystem from causing problems system-wide, but for a small, purpose-built container, it's unnecessary overhead worth reclaiming.
ext4 is used here, but any Linux filesystem works inside a LUKS container, XFS or Btrfs if you prefer them. ext4 is just the most battle-tested, and the one I'd reach for unless you have a specific reason not to.
We can now mount it and use it like any other filesystem.
mkdir -p /mnt/mycontainer
mount /dev/mapper/mycontainer /mnt/mycontainer
Locking It Back Up
When you're done, unmount before closing, in that order:
umount /mnt/mycontainer
cryptsetup close mycontainer
Unmounting first ensures nothing is still reading or writing when the LUKS mapping closes. Skip that step and you risk data corruption or a failed close.
What Actually Ended Up In Mine
I built this specifically to store my private CA key at rest, somewhere more deliberate than a password manager's binary attachment field. It didn't stay that way for long. A backup of my password manager's own database followed, then a full backup of this site's source, which weighs in at a grand total of 11.3KiB thanks to having no external dependencies. What started as a single-purpose vault for one private key quietly became something closer to a full personal disaster recovery kit.
Real Tradeoffs Worth Knowing
Encryption solves confidentiality, not everything else.
One passphrase protects everything inside. Consolidating multiple sensitive files into a single container means a single compromised passphrase exposes all of it at once. Worth rotating periodically, even with a strong passphrase already in place. cryptsetup luksChangeKey handles rotation without needing to rebuild the container from scratch.
No built-in integrity checking. LUKS protects confidentiality, but not integrity. There's no protection against corruption or bitrot. If a container is meant to be a real backup, it's worth periodically testing that it still opens cleanly, especially copies sitting untouched on a USB drive somewhere.
Wrapping Up
I built this to solve one specific problem: where to put a private key I didn't want sitting in plaintext. It ended up holding a lot more than that, which says less about the tool and more about how many small, sensitive things quietly accumulate once you actually have somewhere good to put them.