Files
lazysecrets/docs/repos.md
T
keb b677201e34
CI / Checks (pull_request) Successful in 37s
PR title / Conventional title (pull_request) Successful in 1s
feat: Spring Boot config files in repos
application*.properties/.yml and bootstrap* files tracked by git are
listed under Repos, with their secret-looking keys as secrets.

- Keys whose name ends like a secret (password, secret, token, key, …)
  or whose value looks like one (Jasypt ENC(...), a URL or connection
  string with a password) are listed; providers.repos.spring.keys and
  .values replace the patterns, also in a repo's .lazysecrets.yaml.
- A file's details count the keys left out; ${VAR} values are marked
  as references, and a tracked file is only marked red when a listed
  value is in plain text.
- Later YAML/properties documents name their keys after the profile:
  spring.datasource.password (prod).
- Maven's @placeholders@ parse; Argo CD's applications.yaml and Helm
  templates aren't Spring files.
- A green leaf icon, themeable with springColor.
2026-10-15 13:10:05 +02:00

5.9 KiB

SOPS, .env and Spring files in git repos

lazysecrets shows git repositories under Repos: their SOPS-encrypted files (YAML, JSON, .env, INI), plain env files and Spring Boot config as vaults, and the keys in them (db.password, list[0]) as secrets. A dot or bracket inside a key is escaped, app\.name, so it doesn't read as nesting.

Which repos

Repos lists every repo with secret files under the roots (by default whichever of ~/git, ~/repo, ~/repos, ~/projects, ~/code, ~/source and ~/src exist; one or two levels down, repo or org/repo), any listed in paths, and any you starred something in (the repo, a file or a key), wherever it is. They're checked in the background.

Started inside a repo, that repo gets a row of its own at the top, Repo · <name>, and lazysecrets opens on it, with the files under the directory you started in first. In the flat list (`) it sorts first, marked · here.

A repo without secret files isn't listed. --dir <path> starts somewhere else, for example in one project of a monorepo.

Repos load themselves as they're found, files and keys, since they're local and cheap: Go to searches them without loading anything by hand.

Which files

Env files: .env, .env.local, prod.env and the like, also when git-ignored (as they usually are), in the folders git tracks files in; not .env.example, .sample, .template and the like. They're read directly; a file with SOPS metadata is always treated as SOPS, whatever its name.

Folders of dependencies and caches are never looked in, tracked or not: node_modules, vendor, .venv, venv, __pycache__, .terraform, .gradle, .yarn, .next and the like.

SOPS files: those tracked by git, then the first of

  1. include/exclude in the repo's own .lazysecrets.yaml (committed, so everyone sees the same files),
  2. include/exclude in the config,
  3. where the repo's .sops.yaml creation_rules say SOPS files go,
  4. the whole repo.

include/exclude apply to env and Spring files too.

providers:
  repos:
    roots: [~/git]                             # folders of repos (replaces the defaults; [] turns it off)
    paths: [~/work/infra]                      # single repos elsewhere
    include: ["secrets/**", "**/*.sops.yaml"]  # globs from the repo root; ** for any depth
    exclude: ["**/testdata/**"]

A repo's .lazysecrets.yaml can also name the secret its env files are shared with:

sharing:
  key: https://kv-team.vault.azure.net/secrets/env-share   # or its lazysecrets:// link

Spring Boot config

application.yml, application-prod.properties, bootstrap.yaml and the like, tracked by git (not those in a Helm chart's templates/). Most of their keys aren't secret, so only those that look like one are listed:

  • keys named like a secret: ending in password, pwd, secret, token, key, credentials, salt, connection-string and the like (spring.datasource.password, client-secret, checkoutKey),
  • values that look like one: Jasypt's ENC(...), a URL with a password (jdbc:postgresql://app:pw@db/app), or a connection string with AccountKey=, SharedAccessKey= or Password=.

A file's details count the keys left out, and e opens it whole. A ${DB_PASSWORD} value is marked as a reference: the secret is set elsewhere. A tracked file is marked in red only when a listed key has its value in plain text.

Each list of regexps replaces its default; keys: [".*"] lists every key:

providers:
  repos:
    spring:
      keys: ["(?i)(password|secret|token|key)$", "bearer$"]   # matched against the key's name
      values: ["^ENC\\(.+\\)$"]                               # and against its value

A repo's .lazysecrets.yaml can set spring too, for everyone, and wins over the config, one list at a time.

Keys are named as Spring names them, spring.datasource.password; in a file with several documents (---, or #--- in .properties), a later document's keys get its profile, spring.datasource.password (prod). Values Maven fills in at build time (@project.version@) are read as they are.

Decrypting

Listing never decrypts: SOPS encrypts values only, so keys and metadata (encryption, last modified) are read straight from the files. Revealing, copying or lazysecrets get decrypts one value with your sops binary, so whatever sops uses works (age keys, Azure Key Vault through az, AWS/GCP KMS, PGP). When sops can't decrypt, its whole error message is shown.

On a file, the right pane shows how it's encrypted and the keys it's encrypted for (public: age recipients, Key Vault keys, KMS ARNs, PGP fingerprints), when it was last encrypted, and what git knows of it: tracked, ignored or neither, and its last commit. A plain .env file that git tracks, or that isn't ignored, is marked in red: its values are in the repo's history, or easily could be.

Opening files

e opens the selected file, or on a secret, its file at that key's line:

  • SOPS files open with sops edit, which decrypts them into your editor ($SOPS_EDITOR or $EDITOR) and encrypts them again when you save. lazysecrets comes back after, with the file's keys reloaded.
  • Other files, when lazysecrets runs inside nvim (its plugin, or :terminal): lazysecrets quits and the file opens in that nvim, in the window you came from.
  • Otherwise in $VISUAL or $EDITOR in the terminal, coming back after; without either, in the system's default app for the file.

Editors that take a line (vim, nvim, nano, emacs, micro, helix, VS Code, Zed, Sublime and others) start on the key. With sops edit that works for editors taking +N (vim, nvim, nano, emacs, micro and others), and needs sops 3.8 or later.

Repo links name the repo by its git remote, so they open in a colleague's clone wherever it is (sharing).