Skip to content
Latchkey

Phoenix "** (RuntimeError) SECRET_KEY_BASE missing" in CI

Phoenix's generated config/runtime.exs requires SECRET_KEY_BASE in prod. When a prod build, release, or prod-env task runs in CI without it set, runtime config raises before the app can start.

What this error means

A MIX_ENV=prod build, mix release, or mix phx.gen.release step fails with "** (RuntimeError) environment variable SECRET_KEY_BASE is missing".

** (RuntimeError)
** (RuntimeError) environment variable SECRET_KEY_BASE is missing.
You can generate one by calling: mix phx.gen.secret
    (my_app 0.1.0) config/runtime.exs:24: MyApp.Config.fetch/0

Common causes

runtime.exs requires the secret in prod

The default Phoenix runtime.exs calls System.fetch_env!("SECRET_KEY_BASE") under prod, which raises when the variable is unset.

CI builds prod without providing the secret

A release or prod compile step runs without SECRET_KEY_BASE in the environment, so runtime config fails at load.

How to fix it

Provide SECRET_KEY_BASE from a secret

  1. Generate a value with mix phx.gen.secret (store it as a repo/org secret).
  2. Expose it in the env of the prod/release step.
  3. Re-run the build.
.github/workflows/ci.yml
- run: mix release
  env:
    MIX_ENV: prod
    SECRET_KEY_BASE: ${{ secrets.SECRET_KEY_BASE }}
    DATABASE_URL: ${{ secrets.DATABASE_URL }}

Guard config that is only needed at boot

If a step only compiles (not boots) prod, gate runtime-only requirements so compilation does not demand runtime secrets.

config/runtime.exs
if config_env() == :prod do
  secret_key_base = System.fetch_env!("SECRET_KEY_BASE")
  # ...
end

How to prevent it

  • Store SECRET_KEY_BASE as a CI secret and inject it into prod steps.
  • Keep runtime-only requirements inside config_env() == :prod.
  • Provide DATABASE_URL and other prod env vars for release builds.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →