Luis Rascão edited this page Nov 27, 2016 · 3 revisions


Configuration of relx is done via Erlang key-value elements in the relx.config file(s). There are various configuration elements that can appear, each affects the running of the release building process in specific ways. Note that these must be complete Erlang terms terminated by a ..

App Dirs

App directories specify where relx will search for OTP applications to resolve dependencies.

The app directory configuration element looks as follows:

{lib_dirs, [<list of directory paths>]}.


Paths is a way to add additional code paths (that point to Erlang beam files) to the system. These are not used for dependency resolution, they are only used as code paths. The main use for this is simply to provide a non-resolvable path for additional providers.

The path configuration element looks as follows:

{paths, [<list of directory paths>]}.

So if we wanted to add /usr/local/lib and /opt/lib to the code paths for the system we could add the following:

{paths, ["/usr/local/lib", "/opt/lib"]}.

to our configuration.


Release configuration is the bread and butter, the blood and bones of the Relx system. It provides the framework for realizing dependencies in the system. The release element basically mimics the standard Erlang/OTP Release Metadata file format: There are two main differences. The first is that you don't have to specify a complete list of applications and you may specify version constraints instead of hard versions.

{release, {relname, vsn},
  <app goals>}
{release, {relname, vsn},
 {erts, vsn},
  <app goals>}

See the Overview for goal syntax.

A Note on {relname, vsn}

In the {relname, vsn} tuple, vsn can be a couple of things:

A String

Any string you want. Please be good and use something versiony. SemVer maybe?


This will base the version number off of the most recent git tag that starts with "v"

{semver, Prefix}

Available as of relx 3.3.1.

If you want the 'semver' function, but don't prefix your tags with "v", you can specify a string in the second element of this tuple. This value can be set to "" if you just use straight version numbers as your tags.

{semver, "v"} is the same as semver.

Start Script

Relx generates a start script by default that should work for your release. However, there may be times when you want to provide a custom start script. In those situations you may disable automatic start script creation by adding the following to your relx.config:

{generate_start_script, false}.

Extended start script

To enable the generation of the extended start script you can the following to your relx.config:

{extended_start_script, true}.

This extended start script contains more commands and functionality.

Start script hooks

You can specify a list of hooks to be invoked at various phases of the start script, they are pre/post start/stop, there are some builtin scripts already but you can define your own, the builtin scripts are:

  • pid, {pid, PidFileLocation} - write the Erlang VM pid file to a file of your choosing or, by default, /var/run/<release_name>.pid
  • wait_for_vm_start - waits until the Erlang VM is fully started (ie. responding to pings)
  • {wait_for_process, Name} - waits until a process named Name registers itself
  • {custom, Script} - invokes the provided script

