Secrets and Environment Variables
Build secrets and environment variables are treated separately. The main differences being:
- Environment variables are saved in the final image and should not contain sensitive information. Since they are in the final image, providers can add variables that will be available to the app at runtime.
- Secrets are never logged or saved in the build logs. They are also only available at build time and not saved to the final image.
Environment Variables
Environment variables can be set in two ways:
- Through step variables:
{ "steps": { "install": { "variables": { "NODE_ENV": "production" } } }}
- Through the deploy section for runtime variables:
{ "deploy": { "variables": { "NODE_ENV": "production" } }}
Secrets
The names of all secrets that should be used during the build are added to the
top of the build plan. Each step that needs access to secrets must include them
in its secrets
field.
Under the hood, Railpack uses BuildKit secrets mounts to supply an exec command with the secret value as an environment variable.
By default, all secrets defined in the build plan are available to each step.
You can explicitly specify which secrets a step should have access to using the
secrets
array. An empty array indicates that no secrets should be available to
that step.
{ "secrets": ["DATABASE_URL", "API_KEY", "STRIPE_LIVE_KEY"], "steps": { "build": { "secrets": ["DATABASE_URL", "API_KEY"] // Only these secrets are available to this step } }}
You can also use "*"
in a step’s secrets array to indicate that it should have
access to all secrets defined in the build plan:
{ "secrets": ["DATABASE_URL", "API_KEY", "STRIPE_LIVE_KEY"], "steps": { "build": { "secrets": ["*"] // This step has access to all secrets } }}
Providing Secrets
You can add secrets when building or generating a build plan with the --env
flag. The names of these variables will be added to the build plan as secrets.
CLI Build
If building with the CLI, Railpack will check that all the secrets defined in the build plan have variables.
railpack build --env STRIPE_LIVE_KEY=sk_live_asdf
Custom Frontend
If building with a custom frontend,
you should still provide the secrets when generating the plan with --env
. This
adds the secrets to the build plan. You then need to pass the secrets to Docker
or BuildKit with the --secret
flag.
# Generate a build planrailpack plan --env STRIPE_LIVE_KEY=sk_live_asdf --out test/railpack-plan.json
# Build with the custom frontendSTRIPE_LIVE_KEY=asdf123456789 docker build \ --build-arg BUILDKIT_SYNTAX="ghcr.io/railwayapp/railpack:railpack-frontend" \ -f test/railpack-plan.json \ --secret id=STRIPE_LIVE_KEY,env=STRIPE_LIVE_KEY \ --build-arg secrets-hash=asdfasdf \ examples/node-bun
For more information about running Railpack in production, see the Running Railpack in Production guide.
Layer Invalidation
By default, BuildKit will not invalidate a layer if a secret is changed. To get
around this, Railpack uses a hash of the secret values and mounts this as a file
in the layer. This will bust the layer cache if the secret is changed. Pass the
secret hash to BuildKit with the --build-arg secrets-hash=<hash>
flag.