Runtime Configuration
config.exs & sys.config
There are differences in how you approach runtime configuration of your application
when using releases vs regular Mix projects. You still use your config.exs
, but
there are caveats which apply:
- With releases, at runtime there is no longer any Mix project information, as your
application is indistinguishable from any other Erlang application. This means your
application should never use anything from the
Mix.*
namespace. - Related to the above, it is not possible to use Mix tasks, generally speaking, you
can include the
:mix
application in a release, but whether it works is uncertain at best, due to the fact that Mix is designed to be used in conjunction with the Mix project structure, and with amix.exs
available. Neither of which are true in releases. - With Mix projects, your configuration is evaluated at runtime, so you can use
functions such as
System.get_env/1
to conditionally change configuration based on the runtime environment. With releases,config.exs
is evaluated at build time, and converted to asys.config
file. Using functions likeSystem.get_env/1
will result in incorrect configuration. Instead, you must configure your application so that if you need to fetch environment information at runtime, you can do so. See the Configuration Conventions section below for more information.
Configuration Conventions
It is a common convention within the Elixir community to handle a {:system, "VAR"}
tuple
which indicates to the application being configured that it should use System.get_env/1
to
fetch that configuration value. This convention can be expanded to also accept a {:system, "VAR", default}
tuple so that you can provide sane defaults if the variable is not set in the environment.
This convention is so valuable, that I’ve provided a Config
module below, which you can drop into
your application, and use in place of Application.get_env/2
, and it will seamlessly handle both of the
conventions above for you. I’ve used it now in a number of applications, and have found it to make
my life much easier. I have considered making it a library on Hex, or adding it to distillery
, but
it is so simple, that a simple gist seems more useful.
See config.ex for the implementation.
If you still want to use it as Hex package, take look at confex.
Configuration Tools
It may be the case that you are providing release packages to end users, who will need to configure the
application. These end users may even be your own internal ops team. They may or may not be familiar with
Erlang terms, and thus sys.config
is a very poor configuration experience. In these situations you may
want to consider an alternative configuration tool I wrote, called conform.
It was designed specifically for use with releases, and with ease of use for end-users as the ultimate goal.
As a developer, you define a schema which maps simple configuration settings contained in an init-style .conf
file,
into the specific structures required for your application’s configuration. To see an example of what these look
like, take a look here.
When you deploy your application, users simply modify the .conf
file as needed, and run the release, conform
handles
converting the configuration into runtime configuration for the release using the schema, and you can access that
configuration via Application.get_env/2
as usual.
vm.args
This file is how you configure the Erlang runtime for your release. By default, it sets up the VM in distributed mode
with the name set to <release_name>@127.0.0.1
, and the cookie set to <release_name>
. This is how we are able to
remote shell to the node once it’s started.
For a complete list of flags you can use in vm.args
, see here.
However, as is often the case, you may want to dynamically configure the name of the node (when clustering) and/or
the cookie (for security), as well as other settings based on values provided via environment variables. You can do
so by setting REPLACE_OS_VARS=true
and then using ${VAR_NAME}
in the vm.args
file.
If you are uncertain where the default vm.args
is located, you may find it under releases/<version>/vm.args
.
You may also provide your own config directory where your custom vm.args
, sys.config
, and potentially other
configuration files will be loaded from, by setting RELEASE_CONFIG_DIR=path/to/files
. By default this will be set
to the root directory of the release, i.e. the folder to which you extracted the tarball. If vm.args
or sys.config
cannot be found in RELEASE_CONFIG_DIR
, it will fall back to using the ones under the releases/<version>
directory.