Skip to content

Quick Start

Jake Paine edited this page May 23, 2026 · 4 revisions

Quick Start

This walks through a developer/admin setup: initializing a repo, adding an encrypted secret, editing it, inspecting the Git-backed changes, and committing the result. Production/deploy machines that only render or exec secrets do not need the external sops or age binaries.

Before you start

For this developer/admin walkthrough you need:

  • keyseal installed and on your PATH
  • external sops installed and on your PATH
  • age key material; generate a key with age-keygen if you do not have one

1. Initialize the repository

Run this from the root of the Git repository where you want to store secrets:

keyseal init

This creates:

  • keyseal.yaml - Keyseal configuration
  • .sops.yaml - SOPS creation rules (with placeholder recipients)

And scaffolds directories:

production/platform/
production/infra/
production/tenants/
staging/platform/
staging/infra/
staging/tenants/

The generated .sops.yaml contains placeholder age recipients (age1REPLACE_ME). You must replace these with real age public keys before SOPS will encrypt anything.

# generate a key if you need one
age-keygen -o ~/.config/sops/age/keys.txt
# the public key is printed to stdout, e.g.:
# Public key: age1abc123...

Edit .sops.yaml and replace the placeholder values:

creation_rules:
  - path_regex: production/.*\.enc\.yaml$
    age: age1abc123...,age1recovery456...
  - path_regex: staging/.*\.enc\.yaml$
    age: age1abc123...,age1recovery456...

If your age private key is not in SOPS's default location, set it in keyseal.yaml:

sops:
  binary: sops
  age_binary: age
  age_key_file: /home/you/.config/sops/age/keys.txt

Keyseal passes this through to the SOPS Go decrypt library for read-only commands and to the SOPS CLI for mutating commands. You do not need to prefix every command with SOPS_AGE_KEY_FILE=... unless you want a one-off override.


2. Add a secret

keyseal add production/platform/app

This creates a starter document, encrypts it via SOPS, and writes only the ciphertext to production/platform/app.enc.yaml.

To use a built-in template:

keyseal add production/platform/app --template laravel

Available templates: laravel, stripe, mail, mysql-app. See Templates.


3. Edit the secret

keyseal edit production/platform/app

This opens production/platform/app.enc.yaml in SOPS's interactive editor (your $EDITOR or SOPS default). You edit the decrypted view, save, and SOPS re-encrypts in place.


4. Inspect what changed

keyseal status
keyseal status production/platform/app
keyseal diff production/platform/app
keyseal history production/platform/app
keyseal history production/platform/app --oneline

status stays focused on Keyseal-managed files. diff and history take logical names, not raw file paths.

When you are ready to record the change:

keyseal commit -m "Add production app secret"

Mutating commands also support --commit and -m. -m implies commit. If you want that behavior by default, set git.auto_commit: true in keyseal.yaml.


5. Render to a file

keyseal render production/platform/app --out /run/secrets/app.env

This decrypts the file with the official SOPS Go decrypt library, validates its contents, and writes a dotenv-formatted file. The output file is written atomically (temp file + rename) with mode 0600 by default.

To render to stdout instead:

keyseal render production/platform/app --stdout

To render multiple secrets merged together:

keyseal render production/platform/app production/platform/mail --out /run/secrets/app.env

When multiple secrets are merged, later files win on key conflicts.


6. Run a command with secrets injected

keyseal exec production/platform/app -- php artisan migrate

Secrets are injected as environment variables into the subprocess. They override any matching keys in the current environment. The subprocess inherits all other environment variables.


7. Run doctor

keyseal doctor

Doctor checks your configuration, mutating-command SOPS CLI setup, age key context, and all discovered .enc.yaml files. Common things it catches:

  • Placeholder recipients still in .sops.yaml
  • Empty placeholder .enc.yaml files that still need to be populated
  • Plaintext files at .enc.yaml paths (file was never actually encrypted)
  • SOPS binary missing or not executable for mutating commands
  • age binary missing or not executable for admin key workflows
  • keyseal.yaml invalid or missing

Fix whatever it reports before committing secrets. See Doctor for the full breakdown.


Typical development loop

# first time in a new repo
keyseal init
# edit .sops.yaml to add real age public keys
keyseal add production/platform/app --template laravel
keyseal edit production/platform/app
keyseal status
keyseal commit -m "Update production app secret"
keyseal doctor

# when .sops.yaml recipients change later, sync encrypted files
keyseal updatekeys --all --yes

# every time you need to use secrets locally
keyseal exec production/platform/app -- your-command
# or
keyseal render production/platform/app --out /run/secrets/app.env

Deployment-only usage

On a production/deploy machine that only needs read-only secrets, install Keyseal and provide the encrypted repo plus age private key material. Do not install sops or age just for render or exec:

cd /srv/my-app/secrets
SOPS_AGE_KEY_FILE=/etc/keyseal/age.key keyseal render production/platform/app --out /run/secrets/app.env
SOPS_AGE_KEY_FILE=/etc/keyseal/age.key keyseal exec production/platform/app -- ./start.sh

Servers need the age key, not the age CLI.

Clone this wiki locally