diff --git a/README.md b/README.md index fe80d53ee..8972e5cee 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ The following environment variables configure Livebook: * LIVEBOOK_SECRET_KEY_BASE - sets a secret key that is used to sign and encrypt the session and other payloads used by Livebook. Must be at least 64 characters long and it can be generated by commands such as: `openssl rand -base64 48`. Defaults to a random secret on every boot. + * LIVEBOOK_ROOT_PATH - the root path to use for file selection. + ## License diff --git a/config/runtime.exs b/config/runtime.exs index 1c5701ca9..1ac6d9586 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -6,6 +6,8 @@ config :livebook, LivebookWeb.Endpoint, Livebook.Config.secret!("LIVEBOOK_SECRET_KEY_BASE") || Base.encode64(:crypto.strong_rand_bytes(48)) +config :livebook, :root_path, Livebook.Config.root_path!("LIVEBOOK_ROOT_PATH") + if password = Livebook.Config.password!("LIVEBOOK_PASSWORD") do config :livebook, authentication_mode: :password, password: password else diff --git a/lib/livebook/config.ex b/lib/livebook/config.ex index 16e393949..40dc40e36 100644 --- a/lib/livebook/config.ex +++ b/lib/livebook/config.ex @@ -28,13 +28,36 @@ defmodule Livebook.Config do """ @spec root_path() :: binary() def root_path() do - Application.get_env(:livebook, :root_path, File.cwd!()) + Application.fetch_env!(:livebook, :root_path) end ## Parsing @doc """ - Parses a long secret. + Parses and validates the root path from env. + """ + def root_path!(env) do + if root_path = System.get_env(env) do + root_path!("LIVEBOOK_ROOT_PATH", root_path) + else + File.cwd!() + end + end + + @doc """ + Validates `root_path` within context. + """ + def root_path!(context, root_path) do + if File.dir?(root_path) do + root_path + else + IO.warn("ignoring #{context} because it doesn't point to a directory: #{root_path}") + File.get_cwd!() + end + end + + @doc """ + Parses and validates the secret from env. """ def secret!(env) do if secret_key_base = System.get_env(env) do @@ -50,7 +73,7 @@ defmodule Livebook.Config do end @doc """ - Parses a port. + Parses and validates the port from env. """ def port!(env) do if port = System.get_env(env) do @@ -62,7 +85,7 @@ defmodule Livebook.Config do end @doc """ - Parses a password. + Parses and validates the password from env. """ def password!(env) do if password = System.get_env(env) do diff --git a/lib/livebook_cli/server.ex b/lib/livebook_cli/server.ex index 437c4f7e0..13906c505 100644 --- a/lib/livebook_cli/server.ex +++ b/lib/livebook_cli/server.ex @@ -24,6 +24,7 @@ defmodule LivebookCLI.Server do If LIVEBOOK_PASSWORD is set, it takes precedence over token auth --sname Set a short name for the app distributed node -p, --port The port to start the web application on, defaults to 8080 + --root-path The root path to use for file selection The --help option can be given to print this notice. @@ -69,14 +70,20 @@ defmodule LivebookCLI.Server do end end - defp args_to_config(args) do - {opts, _} = - OptionParser.parse!( - args, - strict: [token: :boolean, port: :integer, name: :string, sname: :string], - aliases: [p: :port] - ) + @switches [ + token: :boolean, + port: :integer, + name: :string, + sname: :string, + root_path: :string + ] + @aliases [ + p: :port + ] + + defp args_to_config(args) do + {opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases) validate_options!(opts) opts_to_config(opts, []) end @@ -101,6 +108,11 @@ defmodule LivebookCLI.Server do opts_to_config(opts, [{:livebook, LivebookWeb.Endpoint, http: [port: port]} | config]) end + defp opts_to_config([{:root_path, root_path} | opts], config) do + root_path = Livebook.Config.root_path!("--root-path", root_path) + opts_to_config(opts, [{:livebook, :root_path, root_path} | config]) + end + defp opts_to_config([{:sname, sname} | opts], config) do sname = String.to_atom(sname) opts_to_config(opts, [{:livebook, :node, {:shortnames, sname}} | config])