teamon
Runtime configuration only for production
Context
I have a small team working on one elixir application.
Every developer runs the app locally.
The app is built with mix release inside docker on CI and deployed as a container.
Over time, we’ve settled on this approach to configuration files:
config/config.exsprovides a common build-time configuration base for all dev/test/prodconfig/dev.exsprovides a build-time configuration for all developersconfig/dev.local.exsgives a handy way to override development config locally - each developer can put whatever they need in there (per-user config, developer secrets, etc.), this file is put into.gitignoreconfig/test.exsprovides all necessary configuration to run tests - this is to ensure thatmix testcan be run right aftergit clonewithout any configuration necessaryconfig/prod.exsprovides build-time config for productionconfig/releases.exsprovides runtime config for production, which is essentially ENV variables mapping withSystem.fetch_env!/1so the app fails to start when some configuration is missing
Config files examples
Click to expand
# config/config.exs - common build-time config for all
use Mix.Config
config :phoenix, :json_library, Jason
import_config "#{Mix.env()}.exs"
# config/dev.exs - all config for development
use Mix.Config
config :myapp, MyAppWeb.BasicAuth, user: "", pass: ""
import_config "dev.local*.exs"
# config/prod.exs - build-time config for production
use Mix.Config
config :myapp, MyAppWeb.Endpoint, server: true
# config/test.exs - all config for test
use Mix.Config
config :myapp, MyAppWeb.Endpoint, server: false
config :myapp, MyAppWeb.BasicAuth, user: "test", pass: "test"
# config/dev.local.exs - local config for development, gitignored
use Mix.Config
config :myapp, MyAppWeb.Endpoint, url: [host: "alice-dev-proxy.example.com"]
config :myapp, MyAppWeb.BasicAuth, user: "", pass: ""
# config/releases.exs - runtime config for production
import Config
config :myapp, MyAppWeb.BasicAuth,
user: System.fetch_env!("ADMIN_USER"),
pass: System.fetch_env!("ADMIN_PASS")
The problem
The new preferred way of runtime configuration is to use config/runtime.exs.
This file will be executed regardless if run with mix or as a part of the release.
Now, if I simply rename my config/releases.exs to config/runtime.exs it will blow up in dev & test due to System.fetch_env!/1 usage. Nobody have all the ENV values referenced locally (a lot of the are secrets).
I can’t seem to find any reference on how to deal with such case.
Any ideas?
Bonus question
Another, somehow-related issues is using .exs files as runtime configuration.
With elixir 1.10 I could add import_config "foo.exs" at the bottom of config/releases.exs and then mount foo.exs file on a production system at /app/releases/0.1.0/foo.exs (docker on kubernetes via ConfigMap).
With elixir 1.11 it now fails with ** (RuntimeError) import_config/1 is not enabled for this configuration file. Some configuration files do not allow importing other files as they are often copied to external systems, which seems to be a bit ironic, as I do want to “copy to external system” ![]()
The question here is: I DO want to use runtime-mounted .exs file as a configuration (alongside ENV vars) simply because it is much better than yaml, but it seems to be discouraged.
Most Liked
wojtekmach
at hexpm we ended up with the following:
# config/runtime.exs
import Config
if config_env() == :prod do
config :hexpm, ...
end
[1] hexpm/config/runtime.exs at 5b86630bccd308ecd394561225cf4ea78b008c8e · hexpm/hexpm · GitHub
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








