diff --git a/README.md b/README.md index 568281a8a..c169e11a9 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,9 @@ The following environment variables configure Livebook: * LIVEBOOK_APP_SERVICE_URL - sets the application url to manage this Livebook instance within the cloud provider platform. + * LIVEBOOK_BASE_URL_PATH - sets the base url path the web application is served on. + Useful when deploying behind a reverse proxy. + * LIVEBOOK_COOKIE - sets the cookie for running Livebook in a cluster. Defaults to a random string that is generated on boot. @@ -175,6 +178,10 @@ The following environment variables configure Livebook: "standalone" (Elixir standalone), "attached:NODE:COOKIE" (Attached node) or "embedded" (Embedded). Defaults to "standalone". + * LIVEBOOK_DISTRIBUTION - sets the node distribution for running Livebook in a + cluster. Must be "name" (long names) or "sname" (short names). Note that this + sets RELEASE_DISTRIBUTION if present when creating a release. Defaults to "sname". + * LIVEBOOK_FORCE_SSL_HOST - sets a host to redirect to if the request is not over HTTP. Note it does not apply when accessing Livebook via localhost. Defaults to nil. @@ -192,8 +199,8 @@ The following environment variables configure Livebook: * LIVEBOOK_IP - sets the ip address to start the web application on. Must be a valid IPv4 or IPv6 address. - * LIVEBOOK_BASE_URL_PATH - sets the base url path the web application is served on. - Useful when deploying behind a reverse proxy. + * LIVEBOOK_NODE - sets the node name for running Livebook in a cluster. Note that + this sets RELEASE_NODE if present when creating a release. * LIVEBOOK_PASSWORD - sets a password that must be used to access Livebook. Must be at least 12 characters. Defaults to token authentication. @@ -224,11 +231,6 @@ The following environment variables configure Livebook: -If running Livebook as a Docker image or an Elixir release, [the environment -variables used by Elixir releases are also available]( -https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-environment-variables). -The notables ones are `RELEASE_NODE` and `RELEASE_DISTRIBUTION`. - If running Livebook via the command line, run `livebook server --help` to see all CLI-specific options. diff --git a/lib/livebook.ex b/lib/livebook.ex index d70165a42..d828de6a2 100644 --- a/lib/livebook.ex +++ b/lib/livebook.ex @@ -160,6 +160,10 @@ defmodule Livebook do Livebook.Config.cookie!("RELEASE_COOKIE") || Livebook.Utils.random_cookie() + if node = Livebook.Config.node!("LIVEBOOK_NODE", "LIVEBOOK_DISTRIBUTION") do + config :livebook, :node, node + end + if app_service_name = Livebook.Config.app_service_name!("LIVEBOOK_APP_SERVICE_NAME") do config :livebook, :app_service_name, app_service_name diff --git a/lib/livebook/config.ex b/lib/livebook/config.ex index e6f675534..5d2984510 100644 --- a/lib/livebook/config.ex +++ b/lib/livebook/config.ex @@ -291,6 +291,25 @@ defmodule Livebook.Config do end end + @doc """ + Parses node and distribution type from env. + """ + def node!(node_env, distribution_env) do + case {System.get_env(node_env), System.get_env(distribution_env, "sname")} do + {nil, _} -> + nil + + {name, "name"} -> + {:longnames, String.to_atom(name)} + + {sname, "sname"} -> + {:shortnames, String.to_atom(sname)} + + {_, other} -> + abort!(~s(#{distribution_env} must be one of "name" or "sname", got "#{other}")) + end + end + @doc """ Parses and validates the password from env. """ diff --git a/mix.exs b/mix.exs index 7231aba18..d50068175 100644 --- a/mix.exs +++ b/mix.exs @@ -131,7 +131,7 @@ defmodule Livebook.MixProject do defp releases do [ livebook: [ - include_executables_for: [:unix], + include_executables_for: [:unix, :windows], include_erts: false, rel_templates_path: "rel/server", steps: [:assemble, &remove_cookie/1] diff --git a/rel/server/env.bat.eex b/rel/server/env.bat.eex index 6ccfe937d..3ac238322 100644 --- a/rel/server/env.bat.eex +++ b/rel/server/env.bat.eex @@ -1,4 +1,6 @@ +if defined LIVEBOOK_NODE set RELEASE_NODE="!LIVEBOOK_NODE!" if not defined RELEASE_NODE set RELEASE_NODE=livebook_server +if defined LIVEBOOK_DISTRIBUTION set RELEASE_DISTRIBUTION="!LIVEBOOK_DISTRIBUTION!" set RELEASE_MODE=interactive set cookie_path="!RELEASE_ROOT!\releases\COOKIE" diff --git a/rel/server/env.sh.eex b/rel/server/env.sh.eex index 205f3211e..ba65f747a 100644 --- a/rel/server/env.sh.eex +++ b/rel/server/env.sh.eex @@ -1,4 +1,5 @@ -export RELEASE_NODE="${RELEASE_NODE:-livebook_server}" +export RELEASE_NODE=${LIVEBOOK_NODE:-${RELEASE_NODE:-livebook_server}} +export RELEASE_DISTRIBUTION=${LIVEBOOK_DISTRIBUTION:-${RELEASE_DISTRIBUTION:-sname}} export RELEASE_MODE=interactive cookie_path="${RELEASE_ROOT}/releases/COOKIE" diff --git a/test/livebook/config_test.exs b/test/livebook/config_test.exs new file mode 100644 index 000000000..24c43e51e --- /dev/null +++ b/test/livebook/config_test.exs @@ -0,0 +1,48 @@ +defmodule Livebook.ConfigTest do + use ExUnit.Case, async: true + + alias Livebook.Config + + describe "node!/1" do + test "parses longnames" do + with_env([TEST_LIVEBOOK_NODE: "test@::1", TEST_LIVEBOOK_DISTRIBUTION: "name"], fn -> + assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") == + {:longnames, :"test@::1"} + end) + end + + test "parses shortnames" do + with_env([TEST_LIVEBOOK_NODE: "test", TEST_LIVEBOOK_DISTRIBUTION: "sname"], fn -> + assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") == + {:shortnames, :test} + end) + end + + test "parses shortnames by default" do + with_env([TEST_LIVEBOOK_NODE: "test", TEST_LIVEBOOK_DISTRIBUTION: nil], fn -> + assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") == + {:shortnames, :test} + end) + end + + test "returns nil if node is not set" do + with_env([TEST_LIVEBOOK_NODE: nil, TEST_LIVEBOOK_DISTRIBUTION: "name"], fn -> + assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") == nil + end) + end + end + + defp with_env(env_vars, fun) do + existing = + Enum.map(env_vars, fn {env, _value} -> + {env, env |> to_string() |> System.get_env()} + end) + + try do + System.put_env(env_vars) + fun.() + after + System.put_env(existing) + end + end +end