Quickstart 

    The quickest way to see Basil work end to end is the dev fixture: one script boots a throwaway backend, writes an example catalog + policy, pre-fills a few keys, and creates a sealed bundle, then prints the exact commands to run the broker and drive it. Under five minutes.

    Prerequisites 

    • A Vault-compatible backend CLI on your PATH: OpenBao (bao) or HashiCorp Vault (vault).
    • The Basil binary (basil). Build it with cargo build (Rust 1.96) or from the Nix dev shell. See Installation.

    1. Boot a dev backend + example config (one command) 

    # Boots a dev `bao` in -dev mode, writes an example catalog/policy, pre-fills
    # keys, and seals a 0600 bundle. Prints the run + CLI commands when it finishes.
    scripts/prefill-test-store.sh --engine openbao      # or: --engine vault

    Basil treats OpenBao and HashiCorp Vault as one vault backend kind, so either engine works.

    2. Run the broker 

    Copy the basil agent … invocation the script printed. It wires the generated TOML config, backend address, and socket. The config points at the catalog, policy, sealed bundle, and generated passphrase unlock file:

    basil agent \
      --config <printed>/fixtures/basil-agent.toml \
      --vault-addr http://127.0.0.1:8210 \
      --socket /tmp/basil.sock
    💡 Sharing the socket with local services

    For shared local deployments, configure the socket in the agent TOML instead of a post-start chmod. The socket mode/group only controls which local users can open the transport; Basil still authorizes each RPC from kernel peer credentials and catalog policy.

    socket = "/run/basil/basil.sock"
    socket-mode = "0660"
    socket-group = "basil-clients"

    3. Drive it 

    The broker resolves your kernel-attested uid/gid to a policy subject, and the example policy grants the user that ran the script. Talk to the broker over its socket with the basil CLI:

    basil --socket /tmp/basil.sock status
    # sign a message with a key whose private half never leaves the backend:
    basil --socket /tmp/basil.sock sign --key-id web.tls.signing_key 'hello'
    # AEAD-encrypt; Basil generates the nonce, so you can't reuse one:
    basil --socket /tmp/basil.sock encrypt --key-id app.aead 'backup-bytes'
    # mint a short-lived TLS leaf, leaving the issuing CA key in the backend:
    basil --socket /tmp/basil.sock issue-cert --key-id web.tls.cert_issuer \
      --common-name svc.example.org --dns-san svc.example.org --ttl-secs 3600

    That's the whole loop: your shell proved who it was to the kernel, policy said yes, and the Vault-compatible backend did the crypto in place. No private key ever crossed the socket.

    Where to go next