Managing secrets
Every application needs credentials, and the question is only how badly they are stored. Here is a ladder you can climb at your own pace.
Where they must not be
- In the repository. Git keeps history: removing a key in a later commit does not remove it. Assume anything ever committed is public.
- In the container image. Layers are permanent and anyone who can pull it can read them — see running containers safely.
- On the command line.
psshows arguments to every user on the machine, and your shell history keeps them. - In a world-readable config.
chmod 600and the right owner, at minimum.
The ladder
- 1. An environment file
EnvironmentFile=/etc/myapp/envin the unit, mode 600, owned by the service user. Simple, and a large improvement on a committed config.- 2. systemd credentials
LoadCredentialEncrypted=decrypts a secret into memory for that service only, bound to the machine. No plaintext on disk at all.- 3. A secret store
- HashiCorp Vault, Infisical or OpenBao. Central, audited, with rotation and short-lived credentials. Worth it once several machines and several people are involved.
Most servers belong on rung one or two. Climbing further costs operational effort and should solve a problem you actually have.
In a repository, encrypted
If you want secrets version-controlled, encrypt them: sops with age or
GPG, or ansible-vault if you already use
Ansible. The file in the repository is
ciphertext; decryption happens at deploy time. That gives you review and history
without publishing anything.
Separate per environment and per service
Staging must not share credentials with production — see staging and test servers — and each service gets its own database user with only the rights it needs. When something leaks, that containment decides whether you rotate one credential or all of them.
Rotation
Rotate on a schedule, and immediately when:
- Someone with access leaves — see users and sudo
- A key was committed, pasted into a ticket, or sent over chat
- A machine may have been compromised — see a compromised server
Rotation is only realistic if it is scripted. A credential that takes an afternoon of manual editing to change will not be changed when it matters.
Our side of it
Your API key is a credential of exactly this kind: out of the repository, restricted to the addresses your automation runs from, and revoked the moment it may have leaked. Tell us and we kill it immediately — no waiting period, no charge. See keeping your account secure.
Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base