Use per host configuration

Ole J. Rosendahl edited this page May 30, 2017 · 7 revisions

Use different configurations on different deploy hosts.

To use different configurations on different production / staging hosts, you can either:

  • link the sys.config by setting the env LINK_SYS_CONFIG=/path/to/sys.config in the .deliver/config
  • or even more flexible by linking the vm.args by setting the env LINK_VM_ARGS=/path/to/vm.argsin the .deliver/config

Linking the sys.config should be sufficient for the most needs. Linking vm.args is more flexible because you can also set arguments for the beam process and even load additional configs.

The sys.config and vm.args files are placed as link into the release / upgrade tar.gz and can be found in the deployed release at $DELIVER_TO/$APP/releases/$VERSION/sys.config or $DELIVER_TO/$APP/releases/$VERSION/vm.args. The sys.config file is usually generated during compile time from the $APP/config/config.exs merged with the $APP/config/production.exs and is replaced by the link. The generated sys.config can be used as template for the custom configs used as link destination on each host. Same with the vm.args which is generated with default arguments.

example with linked sys config:

  # .deliver/config
  APP=my_app
  LINK_SYS_CONFIG=/etc/my_app.config

build the release with mix edeliver build release and

install the different configs on the different hosts:

  # /etc/my_app.config on production host 1
  # configuration must be erlang terms, see:
  # http://www.erlang.org/doc/man/config.html
  [{my_app, [
    {'Elixir.MyApp.Repo',
      [{adapter,'Elixir.Ecto.Adapters.Postgres'},
       {database,<<"my_database">>},
       {username,<<"master_user">>},
       {hostname,<<"master.server">>}]
    }]
   }].
  # /etc/my_app.config on production host 2
  [{my_app, [
    {'Elixir.MyApp.Repo',
      [{adapter,'Elixir.Ecto.Adapters.Postgres'},
       {database,<<"my_database">>},
       {username,<<"slave_user">>},
       {hostname,<<"slave.server">>}]
    }]
   }].
  # /etc/my_app.config on staging host
  [{my_app, [
    {'Elixir.MyApp.Repo',
      [{adapter,'Elixir.Ecto.Adapters.Postgres'},
       {database,<<"test_database">>},
       {username,<<"test_user">>},
       {hostname,<<"test.server">>}]
    }]
   }].

and deploy the release.

example with linked vm args:

  # .deliver/config
  APP=my_app
  LINK_VM_ARGS=/etc/my_app/vm.args

build the release with mix edeliver build release and

install the different configs on the different hosts:

## /etc/my_app/vm.args
## using short names instead of long node names
-sname myapp

## set more secret cookie
-setcookie secret_cookie****************

## enable kernel poll
+K true

## increase number of concurrent ports/sockets
-env ERL_MAX_PORTS 4096

## tweak gc to run more often
-env ERL_FULLSWEEP_AFTER 1

## add additional configs
-config /etc/my_app/logging.config
-config /etc/my_app/database.config
  # /etc/my_app/logging.config on production host 1
  # configuration must be erlang terms, see:
  # http://www.erlang.org/doc/man/config.html
  [{logger,
     [{console, [{level,error}]},
      {truncate, 1073741824}]
  }].
  # /etc/my_app/logging.config on staging 1
  [{logger,
     [{console, [{level,debug}]},
      {truncate, 1048576}]
   }].
  # /etc/my_app/database.config on production host 1
  [{my_app, [
    {'Elixir.MyApp.Repo',
      [{adapter,'Elixir.Ecto.Adapters.Postgres'},
       {database,<<"my_database">>},
       {username,<<"master_user">>},
       {hostname,<<"master.server">>}]
    }]
   }].
  # /etc/my_app/database.config on staging host
  [{my_app, [
    {'Elixir.MyApp.Repo',
      [{adapter,'Elixir.Ecto.Adapters.Postgres'},
       {database,<<"test_database">>},
       {username,<<"test_user">>},
       {hostname,<<"test.server">>}]
    }]
   }].

linking with distillery

In order to link either sys.config or vm.args while using the distillery release generator, you must add the LinkConfig plugin to the rel/config.exs distillery config:

environment :prod do
  ..
  plugin Releases.Plugin.LinkConfig
end

caveats

  • You can't embed updated configs into your release. You must set the new config in the relup instructions file in addition to updating the configs on the host
  • Additional configs added to a linked vm.args are lost after a hot code upgrade. These configs must be reloaded after a hot code upgrade