Skip to main content
Native secret management is coming soon. Ravion will let you create, edit, and share secrets directly from the dashboard, the CLI, and ravion.yaml. Until then, you own the secret values in your AWS account and Ravion references them — which is what this guide covers.
Ravion never stores your secret values. Terraform and your deployments run inside your own AWS account, so a secret’s value only ever moves from AWS Secrets Manager (or SSM Parameter Store) into your running task. Your Ravion config holds references — ARNs — not values, which makes ravion.yaml safe to commit. The pattern we recommend, and the one we use for Ravion itself: One Secrets Manager secret per environment, holding a JSON object of many keys. Each module then references individual keys out of that one secret.

Why one secret with many keys

The obvious alternative — one Secrets Manager secret per environment variable — works, but it scales badly:
  • Cost. Secrets Manager bills per secret, per month. Forty secrets cost forty times as much as one secret with forty keys.
  • One place to edit. Adding a variable is a JSON key edit, not a new AWS resource, a new ARN, and a new config entry pointing at it.
  • One ARN to remember. Every reference in ravion.yaml shares the same ARN prefix and differs only by the key name, so the config stays readable and diffs stay obvious.
  • One audit trail. Secrets Manager versions the whole JSON document, so every change to any variable is a single version you can inspect or roll back.
This applies to the secrets you create. Leave secrets that a module or AWS creates for you — database master passwords, cache connection strings — where they are, and reference them by their own ARN. Those rotate in place without touching your environment secret. Each module’s catalog page documents the secret it creates, and you’ll find its ARN in the module’s stack outputs.

Step 1: Create the environment secret

Create one secret per environment, named for the environment and the app. We use prod/ravion.
Create the secret in the same AWS account and region as the modules that read it. The generated execution role policy is scoped to the current account, so cross-account secret references don’t work (see Permissions).
Keep the environment in the name even when each environment lives in its own AWS account. The ARN then says which environment it belongs to on its own, which matters when you’re reading it in a config diff, a task definition, or an IAM policy.
Then grab the full ARN, which includes the six-character suffix AWS appends:

Step 2: Reference keys from your modules

ECS modules (rvn-ecs-web, rvn-ecs-worker) take a Runtime secrets (secrets) input: a list of {name, valueFrom} objects, where name is the environment variable inside your container and valueFrom is an ARN. Append the JSON key to the ARN to pull a single key out of the document:
ravion.yaml
Use environment_variables for anything non-sensitive and secrets for everything else. Secret values never appear in the Ravion dashboard, in your config file, or in build logs.

Anatomy of the ARN

Three things trip people up:
  • The trailing :: is required when you specify a JSON key. The empty version stage and version ID mean “whatever is current” (AWSCURRENT), which is what you almost always want. Omit them and ECS rejects the ARN.
  • The -AbCdEf suffix is part of the ARN. It’s generated by AWS, so read the ARN with describe-secret rather than assembling it by hand.
  • Quote the value in YAML. An unquoted string ending in :: is fine in most parsers, but quoting avoids surprises.
Leave the key off entirely — ...:secret:prod/myapp-AbCdEf — and ECS injects the entire secret string into the variable, JSON braces and all. That’s only what you want when the secret holds a single plain value, which is typical of the secrets a module creates for you.

Step 3: Apply and deploy

Adding or removing a secrets entry changes the task definition, so it takes effect on the next deployment of that module.

Rotating and adding values

Adding a key is a change to the JSON document, not to your Ravion config — except for the one line that maps it to an environment variable.
1

Update the JSON document

put-secret-value replaces the whole document, so merge rather than overwrite:
Editing the secret in the AWS console does the same merge for you.
2

Map it to an environment variable

Add an entry to secrets in ravion.yaml and apply the config. Skip this step when you’re rotating a value that’s already mapped.
3

Redeploy to pick up new values

ECS resolves secrets when a task starts, so a rotated value doesn’t reach running tasks. Deploy the module — or otherwise force new tasks — to roll the new value out.
Rotating a secret in place is not zero-risk: during the rollout, old tasks hold the old value and new tasks hold the new one. For credentials that can’t tolerate that overlap, accept both values during the rollout, or roll dependent services in a deliberate order.

Secrets during builds

Runtime secrets are injected into the running container, not into the build. When a build needs a credential — a private package registry token, for example — use Build environment variables (build_environment_variables), which accept a reference instead of a literal value:
ravion.yaml
For Dockerfile builds, set dockerfile_inject_env_variables: true to pass these through as Docker build arguments, and declare a matching ARG in your Dockerfile. Build arguments are visible in image history, so prefer runtime secrets for anything the build doesn’t strictly need.

Permissions

When Ravion creates the ECS execution role for a service, it attaches a policy that allows reading Secrets Manager secrets and SSM parameters and decrypting them with KMS, conditioned on the resource living in the same AWS account as the service. So the common case needs no IAM work from you. Three cases do need attention:
  • Cross-account secrets don’t work with the generated policy. Replicate the secret into the workload account instead.
  • Customer-managed KMS keys need the key’s own resource policy to allow kms:Decrypt for the execution role. The identity-side permission is already there; the key policy isn’t.
  • A supplied execution role — when you set execution_role_arn yourself — bypasses the generated policy entirely. Attach the equivalent permissions to your role.

SSM Parameter Store as an alternative

Anywhere a Secrets Manager ARN works, an SSM SecureString parameter ARN works too:
Parameter Store has no per-parameter charge for standard parameters, which makes one-parameter-per-value affordable. The tradeoff is that each value is its own resource with its own ARN, and there’s no JSON key selection — so you lose the single-document editing and versioning that makes the one-secret pattern pleasant. Use Parameter Store for a handful of values, and the one-secret pattern once you have more than a few.

Practices worth keeping

  • Never let environments share a secret. A staging secret should never be reachable from production, or vice versa — separate secrets, ideally in separate AWS accounts.
  • Split a secret only for access control. One secret per environment is the default; add another when a team shouldn’t be able to read another team’s values.
  • Don’t paste secret values into support reports. ravion report and ravion feedback send what you type to us — review the message first.

Troubleshooting

ECS Web Service

Runtime secrets and build environment variables for rvn-ecs-web.

ECS Worker

The same secrets input for background workers.

Project config file

How ravion.yaml is structured and applied.

How Ravion works

Why secret values stay inside your AWS account.

Builds

Build environment variables and Docker build arguments.