The extended_start_script_hooks element is available for this purpose, an example configuration using all the scripts would be:

              {extended_start_script_hooks, [
                    {pre_start, [
                      {custom, "hooks/pre_start"}
                    {post_start, [
                      {pid, "/tmp/"},
                      {wait_for_process, proc_p1},
                      {custom, "hooks/post_start"}
                    {pre_stop, [
                      {custom, "hooks/pre_stop"}
                    {post_stop, [
                      {custom, "hooks/post_stop"}


These are documented on the Overlays wiki page. Go there for more information.

Advanced Options

The following are options that you would probably not need to use very often. They exist for doing unusual things with the system or adding plugin style functionality.

Alternate Erts

Generally you will want the binary erts that you compiled with. If this is not the case (you are using a cross compiled erlang) then you can point to an alternate erlang build:

 {include_erts, "/path/to/alternate/erlang"}.

Priority Application Loading

In certain cases, you may want to force load certain dependent applications prior to the main bundled apps. These situations arise where they are included as dependencies and available in ebin but not part of the application list in .app file. You can force load the dependent apps by modifying the release element as follows:

{release, {relname, vsn},
  [{dep_app1, load}, ..., app]}


Providers are how the Relx system can be extended by a user. They are basically Erlang modules that implement the rcl_provider behaviour and are available via a code path. See the section on providers for more information.

The providers element provides a completely new list of providers, replacing any providers that may already exist. The provider element is as follows:

 {providers, [<list of module names>]}.

Lets say I have three providers; my_custom_assembler, my_rpm_assembler and my_deb_assembler. I could make these the complete list of providers by doing the following in my config:

{providers, [my_custom_assembler,

Order is important in the providers as they will be executed in the order specified.

Add Providers

add_providers is very similar to providers with the exception that the listed providers are added to the end of the current list of providers rather then replacing the list all together. Add providres looks as follows:

 {add_providers, [<list of module names>]}.

Lets take our previous example but only add my_rpm_assembler and my_deb_assembler to the existing list of providers. We do this by adding the following:

{add_providers, [my_rpm_assembler,

Example Configuration

%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*-
%% Example Relx Config
%% ======================
%% This is an example relx config whose purpose is to demonstrate all of the
%% options available in relx. Its not expected that you will use all of the
%% things here. In fact, there is a high likely hood that *your* relx.config
%% will be extremely minimal, as relx does a very good job of figuring out
%% things on its own.
%% The Release We Are Building
%% ---------------------------
%% Lets say we have a release called sexpr. The sexpr release supports versions
%% 0.0.1 and 0.0.2 with different dependencies. 0.0.1 requires erlware commons
%% 0.8.0 or lesser. 0.0.2 requires erlware_commons 0.8.1 or greater along with
%% neotoma (any version). We also do not want neotoma to be loaded. We also want
%% our default release. the one we build in the common case to be sexper 0.0.2.

%% You can tell relx about additional directories that you want searched for
%% otp apps during the discovery process. You do that in the 'lib_dirs' config. 
%% You can specify these on the command line with `-l`.
{lib_dirs, ["../erlang_app"]}.

%% You can also specify these paths on the command line with `-p`. Be aware that
%% relx plays well with rebar so if you have a deps directory in the current
%% directory it will be automatically added.
{paths, ["/opt/erlang_apps"]}.

%% If you have a sys.config file you need to tell relx where it is. If you do
%% that relx will include the sys.config in the appropriate place
%% automatically.
{sys_config, "./config/sys.config"}.

%% relx will include erts by default. However, if you don't want to include
%% erts you can add the `include_erts` tuple to the config and tell relx not
%% to include it.
%% You can also override the default location erts will be included from by giving
%% a path to an alternate erlang build.
%% {include_erts, "/path/to/alternate/erlang"}.
{include_erts, false}.

%% relx will include src files of your applications, if present, by default.
%% If you don't want to include the src files, set `include_src` to false.
{include_src, false}.

%% When we have multiple releases relx needs to know which one to build. You
%% can specify that on the command line with the `-n` and `-v` arguments to
%% relx. However, it is often more convenient to do it in the config.
{default_release, sexpr, "0.0.2"}.

{release, {sexpr, "0.0.1"},
  %% There are two syntaxes for constraints.
  %% The first is the tuple syntax shown here.
  {erlware_commons, "0.8.0", '<='}]}.

{release, {sexpr, "0.0.2"},

  %% This is the second constraint syntax, it is interchangeable with the tuple
  %% syntax and its up to you which you find more readable/usable.

  %% You can put the release load types in the release spec here in exactly the
  %% same way that you can do it for a normal relfile. The syntax is
  %% {<constraint>, <type>}.
  {neotoma, load}]}.

%% During development its often the case that you want to substitute the app
%% that you are working on for a 'production' version of an app. You can
%% explicitly tell relx to override all versions of an app that you specify
%% with an app in an arbitrary directory. Relx will then symlink that app
%% into the release in place of the specified app. be aware though that relx
%% will check your app for consistancy so it should be a normal OTP app and
%% already be built.
{overrides, [{sexpr, "../sexpr"}]}.

%% In some cases you might want to add additional functionality to relx. You
%% can do this via a 'provider'. A provider is an implementation of the relx
%% provider behaviour. This probably shouldn't be needed very often.
{add_providers, [my_custom_functionality]}.

% Generate an extended start script with some hooks
{extended_start_script, true}.
{extended_start_script_hooks, [
  {pre_start, [
    {custom, "hooks/pre_start"}
  {post_start, [
    {pid, "/tmp/"},
    {wait_for_process, proc_p1},
    {custom, "hooks/post_start"}
  {pre_stop, [
    {custom, "hooks/pre_stop"}
  {post_stop, [
    {custom, "hooks/post_stop"}

Next: Overlays