bitwalker / distillery

Simplify deployments in Elixir with OTP releases!
MIT License
2.96k stars 396 forks source link

COOKIE env var treated differently for foreground and remote_console #660

Closed jesseshieh closed 5 years ago

jesseshieh commented 5 years ago

To reproduce

mix phx.new foo
cd foo
# install distillery 2.0.12 in mix.exs
mix deps.get
mix release.init
# make note of the cookie in your rel/config.exs prod environment
MIX_ENV=prod mix release --env=prod
COOKIE=cmdline-cookie _build/prod/rel/foo/bin/foo foreground

Then in a separate terminal, run

COOKIE=cmdline-cookie _build/prod/rel/foo/bin/foo remote_console

Notice, that the output is

Node foo@127.0.0.1 is not running!

Now launch a remote console without the COOKIE env var, and see it attach successfully

_build/prod/rel/foo/bin/foo remote_console

Notice that the cookie value is from your rel/config.exs, not the COOKIE env var.

iex(foo@127.0.0.1)1> Node.get_cookie
:"xfmJ(2Gq`BHjB$Bn4T48uZwq;1wCi1ue0|Ca(`LU^1Jfni6@*%4rh7v/4}ty{d4f"

This also happens when running the console command directly. For example

COOKIE=cmdline-cookie _build/prod/rel/foo/bin/foo console
iex(foo@127.0.0.1)1> Node.get_cookie
:"xfmJ(2Gq`BHjB$Bn4T48uZwq;1wCi1ue0|Ca(`LU^1Jfni6@*%4rh7v/4}ty{d4f"

I expected the COOKIE env var to override the cookie value in vm.args when running the foreground command as it does when running the remote_console command. I think the issue is that the remote_console command passes the COOKIE as a command line flag here, but the foreground does not. When running the foreground command, the require_cookie and load_cookie commands check and see that the COOKIE var exists, but does not appear to use it.

Distillery: 2.0.12 OS: Ubuntu 16.04 Erlang: 21.0 Elixir: 1.7.4

For example rel/config.exs see example repo https://github.com/jesseshieh/distillery-cookie-issue

As far as documentation, I found only this page mentions the COOKIE env var.

bitwalker commented 5 years ago

I would expect foreground to use whatever is in vm.args, unless vm.args is using env var replacement. The another, larger, problem though is that if you provide -setcookie in vm.args, then try to override it with -setcookie on the command line, what ends up happening is that both cookies are ignored and a cookie is loaded from .erlang.cookie in $HOME. While load_cookie will favor the COOKIE env var, the release tasks which start the release, e.g. foreground, provide the -args_file option for the bundled vm.args, so we have to use what is specified there.

The other reason why these commands behave differently is because remote_console requires a cookie to connect to a remote node, and can connect to any arbitrary node if you tell it to. It will attempt to load one from vm.args if it can, for ease of use, but that's for the primary use case of connecting to the same release you started. On the other hand, foreground is designed entirely around using the config files packaged with the release, and if you want dynamic cookies, then using REPLACE_OS_VARS and ${COOKIE} in vm.args is what is provided in terms of tooling support.

I can see it being desirable to be able to override command-line options for the release start tasks, but I'm not sure there is something we can actually do about this that doesn't have some edge case, short of some really hacky tricks to strip out duplicate/conflicting command line flags in some kind of override hierarchy, which I don't consider an option.

jesseshieh commented 5 years ago

Makes sense! Thanks for the thorough explanation.