From 84b183dd5190d2ea540147d662d140279b216d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Thu, 13 Jun 2024 18:03:28 +0200 Subject: [PATCH] Defer distribution boot in releases (#2648) --- README.md | 6 ++++-- elixirkit/lib/elixirkit/server.ex | 2 +- lib/livebook.ex | 4 +--- rel/app/env.bat.eex | 20 ++++++++------------ rel/app/env.sh.eex | 23 +++++++++++------------ rel/app/vm.args.eex | 3 ++- rel/server/env.bat.eex | 23 +++++++++-------------- rel/server/env.sh.eex | 31 +++++++++++++++++++------------ 8 files changed, 55 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index ee7f19feb..565cc2312 100644 --- a/README.md +++ b/README.md @@ -256,8 +256,10 @@ The following environment variables can be used to configure Livebook on boot: * `LIVEBOOK_IP` - sets the ip address to start the web application on. Must be a valid IPv4 or IPv6 address. - * `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_NODE` - sets the node name for running Livebook in a cluster. + Note that Livebook always runs using long names distrivution, so the + node host name must use a fully qualified domain name (FQDN) or an IP + address. * `LIVEBOOK_PASSWORD` - sets a password that must be used to access Livebook. Must be at least 12 characters. Defaults to token authentication. diff --git a/elixirkit/lib/elixirkit/server.ex b/elixirkit/lib/elixirkit/server.ex index 56caa9e5c..b1f58e441 100644 --- a/elixirkit/lib/elixirkit/server.ex +++ b/elixirkit/lib/elixirkit/server.ex @@ -10,7 +10,7 @@ defmodule ElixirKit.Server do @impl true def init(pid) do port = System.fetch_env!("ELIXIRKIT_PORT") |> String.to_integer() - {:ok, socket} = :gen_tcp.connect('localhost', port, mode: :binary, packet: 4) + {:ok, socket} = :gen_tcp.connect(~c"localhost", port, mode: :binary, packet: 4) {:ok, %{pid: pid, socket: socket}} end diff --git a/lib/livebook.ex b/lib/livebook.ex index 7052f8c1e..e207340d9 100644 --- a/lib/livebook.ex +++ b/lib/livebook.ex @@ -203,9 +203,7 @@ defmodule Livebook do config :livebook, :cookie, - Livebook.Config.cookie!("LIVEBOOK_COOKIE") || - Livebook.Config.cookie!("RELEASE_COOKIE") || - Livebook.Utils.random_cookie() + Livebook.Config.cookie!("LIVEBOOK_COOKIE") || Livebook.Utils.random_cookie() # TODO: remove in v1.0 if System.get_env("LIVEBOOK_DISTRIBUTION") == "sname" do diff --git a/rel/app/env.bat.eex b/rel/app/env.bat.eex index 439c83a65..1c575f7da 100644 --- a/rel/app/env.bat.eex +++ b/rel/app/env.bat.eex @@ -6,19 +6,13 @@ if not defined LIVEBOOK_EPMDLESS set LIVEBOOK_EPMDLESS=true if "!LIVEBOOK_EPMDLESS!"=="1" goto epmdless if "!LIVEBOOK_EPMDLESS!"=="true" goto epmdless goto continue - :epmdless set ELIXIR_ERL_OPTIONS=!ELIXIR_ERL_OPTIONS! -epmd_module Elixir.Livebook.EPMD -start_epmd false -erl_epmd_port 0 - :continue -for /f "skip=1" %%X in ('wmic os get localdatetime') do if not defined TIMESTAMP set TIMESTAMP=%%X -set RELEASE_DISTRIBUTION="name" +set RELEASE_MODE="interactive" +set RELEASE_DISTRIBUTION="none" -if defined LIVEBOOK_NODE set RELEASE_NODE=!LIVEBOOK_NODE! -if not defined RELEASE_NODE set RELEASE_NODE=livebook-app-!TIMESTAMP:~8,6!-!RANDOM! - -set RELEASE_MODE=interactive set MIX_ARCHIVES=!RELEASE_ROOT!\vendor\archives set MIX_REBAR3=!RELEASE_ROOT!\vendor\rebar3 if not defined LIVEBOOK_SHUTDOWN_ENABLED set LIVEBOOK_SHUTDOWN_ENABLED=true @@ -26,10 +20,12 @@ set LIVEBOOK_DESKTOP=true if not defined LIVEBOOK_PORT (set LIVEBOOK_PORT=0) set PATH=!RELEASE_ROOT!\vendor\otp\erts-<%= @release.erts_version%>\bin;!RELEASE_ROOT!\vendor\otp\bin;!RELEASE_ROOT!\vendor\elixir\bin;!PATH! -set cookie_path=!RELEASE_ROOT!\releases\COOKIE -if not exist %cookie_path% ( - :: '| set /p=""' is so that we don't add ' \r\n' to the cookie - echo | set /p="cookie-!TIMESTAMP:~0,11!-!RANDOM!" > %cookie_path% +if defined LIVEBOOK_NODE set RELEASE_NODE=!LIVEBOOK_NODE! +if defined LIVEBOOK_COOKIE set RELEASE_COOKIE=!LIVEBOOK_COOKIE! + +if not defined RELEASE_COOKIE ( + for /f "skip=1" %%X in ('wmic os get localdatetime') do if not defined TIMESTAMP set TIMESTAMP=%%X + set RELEASE_COOKIE=cookie-!TIMESTAMP:~0,11!-!RANDOM! ) cd !HOMEDRIVE!!HOMEPATH! diff --git a/rel/app/env.sh.eex b/rel/app/env.sh.eex index eaebd1668..51a377f52 100644 --- a/rel/app/env.sh.eex +++ b/rel/app/env.sh.eex @@ -2,25 +2,24 @@ if [ -f "$HOME/.livebookdesktop.sh" ]; then . "$HOME/.livebookdesktop.sh" fi -export RELEASE_DISTRIBUTION="name" -export RELEASE_NODE=${LIVEBOOK_NODE:-${RELEASE_NODE:-"livebook-app-$(cat /dev/urandom | env LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"}} -export RELEASE_MODE=interactive +export LIVEBOOK_EPMDLESS=${LIVEBOOK_EPMDLESS:-true} +if [ "$LIVEBOOK_EPMDLESS" = "true" ] || [ "$LIVEBOOK_EPMDLESS" = "1" ]; then + export ELIXIR_ERL_OPTIONS="${ELIXIR_ERL_OPTIONS} -epmd_module Elixir.Livebook.EPMD -start_epmd false -erl_epmd_port 0" +fi + +export RELEASE_MODE="interactive" +export RELEASE_DISTRIBUTION="none" + export MIX_ARCHIVES="${RELEASE_ROOT}/vendor/archives" export MIX_REBAR3="${RELEASE_ROOT}/vendor/rebar3" -export LIVEBOOK_EPMDLESS=${LIVEBOOK_EPMDLESS:-true} export LIVEBOOK_SHUTDOWN_ENABLED=${LIVEBOOK_SHUTDOWN_ENABLED:-true} export LIVEBOOK_DESKTOP=true [ -z "$LIVEBOOK_PORT" ] && export LIVEBOOK_PORT=0 export PATH="$RELEASE_ROOT/vendor/otp/erts-<%= @release.erts_version%>/bin:$RELEASE_ROOT/vendor/otp/bin:$RELEASE_ROOT/vendor/elixir/bin:$PATH" -if [ "$LIVEBOOK_EPMDLESS" = "true" ] || [ "$LIVEBOOK_EPMDLESS" = "1" ]; then - export ELIXIR_ERL_OPTIONS="${ELIXIR_ERL_OPTIONS} -epmd_module Elixir.Livebook.EPMD -start_epmd false -erl_epmd_port 0" -fi +if [ ! -z "${LIVEBOOK_NODE}" ]; then export RELEASE_NODE=${LIVEBOOK_NODE}; fi +if [ ! -z "${LIVEBOOK_COOKIE}" ]; then export RELEASE_COOKIE=${LIVEBOOK_COOKIE}; fi -cookie_path="${RELEASE_ROOT}/releases/COOKIE" -if [ ! -f $cookie_path ]; then - RELEASE_COOKIE=$(cat /dev/urandom | env LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) - echo "$RELEASE_COOKIE" > "$cookie_path" || export RELEASE_COOKIE -fi +export RELEASE_COOKIE="${RELEASE_COOKIE:-$(cat /dev/urandom | env LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)}" cd $HOME diff --git a/rel/app/vm.args.eex b/rel/app/vm.args.eex index 67880f479..abd39f5ab 100644 --- a/rel/app/vm.args.eex +++ b/rel/app/vm.args.eex @@ -1,2 +1,3 @@ # Disable busy waiting so that we don't waste resources -+sbwt none +sbwtdcpu none +sbwtdio none +# Limit the maximal number of ports for the same reason ++sbwt none +sbwtdcpu none +sbwtdio none +Q 65536 diff --git a/rel/server/env.bat.eex b/rel/server/env.bat.eex index 3def5c56b..f6677c291 100644 --- a/rel/server/env.bat.eex +++ b/rel/server/env.bat.eex @@ -5,22 +5,17 @@ if exist "!RELEASE_ROOT!\user\env.bat" ( if "!LIVEBOOK_EPMDLESS!"=="1" goto epmdless if "!LIVEBOOK_EPMDLESS!"=="true" goto epmdless goto continue - :epmdless set ELIXIR_ERL_OPTIONS=!ELIXIR_ERL_OPTIONS! -epmd_module Elixir.Livebook.EPMD -start_epmd false -erl_epmd_port 0 - :continue -set RELEASE_MODE=interactive -if defined LIVEBOOK_NODE set RELEASE_NODE="!LIVEBOOK_NODE!" -if not defined RELEASE_NODE set RELEASE_NODE=livebook_server -set RELEASE_DISTRIBUTION="name" -if defined LIVEBOOK_COOKIE set RELEASE_COOKIE="!LIVEBOOK_COOKIE!" -set cookie_path="!RELEASE_ROOT!\releases\COOKIE" -if not exist %cookie_path% ( - if not defined RELEASE_COOKIE ( - for /f "skip=1" %%X in ('wmic os get localdatetime') do if not defined TIMESTAMP set TIMESTAMP=%%X - :: '| set /p=""' is so that we don't add ' \r\n' to the cookie - echo | set /p="cookie-!TIMESTAMP:~0,11!-!RANDOM!" > %cookie_path% - ) +set RELEASE_MODE="interactive" +set RELEASE_DISTRIBUTION="none" + +if defined LIVEBOOK_NODE set RELEASE_NODE=!LIVEBOOK_NODE! +if defined LIVEBOOK_COOKIE set RELEASE_COOKIE=!LIVEBOOK_COOKIE! + +if not defined RELEASE_COOKIE ( + for /f "skip=1" %%X in ('wmic os get localdatetime') do if not defined TIMESTAMP set TIMESTAMP=%%X + set RELEASE_COOKIE=cookie-!TIMESTAMP:~0,11!-!RANDOM! ) diff --git a/rel/server/env.sh.eex b/rel/server/env.sh.eex index 6cc564e6e..7b2a03d08 100644 --- a/rel/server/env.sh.eex +++ b/rel/server/env.sh.eex @@ -1,26 +1,33 @@ -NODE_DEFAULT="livebook_server" - if [ "$LIVEBOOK_CLUSTER" = "fly" ]; then export ERL_AFLAGS="-proto_dist inet6_tcp" export LIVEBOOK_CLUSTER="dns:${FLY_APP_NAME}.internal" - NODE_DEFAULT="${FLY_APP_NAME}-${FLY_IMAGE_REF##*-}@${FLY_PRIVATE_IP}" + if [ ! -z "${LIVEBOOK_NODE}" ]; + then export LIVEBOOK_NODE="${FLY_APP_NAME}-${FLY_IMAGE_REF##*-}@${FLY_PRIVATE_IP}"; + fi fi if [ -f "${RELEASE_ROOT}/user/env.sh" ]; then . "${RELEASE_ROOT}/user/env.sh" fi -export RELEASE_MODE=interactive -export RELEASE_NODE=${LIVEBOOK_NODE:-${RELEASE_NODE:-${NODE_DEFAULT}}} -export RELEASE_DISTRIBUTION="name" - if [ "$LIVEBOOK_EPMDLESS" = "true" ] || [ "$LIVEBOOK_EPMDLESS" = "1" ]; then export ELIXIR_ERL_OPTIONS="${ELIXIR_ERL_OPTIONS} -epmd_module Elixir.Livebook.EPMD -start_epmd false -erl_epmd_port 0" fi +export RELEASE_MODE="interactive" +export RELEASE_DISTRIBUTION="none" + +# Mirror these values, so that it is easier to use "bin/release rpc", +# though it still requires setting RELEASE_DISTRIBUTION=name +if [ ! -z "${LIVEBOOK_NODE}" ]; then export RELEASE_NODE=${LIVEBOOK_NODE}; fi if [ ! -z "${LIVEBOOK_COOKIE}" ]; then export RELEASE_COOKIE=${LIVEBOOK_COOKIE}; fi -cookie_path="${RELEASE_ROOT}/releases/COOKIE" -if [ ! -f $cookie_path ] && [ -z "$RELEASE_COOKIE" ]; then - RELEASE_COOKIE=$(cat /dev/urandom | env LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) - echo "$RELEASE_COOKIE" > "$cookie_path" || export RELEASE_COOKIE -fi + +# We remove the COOKIE file when assembling the release, because we +# don't want to share the same cookie across users. The Elixir release +# script attempts to read from that file, which would fail, therefore +# we need to set it here. Also there is a very tiny time gap between we +# start distribution and set the cookie during application boot, so we +# specifically want the temporary node cookie to be random, rather than +# a fixed value. Note that this value is overriden on boot, so other +# than being the initial node cookie, we don't really use it. +export RELEASE_COOKIE="${RELEASE_COOKIE:-$(cat /dev/urandom | env LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)}"