DEV Community

Kingsley Kanu
Kingsley Kanu

Posted on Originally published at iamkay.eu

Where my secrets live, and what the repo gets instead

A repository is a very good place to lose a secret. It is copied to every clone, mirrored to every remote, kept forever, and read by tools that never ask whether a line was meant to be private. So the rule I work to is simple: the repo holds the shape of the configuration, never the values.

What goes where

Secrets live in a password manager I host myself. Nothing else is the source of truth. A database password, an API token or a private key exists in exactly one place, and everything else refers to it.

The repository carries a template instead. Each project has an example environment file with the same variable names as the real one and placeholder values that mean nothing. Anyone reading the repo can see what has to be supplied. Nobody reading it can see what was supplied.

The real values reach a machine at deploy time, through an environment file that is created on the target and never committed. The build and deploy scripts read from the environment. They do not contain a value to fall back on, because a default password in a script is a committed password with extra steps.

Three habits that do the real work

  1. Look at what is staged before every commit. git diff --cached takes seconds, and it catches the file that was only supposed to be in the working tree for a minute.
  2. Make the ignore file say it first. The real environment file is ignored from the first commit of a project, before it exists, so there is never a moment when adding everything picks it up.
  3. Scan automatically as well. A secret scanner running as a pre-commit hook, gitleaks being one example, catches the cases where attention was elsewhere. It is a second net, not a replacement for the first.

When one gets committed anyway

Deleting it in the next commit does not help. The old commit still has it, every clone still has it, and any mirror may already have copied it. Once a secret has been committed it is compromised, and the fix is to rotate it at the source: issue a new one, change what uses it, revoke the old one. Cleaning the history is worth doing afterwards, but it is tidying, not remediation.

That ordering matters because the instinct goes the other way. Removing the file feels like the fix, and rotating the secret feels like admitting something happened. Rotating is the one that actually closes the exposure.

Why bother in a homelab

It is tempting to treat a private repo on my own network as safe enough. I do not, because a habit that only switches on when the stakes are high will not be there on the day they are, and the repo that is private today gets a second remote, a collaborator or a mirror tomorrow. Keeping values out of git from the start costs almost nothing. Retrofitting it later costs a rotation of everything that was ever in there.

Top comments (0)