SopsConfigProvider

Decrypt secrets from sops file and set the config to your application on runtime.

Installation

The package can be installed by adding sops_config_provider to your list of dependencies in mix.exs:

def deps do
  [
    {:sops_config_provider, "~> 0.1.0"}
  ]
end

Usage

[ATTENTION] Please make sure that you have sops installed, and proper permission to encrypt and decrypt the file. See SOPS docs for sops intallation and setup

After the installation, you need to add the provider into def project section in mix.exs.

      releases: [
        change_with_your_app_name: [
          config_providers: [
            {
              SopsConfigProvider,
              %{
                app_name: :change_with_your_app_name,
                secret_file_path: "priv/secrets.yml" # I'd recommend to put
                # the secrets inside the priv directory, as it automatically get
                # copied on release
              }
            }
          ]
        ]
      ]

The config provider will decrypt the secrets and set the config like you do in runtime.exs

For example, if you have secrets config in yaml as below

# priv/secrets.yml
sentry:
    dsn: "https://sentry.io"

It'll set the value below and app boot like on runtime.exs

config :sentry, dsn: "http://sentry.io"

Options

Pass options as a map (second element of the tuple) in config_providers.

Option Type Required Default Description
app_nameatom yes Your app name. Used to resolve secret_file_path via Application.app_dir/2.
secret_file_pathstring yes Path to the SOPS-encrypted file relative to the app dir. Supports .json, .yaml, .yml.
sops_binary_pathstring no "sops" Path to the sops binary. Override if sops is not on PATH.
execution_dirstring no "./" Working directory used when running sops -d. Relevant when sops resolves key config (e.g., .sops.yaml) relative to cwd.
env_variables[{string, string}] no [] Environment variables injected into the sops process. Useful for passing AWS/GCP credentials at runtime.
mappingsmap no %{} Remap flat secret keys into nested module configs. See Mappings below.
env_overrideboolean no false Allow OS env vars to override decrypted SOPS values. See Env Override below.
config_envatom no :prod Config environment.

Mappings

mappings lets you nest a secret key under a specific module within an app's config.

Structure:

%{
  app_atom => %{
    secret_key => {TargetModule, :nested_key}
  }
}

Example — map :db_url in :my_app into {MyApp.Repo, :url}:

{
  SopsConfigProvider,
  %{
    app_name: :my_app,
    secret_file_path: "priv/secrets.yml",
    mappings: %{
      my_app: %{
        db_url: {MyApp.Repo, :url}
      }
    }
  }
}

Given this secret file:

my_app:
  db_url: "ecto://user:pass@localhost/mydb"
  other_key: "value"

Produces:

config :my_app, MyApp.Repo, url: "ecto://user:pass@localhost/mydb"
config :my_app, other_key: "value"

Env Override

Set env_override: true to allow OS environment variables to override values from the SOPS file. Useful for emergency overrides or per-deploy flexibility without re-encrypting the secrets file.

Naming convention:APP_KEY — the app atom and config key joined with _, uppercased.

YAML key App Derived env var
api_keystripity_stripeSTRIPITY_STRIPE_API_KEY
dsnsentrySENTRY_DSN
passwordorcaORCA_PASSWORD
webhookslackSLACK_WEBHOOK

Only flat atom keys are overridable. Nested module keys (set via mappings) are not derived and must be changed via the SOPS file.

An env var is ignored if it is not set or is an empty string — the SOPS value is used as-is.

{
  SopsConfigProvider,
  %{
    app_name: :my_app,
    secret_file_path: "priv/secrets.yml",
    env_override: true,
    mappings: %{
      my_app: %{
        database_url: {MyApp.Repo, :url}
      }
    }
  }
}

With this config, setting SENTRY_DSN=https://new-dsn as an OS env var overrides the sentry > dsn value from the SOPS file at runtime. No re-encryption needed.

env_variables example

Pass AWS credentials when the runtime environment doesn't have them on the system:

{
  SopsConfigProvider,
  %{
    app_name: :my_app,
    secret_file_path: "priv/secrets.yml",
    env_variables: [
      {"AWS_ACCESS_KEY_ID", System.get_env("AWS_ACCESS_KEY_ID")},
      {"AWS_SECRET_ACCESS_KEY", System.get_env("AWS_SECRET_ACCESS_KEY")}
    ]
  }
}