Installation

  1. Requirements
  2. Homebrew (recommended)
  3. Manual (single script)
  4. First-time setup
  5. Environment variables
    1. Isolated test vault
  6. Vault files (what lives in CONCEALER_HOME)

Requirements

Dependency Why Notes
Python 3 concealer is a single stdlib-only script No pip install needed
sops encrypt/decrypt the vault  
age encryption backend + age-keygen  
expect drives age’s passphrase prompt (age reads /dev/tty, not stdin) ships with macOS and most Linux

concealer runs a preflight check on every command and exits with an install hint if any of sops, age, age-keygen, or expect are missing.


brew install fxerkan/tap/concealer

This pulls in sops, age, and expect automatically.


Manual (single script)

# prerequisites
brew install sops age            # macOS (or your OS package manager); expect ships with macOS

# get concealer
git clone https://github.com/fxerkan/concealer.git
cd concealer

# optional: put it on PATH with the short `cer` alias
ln -sf "$PWD/concealer" ~/bin/concealer
ln -sf "$PWD/concealer" ~/bin/cer

The script is dependency-free Python — no virtualenv, no packages. cer is a symlink to concealer; every command works under either name.


First-time setup

concealer init          # generate keys + set master password

init prints 8 one-time recovery codes and a starter export CONCEALER_TOKEN=… line, then removes the plaintext age key from disk. Save the recovery codes elsewhere. See Getting Started for the full flow.

Use concealer init --force to reinitialize over an existing vault (destructive — only on a throwaway/test vault).


Environment variables

Variable Purpose Default
CONCEALER_HOME vault directory ~/.concealer; in a repo checkout, the folder next to the script
CONCEALER_TOKEN CLI/MCP unlock token (produced by init / unlock / agent register)
CONCEALER_IDLE web session idle auto-lock timeout, in seconds 300
CONCEALER_ACTOR fallback actor label recorded in the audit log

Isolated test vault

Never test against your real vault. Point CONCEALER_HOME at a throwaway directory:

CONCEALER_HOME=/tmp/testvault concealer init
CONCEALER_HOME=/tmp/testvault concealer web 8799

Vault files (what lives in CONCEALER_HOME)

secrets.enc.yaml        # the vault — SOPS+age encrypted JSON (stored as YAML)
.sops.yaml              # SOPS config (recipient / rules)
keys/
  age-key.txt.age       # age private key, master-password wrapped — the ONLY key at rest
  master.json           # scrypt verifier for the master password (UI)
  recovery.json         # recovery-code hashes + code-wrapped key
  agents.json           # unlock-token hashes + token-wrapped key
  audit.log             # HMAC-chained audit log (+ monotonic seq)
  audit.head            # tail anchor (catches truncation)
  ratestate.json        # per-agent anti-exfiltration rate state (names+timestamps only)
  backup.json           # auto-backup settings (age-wrapped backup password)

Nothing in keys/, secrets.enc.yaml, or .sops.yaml should ever be committed to a public repo. The project’s .gitignore protects these. This repo ships the tool, never a vault.


Developed by FXerkan — Code more, worry less. · MIT License

This site uses Just the Docs, a documentation theme for Jekyll.