Install on macOS
DMG installer (FUSE-T or macFUSE variant), the FUSE prerequisite, and the Apple Silicon kernel-extension setup macFUSE requires.
Prerequisites
| Component | Why | Where |
|---|---|---|
| FUSE-T or macFUSE | Required for the mount subcommand; install the one that matches the .dmg variant you pick (below). Without it, every other LUKSbox feature still works (CLI, GUI, put/get/ls); only mounting a vault as a drive is unavailable. |
FUSE-T: brew tap macos-fuse-t/homebrew-cask && brew install --cask fuse-t, no kernel extension. macFUSE: https://macfuse.io/, installs a kernel extension which needs explicit user approval (see below). |
| libfido2 (bundled) | FIDO2 hardware-key support. Bundled inside the .dmg; no separate install. |
n/a |
Pick a variant: FUSE-T or macFUSE
Release builds are for Apple Silicon; on an Intel Mac,
build from source. Each release ships two .dmg files,
one per FUSE backend. They are otherwise identical (same crypto, same
vault format, same UI):
| Variant | File | Install first | Pick it for |
|---|---|---|---|
| FUSE-T | luksbox-aarch64-macos-fuset.dmg |
FUSE-T. No kernel extension, no Recovery Mode step; the app also starts without it, you just can't mount yet. | A Mac only you use |
| macFUSE | luksbox-aarch64-macos-macfuse.dmg |
macFUSE, with the Apple Silicon setup below. Install it before the app: without macFUSE this variant quits before it shows any window. | Shared Macs, audited setups |
FUSE-T serves the mount over an NFS connection on the loopback
interface that has no authentication, so on a Mac with several users
(or untrusted local apps) another local process could read a mounted
vault. macFUSE's channel is restricted to the user who mounted it. The
details are in
docs/MACOS_FUSE_T.md.
luksbox --version prints which backend a build uses
(FUSE backend: fuse-t or FUSE backend: macfuse).
DMG installer (recommended)
- Download the
.dmgof your variant. From v0.6.1 on, these links always serve the newest stable release:luksbox-aarch64-macos-fuset.dmgorluksbox-aarch64-macos-macfuse.dmg. The Releases page has the same files with the version in their names, plus-portable.tar.gzarchives of the bare CLI and GUI binaries. - Verify the SHA-256 against the value in the release notes:
The
shasum -a 256 luksbox-*macos-*.dmg # Compare to the row in SHA256SUMS.txt or the Markdown table on # the release page..dmgis also Apple-notarised, so Gatekeeper validates the signature chain on first open - but the SHA-256 is your offline integrity check that doesn't depend on Apple's PKI. - Open the DMG, drag
LUKSbox.appto/Applications, eject. - The
.appis self-contained: libfido2 + transitive dependencies are bundled underContents/Frameworks/. You do not needbrew install libfido2. - Double-click
LUKSbox.app. macOS shows the standard "downloaded from internet, are you sure?" prompt once; click Open. Subsequent launches are silent. See the First launch section below for what to expect and how to verify the signature locally. - Double-clicking a
.lbxfile in Finder opens it directly in LUKSbox.
First launch
The .dmg is codesigned with our Developer ID Application
certificate (PENTHERTZ, team ID 456J2U7HQL) and notarised by
Apple. Double-clicking the downloaded .dmg opens it directly,
drag LUKSbox.app to Applications, double-click to run.
The first time you launch any app downloaded from the internet, macOS shows the standard system dialog:
"LUKSbox" is an app downloaded from the Internet. Are you sure you want to open it?
Click Open. This is the same prompt every Mac shows for any
downloaded app on first launch - it's not a Gatekeeper warning,
just a sanity check on the quarantine flag the browser set when
you downloaded the .dmg. Subsequent launches go through
without prompting.
You should not see:
- ""LUKSbox" cannot be opened because the developer cannot be verified" - that means the .dmg is unsigned, which it isn't
- "macOS cannot verify that this app is free of malware" - that means the .dmg is signed but not notarised; ours is both
- A right-click -> Open requirement
- A need to run
xattr -dr com.apple.quarantine
If you do see one of those, you've downloaded an artifact from a
release that predates the signing pipeline (v0.1.0 or earlier) or
a binary you built locally without signing. The signing pipeline
landed in v0.1.1; verify the SHA-256 against the release notes for
v0.1.1 or later and re-download the official .dmg.
Verify the signing chain yourself (optional)
# Confirm the staple is attached and Apple's notary verdict was Accepted
xcrun stapler validate -v /Applications/LUKSbox.app
# Confirm Gatekeeper accepts it as a notarised Developer ID app
spctl --assess --type execute --verbose=4 /Applications/LUKSbox.app
# Expected:
# /Applications/LUKSbox.app: accepted
# source=Notarized Developer ID
Enabling macFUSE on Apple Silicon (M1 / M2 / M3 / M4)
This section is only for the macFUSE variant. Skip it if you
use the FUSE-T variant or don't need the mount subcommand; the
rest of LUKSbox (CLI, GUI, FIDO2 unlock, file extraction via get,
hybrid PQ keyslots) works fine without it.
macFUSE installs a third-party kernel extension. On Apple Silicon Macs (any M-series chip), Apple's default System Integrity Protection posture refuses to load any kext signed by anyone other than Apple, including legitimate ones like macFUSE. To opt in to third-party kexts, you have to lower the boot policy via the Startup Security Utility - and that utility is only reachable from Recovery Mode.
The full one-time setup:
Step 1. Boot into Recovery Mode
- Apple menu -> Shut Down. Wait for the Mac to fully power off.
- Press and hold the Power button until "Loading startup options" appears (about 10 seconds).
- Select Options, then click Continue. macOS Recovery loads; you may be asked to authenticate as an administrator user of the Mac.
Step 2. Open the Startup Security Utility
In the Recovery menu bar at the top of the screen: Utilities menu -> Startup Security Utility.
This is the "Utility mode" the macFUSE installer references in its warning dialog. It exists only inside Recovery; you cannot reach it from a normal boot.
Step 3. Lower the security policy
- Pick the system disk you want to configure (usually "Macintosh HD").
- Click Security Policy....
- Select Reduced Security.
- Tick the checkbox Allow user management of kernel extensions from identified developers.
- Click OK, authenticate when prompted, restart.
Step 4. Approve the macFUSE kext
After reboot, install macFUSE from https://macfuse.io/ if you haven't already. macOS will block the kext on first install with a notification along the lines of "System extension blocked - allow in System Settings". Open System Settings -> Privacy & Security, scroll to the bottom, click Allow next to the "System software from developer Benjamin Fleischer was blocked from loading" entry. Authenticate. Restart again.
After that second reboot the kext is loaded and persists across
all future boots. luksbox mount works directly with no further
prompting.
Why the two reboots?
macOS deliberately makes kext loading a multi-step user-confirmed process to defend against malware that sneaks in a malicious kernel extension. The first reboot (after lowering the policy in Recovery) tells macOS "I'm willing to consider third-party kexts"; the second (after approving in System Settings) actually loads the specific macFUSE kext. Both prompts are permanent for that kext on that Mac; you don't have to repeat this for macFUSE updates that are signed with the same developer ID.
Intel Macs
Intel Macs (with a source build, see above) don't need the Recovery Mode dance. Install macFUSE, approve the kext warning in System Settings -> Privacy & Security when it appears, reboot once, done.
Mounting with FUSE-T
mkdir -p ~/vault
luksbox mount my.lbx ~/vault # gives the prompt back once mounted
luksbox umount ~/vault
luksbox mountruns in the background (v0.6.0+), as it does with macFUSE: it returns once the vault is mounted, and a mount that fails is reported with a non-zero exit status. Before v0.6.0 a FUSE-T mount stayed in the foreground and held the terminal (and any script that called it) until unmount.--foreground(-f) keeps that behaviour.- Copying files into the mount is about 4-5x faster in v0.6.1. A
190 MB copy that took about 17 s now takes under 4 s, as fast as
importing the file from the GUI's browser. Closing a file no longer
forces a metadata save of its own: saves happen every 30 seconds, on
fsyncand at unmount (luksbox mount --syncstill saves on every change). Many small files still copy more slowly than one big one, because macOS asks for a durable save each time it closes a file. - The GUI mounts through a helper process. With FUSE-T, the GUI
hands the unlocked vault to a separate
luksboxprocess that holds the mount, so a FUSE-T crash at unmount cannot take the GUI down. As a result, the Ask choice for giving back the vault's free space when unmounting (v0.6.1, in the GUI's Vault size dialog) cannot ask there: the free space is given back at unmount only with Always, and kept with Ask. Locking a vault that is open in the GUI's browser still asks.
Verifying the download
curl -LO https://github.com/penthertz/LUKSbox/releases/latest/download/SHA256SUMS.txt
shasum -a 256 -c --ignore-missing SHA256SUMS.txt # checks the files you downloaded
The release notes on each GitHub Release page show the SHA-256 of every artifact in a Markdown table for at-a-glance comparison without downloading the manifest.
Known macOS quirks
- Daemonized
mountfrom a multithreaded process can hit a documented macOS / fork() corner case. LUKSbox's CLI is single-threaded specifically to avoid this; the GUI uses a spawned helper for the mount step. - Quarantine xattr on hand-extracted binaries: if you
cpthe CLI binary out of the .app'sContents/MacOS/to somewhere on$PATHand macOS still shows the "downloaded from internet" prompt every time you run it, clear the xattr once withxattr -d com.apple.quarantine /path/to/luksbox. The standard drag-the-.app-to-Applications path doesn't trigger this; onlycp-out-of-DMG-into-PATH does. - macFUSE blocks at first mount, not at install: if you skipped
the Apple Silicon setup above and try
luksbox mountanyway, the FUSE mount call fails with a permission error (the kext isn't loaded). Run through the Recovery Mode steps then retry.
Using LUKSbox without FUSE
If you'd rather install neither FUSE-T nor macFUSE, you can use
LUKSbox without the mount subcommand:
- GUI: open vaults directly in the LUKSbox window. The built-in browser lets you navigate, extract, and re-encrypt files inside the vault without ever mounting it as a drive.
- CLI:
luksbox ls,luksbox get,luksbox put,luksbox cat,luksbox mkdir,luksbox rmall work without FUSE. Onlyluksbox mountneeds FUSE-T or macFUSE.
Both this and the FUSE-T variant keep your Mac at the default Apple security level; only macFUSE needs Reduced Security on Apple Silicon.
Hardware-bound keyslots on macOS: the Secure Enclave
Since v0.4.0, macOS has its own native machine binding:
Secure Enclave keyslots on Apple Silicon
and T2 Macs. Plain, Touch ID gated, fused with FIDO2 or a
passphrase, and hybrid post-quantum variants, all created with
the sep* kinds (luksbox enroll my.lbx --kind sep-biometric on a
vault created with a passphrase).
No Apple developer certificate or entitlement is needed: the
slots work from the notarized .app and from an unsigned CLI
build alike.
The TPM kinds (Tpm2Sealed and friends) work on Linux and Windows
only; macOS has no TPM. Hardware slots from another platform are
simply invisible: a TPM slot enrolled on Linux does not unlock on
macOS, a SEP slot does not unlock anywhere but its home Mac, and the
other slots in the same vault unlock normally everywhere.
Memory protection on macOS (current state + roadmap)
The Linux build of LUKSbox stores the unlocked Master Volume Key
in memfd_secret(2) pages, which are unmappable from any other
process even by root. macOS has no equivalent syscall, so the
macOS build falls back to a regular heap allocation with these
mitigations layered on top:
mlockall(MCL_CURRENT | MCL_FUTURE)to keep keys out of swap (whenRLIMIT_MEMLOCKpermits; the install script doesn't raise this).setrlimit(RLIMIT_CORE, 0)to suppress coredumps that would contain the key.Zeroize-on-drop to wipe the key bytes when their containing scope exits.- Constant-time compares on every key equality check.
This is "as good as a disciplined Mac app" - same posture as
1Password's and Bitwarden's macOS apps - and on a single-user
Mac with FileVault enabled it covers the realistic threats. A
same-machine root attacker (or a process holding the
com.apple.security.cs.debugger entitlement) can still read
the unlocked MVK from the LUKSbox process memory; on Linux the
memfd_secret pages would refuse to map even for root.
On the roadmap: macOS-native MVK storage in the Secure
Enclave. This is distinct from the SEP keyslots that shipped in
v0.4.0: those bind the unlock factor to the enclave, while this
item is about keeping the unlocked MVK inside the enclave at
runtime. Keys would live inside the enclave hardware boundary,
never exposed to the main CPU; AEAD operations would happen
through Apple's SecKey / CryptoKit APIs over IPC. Trade-offs
the design has to handle: per-chunk IPC overhead (throughput
drops from ~590 MB/s in-process AES-NI to a few hundred MB/s
through the enclave), the Secure Enclave doesn't natively
support AES-256-GCM-SIV (only AES-GCM and ChaCha20-Poly1305), and
SEP-bound MVKs aren't portable between Macs (would need a
key-wrapping mode to keep the vault file movable). Tracked in
SECURITY.md Tier 3 item 10.
Estimated ~2 weeks of design + implementation; not blocking the
1.0 milestone but the right macOS-native posture.