Elixir 1.9 runtime config for multiple app name

I have an application that needs to run under 2 different name/configuration on the same box. I have read the mix release documentation but I can’t figure out how I can do this. For dynamic configuration, it says that I need to create a config/releases.exs file as such:

import Config
config :my_app, :secret_key, System.fetch_env!("MY_APP_SECRET_KEY")

However I have some config value that I cannot be put in an environment variable, is there a way to have a config.exs file per application name on the target machine ?

Here’s my mix.exs project section.

  def project do
    [
      app: :my_app,
      version: "0.1.0",
      elixir: "~> 1.9",
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      releases: [
        as: [
          include_executables_for: [:unix],
          applications: [runtime_tools: :permanent]
        ],
        vs: [
          include_executables_for: [:unix],
          applications: [runtime_tools: :permanent]
        ]
      ]
    ]
  end

I would like to have different runtime config for the as and vs app names.

I understand you are trying to get your app’s name depending on context in order to achieve a different runtime behavior. Maybe you could use a new ENV variable that dictates how you app is named? For example:

def project do
    [
      app: get_app_name(),
    ]
  end

defp get_app_name do
 case System.fetch!("SOME_VAR") do
   "bananas" -> :hello
   "oranges" -> :world
   _ -> :default 
 end
end

If you cannot, by any means, use ENV variables at all, then I suggest your go for an alternative approach since afaik, it is not possible to have a mix.exs file per app name, since OTP apps are only allowed to have 1 name during runtime.

You can use runtime_config_path (mentioned in the docs here). You can also access all environment variables, include RELEASE_NAME, inside the script itself: https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-environment-variables

2 Likes

@josevalim if understand, the config file will be copied as is to the release, so it needs to be on the build box. I wished that there was a way to have the config file only located on the target system. If I understand there is no direct way of doing this for the moment.

This can cause me some issue since I would like our sys admins to be able to change the configuration on the target system without needing to generate a new release.

For the moment, In order to avoid storing my secrets into my source control, I will use a combination of environment variable and the use of the runtime_config_path variable.

Because the config script is regular Elixir code, you can have the config/releases.exs execute another config file (or load any other file) that your devops/admin team will change.

For example:

release_root = System.fetch_env!("RELEASE_ROOT")
for {application, kv} <- Config.Reader.read!(Path.join(release_root, "config.exs")),
    {key, value} <- kv do
  config application, key, value
end
4 Likes