Skip to content

Configuration Reference

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

Configuration Reference

Keyseal reads keyseal.yaml from the current working directory. All fields are optional except version and repository.root - everything else has a default that config.Load applies if the field is absent or zero.

Minimal valid config

version: 1
repository:
  root: .

This is technically complete. All other fields take their default values.

Full example

version: 1

repository:
  root: .
  encrypted_extension: .enc.yaml

sops:
  binary: sops
  age_binary: age
  age_key_file: ~/.config/sops/age/keys.txt

git:
  auto_commit: false

defaults:
  output_format: dotenv
  output_dir: /run/secrets
  file_mode: "0600"

validation:
  require_values: true
  key_pattern: "^[A-Z0-9_]+$"

Fields

version

Type: integer
Required: yes
Valid value: 1

Must be exactly 1. Any other value causes config.Load to fail.


repository

repository.root

Type: string
Default: "."

Path to the repository root, relative to the location of keyseal.yaml. Keyseal resolves all secret file paths relative to this directory. In most cases this should be ".".

If you place keyseal.yaml in a subdirectory of your repo and want Keyseal to look for secrets in the repo root, set this to something like ".." - but be aware that path traversal in logical names is blocked, so your root must be the directory you are actually working in.

repository.encrypted_extension

Type: string
Default: ".enc.yaml"

The suffix appended to logical names to form file paths. Must start with "." and must contain ".yaml". Changing this after a repo has been populated will break all existing file lookups unless you rename the files.


sops

sops.binary

Type: string
Default: "sops"

Name or full path of the SOPS binary for mutating operations. Keyseal shells out to this for add, edit, and updatekeys. Read-only render, exec, doctor, and verify decrypt with the official SOPS Go decrypt library and do not use sops.binary.

sops:
  binary: /usr/local/bin/sops

Mutating commands check this binary before creating, editing, or rotating encrypted files so missing tools fail early with a clear error.

sops.age_binary

Type: string
Default: "age"

Name or full path of the age binary for developer/admin key workflows. Keyseal does not call the external age CLI for read-only decrypt operations. Production servers need age private key material, not the age CLI.

sops:
  age_binary: /usr/local/bin/age

sops.age_key_file

Type: string
Default: "~/.config/sops/age/keys.txt"

Path to the age private key file. Keyseal passes this to the SOPS Go decrypt library for render, exec, doctor, and verify, and to the SOPS CLI for add, edit, and updatekeys, when SOPS_AGE_KEY_FILE is not already set in the shell.

Precedence is:

  1. SOPS_AGE_KEY_FILE from the environment
  2. sops.age_key_file from keyseal.yaml
  3. SOPS default behavior

A leading ~ is expanded to the current user's home directory. Relative paths are resolved from the directory containing keyseal.yaml.


defaults

These values are used as fallbacks when the corresponding flag is not passed to a command.

defaults.output_format

Type: string
Default: "dotenv"
Valid values: dotenv, json, yaml

The format used by keyseal render when --format is not passed.

defaults.output_dir

Type: string
Default: "/run/secrets"

The default output directory. Currently used as reference context - render requires either --out or --stdout to be specified explicitly; it does not silently use this directory. Doctor checks that this path is not relative.

defaults.file_mode

Type: string (4-digit octal)
Default: "0600"

The file mode applied to rendered output files when --mode is not passed to render. Must be a 4-character string starting with "0", parseable as an octal number (e.g. "0600", "0640").

Doctor warns if the configured mode has group or world bits set (i.e. is not owner-only). render --out will reject unsafe modes unless --force is passed.


git

git.auto_commit

Type: boolean
Default: false

Controls whether mutating commands (add, edit, rollback) create a Git commit automatically after they succeed.

When enabled, Keyseal stages only the file touched by the command and creates a commit with a generated default message unless you provide -m, --message.

Command-line flags take precedence:

  1. -m, --message implies commit
  2. --commit forces commit
  3. --no-commit suppresses commit
  4. git.auto_commit provides the default when no commit flags are passed

keyseal commit is separate. It stages current Keyseal-managed changes and commits them regardless of git.auto_commit.


validation

These settings control how secret document contents are validated.

validation.require_values

Type: boolean
Default: true

When true, a secret document with an empty values map is rejected. This applies to both add (validates the starter document before encrypting) and render/exec (validates after decrypting).

Set to false only if you have a legitimate reason to store empty-values documents.

validation.key_pattern

Type: string (Go regular expression)
Default: "^[A-Z0-9_]+$"

Every key in the values map of every secret document must match this pattern. The default pattern requires uppercase letters, digits, and underscores only - which is the standard convention for environment variable names in most contexts.

Must be a valid Go regexp. An invalid pattern causes config.Load to fail.

To allow lowercase keys, you could set "^[A-Za-z0-9_]+$", but be aware this relaxes validation across all secrets in the repo.


profiles

Type: map of profile name → profile object
Default: a single empty profile named "default"

This section is reserved. The profiles structure is parsed and validated by doctor (for output path safety), but no command currently executes profiles. The format is documented here for completeness.

profiles:
  default:
    renders:
      - name: app-env
        inputs:
          - production/platform/app
          - production/platform/mail
        format: dotenv
        out: /run/secrets/app.env
        mode: "0600"

Each profile has a renders list. Each render entry describes a set of inputs, a format, and an output path. When profiles are eventually executed, they will provide a way to declare render operations declaratively rather than repeating command-line invocations.

Do not rely on profiles being executed in the current release.


Config loading behavior

config.Load applies defaults to any missing or zero-value field after unmarshaling the YAML. A field set explicitly to its zero value (e.g. require_values: false) is not overwritten - the override is intentional.

The "default" profile key is always present after loading, even if your config does not mention profiles at all.

Config validation runs immediately after defaults are applied. Any validation error (invalid version, bad regexp, unknown format, malformed file mode) is returned as an error from config.Load before any command proceeds.

Clone this wiki locally