Linux fscrypt: Plan Per-Directory Encryption and Key Recovery
Use Linux's filesystem encryption interface for new directory trees, while distinguishing kernel policy from userspace key management and full-disk encryption.
Linux fscrypt is filesystem-level encryption for selected directory trees, not a command that encrypts an existing populated directory in place. A policy is attached to an empty directory; after userspace makes the matching key available, files, subdirectories, and symlinks created below it are transparently encrypted. That is a different boundary from LUKS/dm-crypt, which protects a block device or volume as a whole.
The name covers two layers that should not be confused. The kernel implements the filesystem encryption API, policy checks, and file-name/content encryption. A userspace manager such as Google’s fscrypt tool provisions protectors, stores filesystem metadata, and adds keys to the kernel when a directory is unlocked. The tool is not the kernel feature, and an installed CLI alone does not make an unsupported filesystem encryptable.
Check the filesystem before planning a rollout
Start with the target machine’s filesystem, kernel, and distribution support. The upstream kernel documentation requires filesystem and kernel support; the upstream fscrypt project documents ext4, F2FS, and UBIFS, each with its own kernel configuration or on-disk feature requirements. In particular, ext4 must have its encrypt feature enabled. fscrypt status is a useful first inventory, but validate the exact kernel build, mount, backup path, and recovery process rather than treating a successful command as a complete compatibility test.
New deployments should normally use policy version 2, which the kernel documentation identifies as supported since Linux 5.4 and recommends for new encrypted directories. Version 1 has usability and security limitations and is deprecated. Do not silently change policy versions on a fleet: kernel, userspace, and recovery-tool minimums become part of the data’s portability requirements.
The tool’s setup operation also creates .fscrypt policy/protector metadata on the filesystem. Its documentation explains that the administrator chooses whether non-root users may create that metadata; a world-writable sticky directory improves usability but can allow users to consume filesystem space. Make that choice against the host’s user model and quota policy. Avoid changing permissions manually to “fix” a failed setup without reviewing the tool’s metadata rules.
Create encryption before writing sensitive data
On a disposable host, complete the tool’s one-time global setup after reviewing its metadata-permission choice. For the following unprivileged example, /mnt/fscrypt-lab must already be the mountpoint of a dedicated test filesystem; the current user must be allowed to create a child there, and the filesystem’s .fscrypt metadata directories must permit that user to create policies and protectors. fscrypt setup normally runs with root privileges on a root-owned mountpoint and asks whether non-root users may create metadata; choosing “no” leaves those directories root-writable, so use a root-managed workflow or deliberately configured per-user/group permissions instead of silently adding sudo to the later commands. Then, on a disposable filesystem that reports encryption support, a safe practice run looks like this:
# Read-only capability inventory first.
fscrypt status
# Lab only: initialize metadata on the already-mounted dedicated test filesystem.
sudo fscrypt setup /mnt/fscrypt-lab
# These two commands run as the intended unprivileged owner of this tree.
mkdir -m 700 /mnt/fscrypt-lab/private
fscrypt encrypt /mnt/fscrypt-lab/private
fscrypt status /mnt/fscrypt-lab/private
fscrypt encrypt should prompt for a protector rather than receiving a passphrase embedded in shell history or a script. The command works on an empty directory and normally leaves it unlocked for immediate use. Protectors describe how userspace obtains or derives the key; the kernel policy describes how the filesystem applies encryption. Store recovery material independently of the data and test that the intended user or service identity can unlock it after a restart.
Once a test file has been created, exercise the normal lock and unlock workflow on the lab directory, then verify that the application behaves correctly when it is locked. Include restart, backup, restore, user/profile migration, and key-loss cases before production. The upstream userspace documentation notes that encrypted data can only be backed up while unlocked; a backup taken in that state contains ordinary plaintext unless the backup system encrypts it separately. Record which component protects the backup as well as the live filesystem.
Understand what the boundary does not protect
The kernel’s threat model is deliberately narrower than “the files are secret.” When locked and viewed offline, fscrypt protects file contents and filenames against a point-in-time compromise of the storage device, assuming userspace supplies a strong key. It does not hide other metadata such as file sizes, permissions, timestamps, extended attributes, or allocation holes. The kernel documentation also warns that offline filesystem manipulation before a later authorized access is not guaranteed to preserve confidentiality or authenticity.
After the key is loaded, ordinary filesystem permissions, ACLs, LSM policy, and namespaces remain the access-control boundary for other users on the running host. Encryption is not a replacement for chmod, service isolation, or protecting the unlocked application. A kernel-memory compromise can expose in-use keys, and data already read into application memory is plaintext. If the requirement is whole-volume protection or encryption of an entire root filesystem, use a block-encryption design such as dm-crypt/LUKS instead of trying to apply one directory policy everywhere.
There is no secure “convert this populated tree in place” operation. fscrypt encrypt accepts an empty directory. Copying old files into a newly encrypted directory can leave recoverable source blocks, snapshots, backups, or device-level remnants; deleting the old names does not prove the old bytes were overwritten. For existing sensitive data, plan a migration around a separately encrypted destination and verified backup, assess every old copy, and use the storage vendor’s appropriate sanitization or key-destruction method. Do not promise that shred reliably erases flash, copy-on-write, snapshotting, or remote-backed storage.
Finally, files with incompatible encryption policies cannot simply be renamed into the same encrypted tree. Cross-filesystem or cross-policy “moves” may become copy-and-delete work in userspace, with the same residue and partial-failure risks. Treat a policy boundary as a data-migration boundary, not as a transparent directory attribute that can be retrofitted at will.
Related:
- How to Set Up Full-Disk Encryption on Linux with LUKS
- Choosing a Linux Filesystem: Recovery, Integrity, and Workload Tradeoffs
Sources: