TractorStackdocs
Docs menu

Docs / Trust & compliance

Secrets & credentials

Planned design. TractorStack is in development. This page describes how it is designed to work; nothing here is available to install yet. See the roadmap for the status of each part.

In design The options below are the current design and may change before the first release.

Secrets management and credentials are where an everything-in-Git approach needs the most care. Database passwords, API keys, TLS private keys, hypervisor logins and backup encryption keys all have to reach the machines that use them, but none of them should ever sit in a Git repository in plain text, not even in a private one, and not even for a moment in an old commit.

The rule: never plain text in Git

The repository is copied to laptops, the site runner and backups. Anything in it should be safe to lose. So the design keeps either encrypted secrets or references to secrets in Git, never the values themselves. A check in the GitLab CI pipeline is planned to reject commits that look like they contain a key or password, as a safety net rather than the main defence.

Secrets management and credentials: two planned options

SOPS with ageOpenBao or HashiCorp Vault
Where secrets liveEncrypted files in the repositoryA separate secrets service on site
Extra serversNoneOne service, ideally highly available
Access controlWho holds which age keyPolicies per path, per role
Access logGit history of the encrypted filesBuilt-in audit log of every read
Good fitStage 1 and 2, small teamsSeveral teams, stage 3 and 4, short-lived credentials

With SOPS, values are encrypted per field, so a diff still shows which key changed without showing its value. Decryption happens on the site runner during a run. With OpenBao or Vault, OpenTofu and Ansible fetch secrets at run time and the repository holds only paths. Either way, secrets stay out of GitLab CI variables, so they don’t sit on the GitLab server. We choose with each customer; switching later is possible but takes planning.

# planned example: what Git holds with SOPS
db_password: ENC[AES256_GCM,data:...,type:str]
sops:
  age:
    - recipient: age1...siterunner

OpenTofu state can also contain secrets. It stays in PostgreSQL on site, and OpenTofu’s client-side state encryption is planned to be on by default. See Where state lives.

Scope: who can read what

Tokens for pipelines and scripts are covered in Automation tokens, and tenant separation in Teams & tenants.

Rotation

Each secret is planned to carry an owner and a rotation interval in the repository. Rotating means generating a new value, applying it through a normal change request, and confirming services still work before the old value is revoked. Routine checks are planned to flag secrets past their interval. When someone leaves, their age key or Vault access is removed and anything they could read is put on the rotation list.

Break-glass access

If the secrets service is down or the runner is lost, someone still needs to get in. The design keeps a small set of emergency credentials, sealed offline (for example printed and held by two people, or split between them), with a written runbook for using them. Opening the envelope is logged, and every break-glass credential is rotated afterwards.

Back up the keys that decrypt your backups, somewhere other than the backups. Losing an age key or a Vault unseal key can make every encrypted copy unreadable.

Last updated 25 October 2026 · Questions or corrections: sales@infratractor.com