API & Automation·8 min read·

Secrets in Configuration Management Systems

Keep passwords and API keys out of git with Ansible Vault, sensitive Terraform variables, and rotation habits that work with real systems.

NB

Netbay Developer Relations

Netbay Engineering

On this page

Every configuration management system eventually needs a password, an API key, or a private key at apply time. The temptation is to paste it into a variables file, and six months later it is in the git history, in a teammates terminal scrollback, and in a copied Terraform state. Secrets handling is the difference between automation you brag about and automation that leaks. This post shows the two dominant patterns — Ansible Vault and Terraform's sensitive variables — plus the habits that make them hold up.

Ansible Vault: Encrypt Files, Not Workflows

Ansible Vault is symmetric file encryption built into Ansible. You keep one key file or password per environment; encrypted values ride along in the repository but are unreadable without the key:

bash
ansible-vault create group_vars/prod/vault.yml
ansible-vault edit group_vars/prod/vault.yml
ansible-playbook site.yml --ask-vault-pass
ansible-vault encrypt_string 's3cr3t' --name db_password

A vaulted file holds arbitrary YAML, so the workflow is identical to a normal variables file — the encryption is transparent at run time. A playbook consumes it like any other variable:

yaml
- name: Wire database secrets
  hosts: databases
  vars_files:
    - vault_db.yml
  tasks:
    - name: Pass the secret into a config template
      ansible.builtin.set_fact:
        pg_password: "{{ vault_db_password }}"

    - name: Write the app config
      ansible.builtin.template:
        src: app.env.j2
        dest: /opt/app/.env
        mode: "0600"

Note mode 0600: the final config file is readable by the service user only, and the template renders on the target, so the plaintext secret never has to sit in a file the repository stores. One key per environment, plus a rotation date in the ticket tracker, is enough to start.

Terraform: Mark It Sensitive, Feed It from Outside

Terraform state stores every attribute it tracks, so a password that appears in configuration will land in terraform.tfstate in plaintext. Marking a variable sensitive keeps it out of plan and apply output, but it still lives in state — which is why the state backend from earlier in this series must be encrypted and access-controlled:

hcl
variable "db_password" {
  type        = string
  sensitive   = true
  description = "Database password, injected by CI, never committed"
}

Feed the value from environment variables or a secret manager at plan-and-apply time rather than from a committed tfvars file. Because sensitive values are still recorded in state, treat the state store as a secrets vault that deserves the same encryption, locking, and access review as the production database itself.

Habits That Keep Vaults Honest

Tooling is only as strong as the routine around it:

  • **Scan the repo before you encrypt** — git history stays forever, so rotate anything that ever existed in plaintext.
  • **Rotate on a schedule, not on an incident** — a quarterly db password bump is boring, which is the point.
  • **Least privilege per environment** — a staging key should not unlock production secrets, whatever tool you pick.
  • **Never log vault values** — debug tasks and plan output are silent leak vectors; redact them in CI where you can.
Secret flow at apply time control node vault key entered once per run vaulted vars encrypted in git decrypted on demand managed node app /opt/app/.env mode 0600 terraform state still holds plaintext => encrypt the backend plaintext reaches only the target machine, at the moment it is needed

Takeaway

Pick one pattern per tool — Vault for Ansible, sensitive-fed-from-outside plus an encrypted backend for Terraform — and pair it with the rotation routine, because the tooling is trivial and the discipline is the real work. Run one practice rotation end to end on a test server before you need it in an incident. Netbay's fast provisioning on netbayhosts.in makes that dry-run of the rotation routine cheap to rehearse.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance