luksbox create
Create a new encrypted container.
luksbox create [OPTIONS] <PATH>
Creates a new vault at <PATH> with one initial keyslot. The kind
of slot 0 is set by --kind (passphrase by default).
Examples
Passphrase-only vault (default)
luksbox create my.lbx
Creates my.lbx with one passphrase keyslot using AES-256-GCM-SIV
and the interactive Argon2id preset.
Detached header
luksbox create my.lbx --header /media/usb/my.hdr
Writes the 8 KiB header to a separate file. Without that sidecar,
my.lbx is unreadable - no magic bytes, no keyslot table, just
random data.
FIDO2-protected vault
luksbox create my.lbx --kind fido2
# Two touches: makeCredential + getAssertion
Adds a FIDO2 keyslot as slot 0. You'll be prompted for a backup
passphrase too (added as slot 1) so losing the device doesn't lose
the vault. Skip the backup with --no-backup-passphrase if you
understand the trade-off.
Hybrid post-quantum
# First, generate the Kyber seed file (keep on separate storage)
luksbox kyber-init /media/usb/my.kyber
# Then create the vault
luksbox create my.lbx --kind hybrid-pq --pq-hybrid /media/usb/my.kyber
Or for the strongest variant (FIPS 203 cat 5):
luksbox create my.lbx --kind hybrid-pq1024-fido2 \
--pq-hybrid /media/usb/my.kyber
Key flags
| Flag | Purpose |
|---|---|
--kind <KIND> |
First keyslot kind: passphrase (default), fido2, fido2-direct, hybrid-pq, hybrid-pq-fido2, hybrid-pq1024, hybrid-pq1024-fido2 |
--cipher <aes|chacha|aes-siv> |
AEAD primitive. aes-siv (default) is AES-256-GCM-SIV per RFC 8452 |
--kdf <interactive|sensitive> |
Argon2id preset. sensitive multiplies brute-force cost by 6x |
--header <PATH> |
Write header to a separate sidecar file |
--fido2-device <PATH> |
Pin to a specific FIDO2 device (see list-fido2-devices) |
--pq-hybrid <PATH> |
Path to the .kyber seed file (required for hybrid-PQ kinds) |
--chunk-size <N> |
File chunk size in bytes (default 4096) |
--metadata-size <BYTES> |
Reserved metadata region size (default + cap: 16 MiB). Lower this only for tiny demo vaults; higher values are rejected at the CLI boundary. |
--format <v2|v3> |
On-disk metadata format (default v3). See the format section below. |
--pad-files |
Pad each file's chunk count to next power of 2 (hides exact size from disk forensics) |
--hide-sizes |
Move the size field into AEAD-encrypted chunks (implies --pad-files) |
--no-backup-passphrase |
For --kind fido2: don't add a passphrase backup slot |
On-disk format: v2 vs v0.2.1 (LBM5 + LUKSBOX2)
Every new vault picks one of two on-disk envelopes. The choice is permanent for that vault.
| v0.2.1 format (default) | v2 (legacy) | |
|---|---|---|
| Metadata magic | LBM\x05 |
LBM\x02 |
| Header magic | LUKSBOX2 |
LUKSBOX1 |
| Per-file chunk list location | External: linked chain of encrypted chunk-list blocks in the data area. Files above 256 chunks (~1 MiB plaintext) spill; tiny files stay inline. | Inline: Vec<ChunkRef> packed into the fixed metadata region. |
| Practical per-vault content ceiling | Tested up to ~30 GiB; engineered for much more. 64 MiB metadata cap. | ~8-10 GiB before the metadata region overflows. |
| Crash-safety | <vault>.lbx.{header,meta}-bak sidecar mirrors; mid-write force-quit recovers automatically. |
NOT crash-safe. A force-quit mid-write can leave the vault permanently unopenable. |
| Persistent chmod / hardlinks / symlinks | Yes | No |
| Reader compatibility | LUKSbox v0.2.1+ only | Every LUKSbox release ever shipped |
Pick the v0.2.1 default unless you need to share the new
vault with a colleague on a pre-v0.3 LUKSbox install AND can
suppress the auto-upgrade trigger via LUKSBOX_FORMAT_V2=1 in
their environment. Otherwise the first flush on their side
auto-upgrades the vault to the v0.2.1 envelope and they can no
longer open it with their old binary.
# Default: v0.2.1 (LBM5 + LUKSBOX2 + sidecar mirrors)
luksbox create my.lbx
# Explicit v2 legacy for cross-version compatibility
luksbox create my.lbx --format v2
# Power-user knob: shrink the metadata region for a demo vault
luksbox create demo.lbx --format v2 --metadata-size 256K
Migrating an existing v2 vault to v3
luksbox migrate-to-v3 old-v2.lbx --dst new-v3.lbx
Reads the v2 vault, creates a fresh v3 vault, copies every file
through the VFS read API. Source vault is left untouched; verify the
new one opens cleanly (luksbox info new-v3.lbx) before deleting
the source. The destination is created with a single passphrase
keyslot -- re-enroll other keyslots afterwards via luksbox enroll.
Deniable vaults can be created in v3 format directly via the wizard
(it asks for the format alongside the cipher and KDF params); there's
no automated migrate-to-v3 path for deniable vaults yet because the
deniable open ceremony is interactive.
Environment-variable opt-out
# Force v2 for every fresh vault in this shell session, even
# when --format isn't passed.
LUKSBOX_FORMAT_V2=0 # opts into v3 (the default -- leave unset)
LUKSBOX_FORMAT_V2=1 # opt into v3 (legacy gate from the v0.2-dev cycle)
# Values `false` / `no` / `off` on LUKSBOX_FORMAT_V2 force v2.
What gets created on disk
| File | When |
|---|---|
<PATH> (the .lbx) |
Always |
<PATH>.hdr (if --header) |
When --header is passed |
<PATH>.hybrid |
For hybrid-PQ kinds only - small sidecar with ML-KEM data |
<KYBER_PATH> |
For hybrid-PQ kinds only - the seed file you pre-generated |
After create, the vault is empty. Use luksbox put to add files
or luksbox mount to mount as a drive and write to it normally.