Skip to main content

Manage Secrets

The app-config component needs two secrets: a third-party API_KEY and a structured DB_CONFIG (JSON) containing database credentials. Atmos manages these with a dedicated secrets workflow that keeps them out of your stack YAML and — importantly — out of the .tfvars files written to disk.

In this tutorial the secret backends are the same emulated SSM Parameter Store and Secrets Manager running in your local sandbox, so you can practice the full secrets workflow with no cloud account.

Declare the secret stores

Secrets are stored in stores marked secret: true. The example declares two of them in atmos.yaml, both authenticating to the sandbox via the local-aws identity:

stores:
secrets/ssm:
kind: aws/ssm # AWS SSM Parameter Store (SecureString)
identity: local-aws
secret: true
options:
region: us-east-1
prefix: /atmos/quickstart/secrets
secrets/asm:
kind: aws/asm # AWS Secrets Manager
identity: local-aws
secret: true
options:
region: us-east-1
prefix: /atmos/quickstart/secrets

Declare the secrets on the component

A component declares which secrets it consumes in its secrets.vars section. Each entry names the backing store and whether it's required. The app-config catalog declares both secrets:

components:
terraform:
app-config:
secrets:
vars:
API_KEY:
description: "Third-party API key for the application."
store: secrets/ssm
required: true
DB_CONFIG:
description: "Structured database credentials (JSON) stored in Secrets Manager."
store: secrets/asm
required: true
store
Which declared store holds this secret. API_KEY lives in the emulated SSM Parameter Store (secrets/ssm); DB_CONFIG lives in the emulated Secrets Manager (secrets/asm).
required
When true, Atmos fails fast if the secret has no value before the component is provisioned, rather than passing an empty value to Terraform.
scope
Optional. When set to scope: global, a secret is shared across every stack that uses the same store and declaration, instead of being scoped to a single stack+component. The two secrets in this tutorial use the default (per-stack) scope, but scope: global is useful for credentials that are identical everywhere (for example, a shared read-only token).

Set secret values

In an interactive terminal, run atmos secret and let Atmos guide you through the required secrets for app-config:

atmos secret -s plat-ue2-dev -c app-config

You can also set each secret explicitly with atmos secret set. The simplest invocation supplies the value inline as NAME=VALUE:

atmos secret set API_KEY=sk-quickstart-example -s plat-ue2-dev -c app-config
atmos secret set 'DB_CONFIG={"username":"app","password":"s3cr3t"}' -s plat-ue2-dev -c app-config
--stack / -s
The stack the secret belongs to (e.g. plat-ue2-dev).
--component / -c
The component whose declaration the secret belongs to (e.g. app-config).
tip

atmos secret set can also read the value from standard input with --stdin, or prompt for the value interactively (masked) when you run it without supplying NAME=VALUE. See atmos secret set.

Import secrets from a file

To seed many secrets at once — for example from a local .env file — use atmos secret import. Each key is routed to the backend declared for it:

atmos secret import .env -s plat-ue2-dev -c app-config

Add --dry-run to preview what would be written without changing any backend.

List secrets

atmos secret list shows the declared secrets and whether each has a value, without decrypting or printing the values:

atmos secret list -s plat-ue2-dev -c app-config

Consume secrets in the stack

Components consume secrets with the !secret YAML function. For the structured secret, you can extract a single field with a path expression:

components:
terraform:
app-config:
vars:
api_key: !secret API_KEY
db_password: !secret DB_CONFIG | path ".password"

Secrets never touch disk

This is the key property of the workflow: secret values are delivered to Terraform as TF_VAR_* environment variables, not written into the generated .tfvars file. So api_key arrives as TF_VAR_api_key and db_password as TF_VAR_db_password. The Terraform variables that receive them are declared sensitive = true. This means a secret never lands in a plaintext file in the component directory, even though the rest of the component's variables do.

tip

For the full command reference, see the atmos secret command group.


Next: catch mistakes before they reach Terraform → Validate Configurations →