Local encryption
Varlock includes a built-in varlock() function that lets you secure local untracked secrets (typically in git-ignored env files like .env.local).
This allows you to keep everything out of plaintext - even temporary local overrides, or a “secret-zero” which is needed by some plugins to load the rest of your sensitive data.
Sensitive values will be stored encrypted, with the key linked to your local device, and requiring no extra configuration. The encryption mechanism varies per platform, but as it is tied to your device, these values are not meant to be shared or committed to git.
PLAINTEXT=shh-im-secret # 🚨 dangerSECURED=varlock(local:abc123...) # ✅ secured at restQuick start - existing secrets
Section titled “Quick start - existing secrets”You likely already have some plaintext secrets in a .env.local file. If not you can create one, and add some. Ensure those items are marked as @sensitive in your schema. Then you can use varlock encrypt to encrypt them in-place:
- Run
varlock encrypt --file .env.localto encrypt them in-place - Sensitive plaintext values are replaced with
varlock("local:<***encrypted***>") - Decryption happens automatically during
varlock load/varlock run
Only plaintext values of @sensitive items are encrypted, so you may run it multiple times.
Using varlock(prompt) resolver
Section titled “Using varlock(prompt) resolver”When you need to edit a value or add a new sensitive item, just set the value to varlock(prompt) and run varlock load. You will be prompted for the new value in a secure input prompt, and the encrypted value will be written back to the file automatically.
EXISTING_ITEM=varlock(local:abc123...)NEW_ITEM=varlock(prompt) # will prompt you for new valueUsing varlock encrypt CLI
Section titled “Using varlock encrypt CLI”You can also call the varlock encrypt CLI command to get a secure prompt to encrypt a single value. It will spit out an item you can copy/paste into your file:
◇ Enter the value you want to encrypt│ ▪▪▪▪▪▪▪▪
Copy this into your .env.local file and rename the key appropriately:
SOME_SENSITIVE_KEY=varlock("local:ABC123...")--file option
Section titled “--file option”As outlined above, you can also run varlock encrypt --file .env.local to encrypt all sensitive plaintext values in a file in-place. This is a great way to quickly encrypt many secrets at once.
Core commands
Section titled “Core commands”Use varlock encrypt to create encrypted payloads:
# Interactive: encrypt a single valuevarlock encrypt# Batch: encrypt all sensitive plaintext values in .env.localvarlock encrypt --file .env.localUse varlock reveal to inspect decrypted values safely:
varlock reveal # interactive - select and revealvarlock reveal API_KEY # securely reveal specific itemvarlock reveal API_KEY --copy # copy to clipboardUse varlock lock to invalidate biometric session cache when stepping away:
varlock lockBackend selection overview
Section titled “Backend selection overview”Varlock chooses the best available backend automatically:
| Platform | Backend | Key Storage | Biometric |
|---|---|---|---|
| macOS | Secure Enclave | Hardware Secure Enclave | Touch ID |
| Windows | NCrypt TPM + Windows Hello | TPM (when available), else DPAPI | Windows Hello (face/fingerprint/PIN) |
| Linux | TPM2 / Secret Service | TPM2 and/or system key store | Yes (when configured via polkit/PAM) |
| All platforms | File-based fallback | ~/.varlock/ directory | No |
If native capabilities are unavailable, varlock falls back to file-based local encryption.
Verify encryption backend (macOS/Linux)
varlock-local-encrypt statusVerify encryption backend (Windows/WSL)
varlock-local-encrypt.exe statusUnattended decryption (headless servers & CI)
Section titled “Unattended decryption (headless servers & CI)”Local encryption isn’t just for laptops. On a headless host with a TPM (a home server, a CI runner, a container host), varlock seals the key to the machine’s TPM and decrypts automatically at load with no prompt. That makes it a good way to store a “secret-zero” (like a 1Password service account token) that bootstraps the rest of your secrets:
# @type=opServiceAccountToken @sensitive @internalOP_TOKEN=varlock("local:...")On Linux this requires tpm2-tools and a TPM (see Linux setup below). The sealed value survives reboots and is bound to that specific machine. It can’t be copied to another host.
This unattended path applies to backends whose key is unsealed to the host: Linux (TPM2) and Windows (NCrypt/TPM). macOS is different: Secure Enclave keys never leave the enclave, and every decrypt requires user presence (Touch ID or password), so there is no unattended decrypt on macOS. A headless Mac or CI runner falls back to file-based encryption instead.
What this protects (and what it doesn’t)
Section titled “What this protects (and what it doesn’t)”Hardware-backed encryption protects your secrets at rest: a stolen disk, a leaked backup, or an env file committed by mistake can’t be decrypted off the machine.
It does not protect against an attacker who is already running code as your user on that machine. They can ask the TPM to unseal the value exactly like varlock does. This is the same trade-off as tools like systemd-creds, and it’s inherent to unattended decryption: if no human is present to approve, anything running as you can decrypt.
If you want a presence gate (fingerprint / password / YubiKey via polkit + PAM) on every decrypt, register the policy:
sudo varlock-local-encrypt setup --linux-biometricsOnce configured, varlock’s normal decrypt flow requires user presence, so everyday loads are no longer unattended. Enable this only on interactive machines, not headless servers.
Treat this gate as a consent prompt, not an at-rest boundary. On Linux the TPM unseal isn’t bound to polkit, so (as noted above) other code already running as your user can still unseal directly. It means “a human approved this load,” not “only a human can ever decrypt.”
Platform details & setup
Section titled “Platform details & setup”- Native Swift helper (Secure Enclave integration)
- Uses system-native secure input / auth prompts
- Includes a menu bar applet flow for native interactions
- Hardware-backed key protection via Secure Enclave with biometric auth where supported
✅ No additional install/setup steps required
Windows
Section titled “Windows”- Native helper with TPM-sealed key protection when a TPM 2.0 chip is available (via NCrypt / Platform Crypto Provider)
- Falls back to DPAPI (user-session-scoped) when TPM sealing is unavailable
- Windows Hello gates interactive decrypts (fingerprint/face/PIN), separate from at-rest protection, same as before
- Windows native and WSL workflows are both supported (WSL uses the Windows
varlock-local-encrypt.exevia--via-daemon; Hello + TPM behavior is identical) - Automated daemon startup/installation behavior is built in for biometric session flows
- WSL decrypt flows use a native bridge to the Windows daemon path
✅ No additional install/setup steps required
Upgrading existing keys to TPM
Section titled “Upgrading existing keys to TPM”New keys automatically use TPM sealing when available. Existing DPAPI keys are auto-upgraded to TPM sealing on the next successful decrypt (public key unchanged, no re-encryption of .env values). To upgrade without decrypting, use varlock-local-encrypt rewrap-key --key-id varlock-default.
Windows Defender false positives
Section titled “Windows Defender false positives”varlock-local-encrypt.exe is Varlock’s official local-encryption helper (bundled with the npm package and standalone CLI). Windows Defender may flag it as Trojan:Win32/Wacatac.C!ml or similar, a common machine-learning false positive on new, unsigned executables. The binary is safe when obtained from official Varlock releases.
Verify the download: each GitHub release includes SHA256SUMS.txt with hashes for all native helpers. After installing, compare your file:
# PowerShell: run from the directory containing the .exeGet-FileHash varlock-local-encrypt.exe -Algorithm SHA256Match the hash against the native-bins/win32-x64/varlock-local-encrypt.exe line in SHA256SUMS.txt for your release version.
If quarantined: restore the file from Windows Security → Protection history, or add an exclusion for your project directory. Reinstall from npm or the official release if needed.
Permanent fix: official builds are moving to Authenticode code signing, which greatly reduces these alerts. Until your installed version is signed, verification via SHA256SUMS.txt is the recommended way to confirm authenticity.
- Native Linux helper when available
- User-presence verification via polkit/PAM (can support fingerprint/face/password depending system setup)
Common packages/tools:
tpm2-tools(plus distro TPM2 libs such astpm2-tss)polkitfor user-presence authorization flowsxcliporxselforvarlock reveal --copy
Example installs:
# Debian/Ubuntusudo apt-get updatesudo apt-get install -y tpm2-tools tpm2-tss policykit-1 xclip# Fedora/RHEL variantssudo dnf install -y tpm2-tools tpm2-tss polkit xclipIf biometric/user-presence prompts are unavailable on Linux, complete policy setup (native helper command):
sudo varlock-local-encrypt setup --linux-biometrics