Handling Environment Variables in Phoenix

Environment variables are commonly used to connect different services and configure an application for different environments. Configuration is handled differently in Elixir and Phoenix applications but there are useful patterns to get started with and improve on as your system requires.

We're going to cover a handling development and production configuration for Phoenix applications for Releases introduced in Elixir 1.9, and for production deployment using tools like Distillery.

We'll configure development using a dev.secret.exs file, and also cover build-time vs run-time configuration in different contexts.

Import dev.secret.exs

Where are the env variables?

By using the recommended Config module we have eliminated the need to use local environment variables.

We can safely hard-code our configuration in dev.secret.exs, exclude it from the repository and it's evaluated at build time while the application compiles for local development.

Accessing Configuration Vars

Depending on the service package, this will mostly likely be handled internally.

To access the variables set in config files:

$ Application.fetch_env!(:external_service, :api_key)

Production Configuration (releases)

The release system in Elixir 1.9 is an important improvement for Elixir applications that provides ways to set configuration at run-time.

We should cover the differences between build vs run time configuration in more detail as it's important to understand before using releases.

The config/prod.exs file is evaluated at build-time according to the docs:

config/config.exs (and config/prod.exs) - provides build-time application configuration, which are executed when the release is assembled.

Whenever you invoke a mix command, Mix loads the configuration in config/config.exs, if said file exists. It is common for the config/config.exs file itself import other configuration based on the current MIX_ENV, such as config/dev.exs, config/test.exs, and config/prod.exs.

We say that this configuration is a build-time configuration as it is evaluated whenever you compile your code or whenever you assemble the release.

Configuring our application for production in these files may not work if there are separate build/target environments and other nuances. Additionally, we need to keep sensitive data safe.

Runtime Configuration

To enable runtime configuration the recommended pattern is to create config/releases.exs which will be copied to your release and executed as soon the system starts.

In a default Phoenix installation there is a prod.secret.exs file which can renamed to releases.exs

Conclusion

Runtime configuration for Elixir apps is a complex subject but we covered some basic patterns for development, production and CI/Test environments. We also touched on the differences between compile-time vs runtime configuration for Phoenix Applications.

Releases added some important APIs for handling configuration. Understanding how to use these systems in Phoenix applications for different deployment pipelines and target hosts is an important piece of the overall pie.