Include default secret key base and cookie in apps Dockerfile (#2294)

This commit is contained in:
Jonatan Kłosko 2023-10-24 14:41:49 +02:00 committed by GitHub
parent 3d6a808421
commit b603639b77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 56 additions and 16 deletions

View file

@ -340,7 +340,7 @@ When clustering is enabled, you must additionally set the following env vars:
* `LIVEBOOK_NODE=livebook_server@IP`, where `IP` is the machine IP of each
deployed node
* You must set `LIVEBOOK_SECRET_KEY_BASE` and `RELEASE_COOKIE` to
* You must set `LIVEBOOK_SECRET_KEY_BASE` and `LIVEBOOK_COOKIE` to
different random values (use `openssl rand -base64 48` to generate
said values)

View file

@ -89,7 +89,7 @@ defmodule Livebook do
config :livebook, LivebookWeb.Endpoint,
secret_key_base:
Livebook.Config.secret!("LIVEBOOK_SECRET_KEY_BASE") ||
Base.encode64(:crypto.strong_rand_bytes(48))
Livebook.Utils.random_secret_key_base()
if Livebook.Config.debug!("LIVEBOOK_DEBUG") do
config :logger, level: :debug

View file

@ -116,20 +116,31 @@ defmodule Livebook.Hubs.Dockerfile do
RUN /app/bin/warmup_apps.sh
"""
random_secret_key_base = Livebook.Utils.random_secret_key_base()
random_cookie = Livebook.Utils.random_cookie()
startup =
if config.clustering == :fly_io do
~S"""
# Custom startup script to cluster multiple Livebook nodes on Fly.io
RUN printf '\
#!/bin/bash\n\
export ERL_AFLAGS="-proto_dist inet6_tcp"\n\
export LIVEBOOK_NODE="${FLY_APP_NAME}-${FLY_IMAGE_REF##*-}@${FLY_PRIVATE_IP}"\n\
export LIVEBOOK_CLUSTER="dns:${FLY_APP_NAME}.internal"\n\
/app/bin/livebook start\n\
' > /app/bin/start.sh && chmod +x /app/bin/start.sh
CMD [ "/app/bin/start.sh" ]
"""
# --- Clustering ---
# Set the same Livebook secrets across all nodes
ENV LIVEBOOK_SECRET_KEY_BASE "#{random_secret_key_base}"
ENV LIVEBOOK_COOKIE "#{random_cookie}"
""" <>
~S"""
# Custom startup script to cluster multiple Livebook nodes on Fly.io
RUN printf '\
#!/bin/bash\n\
export ERL_AFLAGS="-proto_dist inet6_tcp"\n\
export LIVEBOOK_NODE="${FLY_APP_NAME}-${FLY_IMAGE_REF##*-}@${FLY_PRIVATE_IP}"\n\
export LIVEBOOK_CLUSTER="dns:${FLY_APP_NAME}.internal"\n\
/app/bin/livebook start\n\
' > /app/bin/start.sh && chmod +x /app/bin/start.sh
CMD [ "sh", "-c", "/app/bin/start.sh" ]
"""
end
[

View file

@ -27,6 +27,14 @@ defmodule Livebook.Utils do
:"c_#{Base.url_encode64(:crypto.strong_rand_bytes(39))}"
end
@doc """
Generates a random value for Phoenix secret key base.
"""
@spec random_secret_key_base() :: String.t()
def random_secret_key_base() do
Base.encode64(:crypto.strong_rand_bytes(48))
end
@doc """
Generates a random binary id that includes node information.

View file

@ -178,6 +178,7 @@ defmodule LivebookWeb.AppHelpers do
"""
attr :hub, :map, required: true
attr :dockerfile, :string, required: true
attr :dockerfile_config, :map, required: true
slot :dockerfile_actions, default: nil
@ -235,6 +236,16 @@ defmodule LivebookWeb.AppHelpers do
platform
</span>
</li>
<li :if={@dockerfile_config.clustering} class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
you may set <code>LIVEBOOK_SECRET_KEY_BASE</code>
and <code>LIVEBOOK_COOKIE</code>
as runtime environment secrets in your deployment platform, to ensure their
values stay the same across deployments. If you do that, you can remove
the defaults from your Dockerfile
</span>
</li>
<li class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>

View file

@ -220,7 +220,11 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
/>
</.form>
<LivebookWeb.AppHelpers.docker_instructions hub={@hub} dockerfile={@dockerfile} />
<LivebookWeb.AppHelpers.docker_instructions
hub={@hub}
dockerfile={@dockerfile}
dockerfile_config={Ecto.Changeset.apply_changes(@config_changeset)}
/>
</div>
<div class="flex flex-col space-y-4">

View file

@ -96,7 +96,11 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
<AppHelpers.docker_config_form_content hub={@hub} form={f} />
</.form>
<.save_result :if={@save_result} save_result={@save_result} />
<AppHelpers.docker_instructions hub={@hub} dockerfile={@dockerfile}>
<AppHelpers.docker_instructions
hub={@hub}
dockerfile={@dockerfile}
dockerfile_config={apply_changes(@changeset)}
>
<:dockerfile_actions>
<button
class="button-base button-gray whitespace-nowrap py-1 px-2"

View file

@ -4,6 +4,7 @@ if not defined RELEASE_NODE set RELEASE_NODE=livebook_server
if defined LIVEBOOK_DISTRIBUTION set RELEASE_DISTRIBUTION="!LIVEBOOK_DISTRIBUTION!"
if not defined RELEASE_DISTRIBUTION (if defined LIVEBOOK_CLUSTER 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 (

View file

@ -1,8 +1,9 @@
export RELEASE_MODE=interactive
export RELEASE_NODE=${LIVEBOOK_NODE:-${RELEASE_NODE:-livebook_server}}
if [[ -z "${LIVEBOOK_CLUSTER}" ]]; then DISTRIBUTION_DEFAULT="sname"; else DISTRIBUTION_DEFAULT="name"; fi
if [ -z "${LIVEBOOK_CLUSTER}" ]; then DISTRIBUTION_DEFAULT="sname"; else DISTRIBUTION_DEFAULT="name"; fi
export RELEASE_DISTRIBUTION=${LIVEBOOK_DISTRIBUTION:-${RELEASE_DISTRIBUTION:-${DISTRIBUTION_DEFAULT}}}
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)