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.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.yamlshares 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.
Step 1: Create the environment secret
Create one secret per environment, named for the environment and the app. We useprod/ravion.
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
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
- 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
-AbCdEfsuffix is part of the ARN. It’s generated by AWS, so read the ARN withdescribe-secretrather than assembling it by hand. - Quote the value in YAML. An unquoted string ending in
::is fine in most parsers, but quoting avoids surprises.
...: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
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: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.
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
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:Decryptfor the execution role. The identity-side permission is already there; the key policy isn’t. - A supplied execution role — when you set
execution_role_arnyourself — 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 SSMSecureString parameter ARN works too:
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 reportandravion feedbacksend what you type to us — review the message first.
Troubleshooting
Related pages
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.