livebook: Use `mix release` to build instead of escript

The current build of livebook does not work with the new [Livebook
Teams](https://livebook.dev/teams/) features. The problem can be observed by
running the current version of livebook, adding a new team and going to the team
page. The process will crash and the team page will show a 500 error.

The base of the problem is that the escript build method is not officially
supported. This commit changes the livebook package to use the `mix release`
workflow, which is also the one used to build the official Docker container.

Unfortunately, the binary built with `mix release` does not support command line
arguments like the `escript` binary does. Instead, users need to pass in most of
the configuration as environment variables, as documented
[here](https://hexdocs.pm/livebook/readme.html#environment-variables). As a
result, this commit also changes the Livebook service to reflect this new way of
configuring Livebook.

Finally, the Livebook release configuration specifically excludes the
ERTS (Erlang Runtime System), which means that the resulting release cannot run
without Erlang installed.

I have tested the results (both of the package and the service) locally.

Changed files
+81 -70
nixos
doc
manual
release-notes
modules
services
tests
pkgs
servers
web-apps
livebook
+7
nixos/doc/manual/release-notes/rl-2405.section.md
···
- `nomad_1_4` has been removed, as it is now unsupported upstream.
+
- The `livebook` package is now built as a `mix release` instead of an `escript`.
+
This means that configuration now has to be done using [environment variables](https://hexdocs.pm/livebook/readme.html#environment-variables) instead of command line arguments.
+
This has the further implication that the `livebook` service configuration has changed:
+
+
- The `erlang_node_short_name`, `erlang_node_name`, `port` and `options` configuration parameters are gone, and have been replaced with an `environment` parameter.
+
Use the appropriate [environment variables](https://hexdocs.pm/livebook/readme.html#environment-variables) inside `environment` to configure the service instead.
+
## Other Notable Changes {#sec-release-24.05-notable-changes}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+15 -9
nixos/modules/services/development/livebook.md
···
{
services.livebook = {
enableUserService = true;
-
port = 20123;
+
environment = {
+
LIVEBOOK_PORT = 20123;
+
LIVEBOOK_PASSWORD = "mypassword";
+
};
# See note below about security
-
environmentFile = pkgs.writeText "livebook.env" ''
-
LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-
'';
+
environmentFile = "/var/lib/livebook.env";
};
}
```
···
is running under, so securing access to it with a password is highly
recommended.
-
Putting the password in the Nix configuration like above is an easy
-
way to get started but it is not recommended in the real world because
-
the `livebook.env` file will be added to the world-readable Nix store.
-
A better approach would be to put the password in some secure
-
user-readable location and set `environmentFile = /home/user/secure/livebook.env`.
+
Putting the password in the Nix configuration like above is an easy way to get
+
started but it is not recommended in the real world because the resulting
+
environment variables can be read by unprivileged users. A better approach
+
would be to put the password in some secure user-readable location and set
+
`environmentFile = /home/user/secure/livebook.env`.
:::
+
+
The [Livebook
+
documentation](https://hexdocs.pm/livebook/readme.html#environment-variables)
+
lists all the applicable environment variables. It is recommended to at least
+
set `LIVEBOOK_PASSWORD` or `LIVEBOOK_TOKEN_ENABLED=false`.
### Extra dependencies {#module-services-livebook-extra-dependencies}
+50 -50
nixos/modules/services/development/livebook.nix
···
package = mkPackageOption pkgs "livebook" { };
-
environmentFile = mkOption {
-
type = types.path;
+
environment = mkOption {
+
type = with types; attrsOf (nullOr (oneOf [ bool int str ]));
+
default = { };
description = lib.mdDoc ''
-
Environment file as defined in {manpage}`systemd.exec(5)` passed to the service.
+
Environment variables to set.
-
This must contain at least `LIVEBOOK_PASSWORD` or
-
`LIVEBOOK_TOKEN_ENABLED=false`. See `livebook server --help`
-
for other options.'';
-
};
-
-
erlang_node_short_name = mkOption {
-
type = with types; nullOr str;
-
default = null;
-
example = "livebook";
-
description = "A short name for the distributed node.";
-
};
-
-
erlang_node_name = mkOption {
-
type = with types; nullOr str;
-
default = null;
-
example = "livebook@127.0.0.1";
-
description = "The name for the app distributed node.";
-
};
+
Livebook is configured through the use of environment variables. The
+
available configuration options can be found in the [Livebook
+
documentation](https://hexdocs.pm/livebook/readme.html#environment-variables).
-
port = mkOption {
-
type = types.port;
-
default = 8080;
-
description = "The port to start the web application on.";
-
};
+
Note that all environment variables set through this configuration
+
parameter will be readable by anyone with access to the host
+
machine. Therefore, sensitive information like {env}`LIVEBOOK_PASSWORD`
+
or {env}`LIVEBOOK_COOKIE` should never be set using this configuration
+
option, but should instead use
+
[](#opt-services.livebook.environmentFile). See the documentation for
+
that option for more information.
-
address = mkOption {
-
type = types.str;
-
default = "127.0.0.1";
-
description = lib.mdDoc ''
-
The address to start the web application on. Must be a valid IPv4 or
-
IPv6 address.
+
Any environment variables specified in the
+
[](#opt-services.livebook.environmentFile) will supersede environment
+
variables specified in this option.
'';
-
};
-
options = mkOption {
-
type = with types; attrsOf str;
-
default = { };
-
description = lib.mdDoc ''
-
Additional options to pass as command-line arguments to the server.
-
'';
example = literalExpression ''
{
-
cookie = "a value shared by all nodes in this cluster";
+
LIVEBOOK_PORT = 8080;
}
'';
};
+
environmentFile = mkOption {
+
type = with types; nullOr types.path;
+
default = null;
+
description = lib.mdDoc ''
+
Additional dnvironment file as defined in {manpage}`systemd.exec(5)`.
+
+
Secrets like {env}`LIVEBOOK_PASSWORD` (which is used to specify the
+
password needed to access the livebook site) or {env}`LIVEBOOK_COOKIE`
+
(which is used to specify the
+
[cookie](https://www.erlang.org/doc/reference_manual/distributed.html#security)
+
used to connect to the running Elixir system) may be passed to the
+
service without making them readable to everyone with access to
+
systemctl by using this configuration parameter.
+
+
Note that this file needs to be available on the host on which
+
`livebook` is running.
+
+
For security purposes, this file should contain at least
+
{env}`LIVEBOOK_PASSWORD` or {env}`LIVEBOOK_TOKEN_ENABLED=false`.
+
+
See the [Livebook
+
documentation](https://hexdocs.pm/livebook/readme.html#environment-variables)
+
and the [](#opt-services.livebook.environment) configuration parameter
+
for further options.
+
'';
+
example = "/var/lib/livebook.env";
+
};
+
extraPackages = mkOption {
type = with types; listOf package;
default = [ ];
···
serviceConfig = {
Restart = "always";
EnvironmentFile = cfg.environmentFile;
-
ExecStart =
-
let
-
args = lib.cli.toGNUCommandLineShell { } ({
-
inherit (cfg) port;
-
ip = cfg.address;
-
name = cfg.erlang_node_name;
-
sname = cfg.erlang_node_short_name;
-
} // cfg.options);
-
in
-
"${cfg.package}/bin/livebook server ${args}";
+
ExecStart = "${cfg.package}/bin/livebook start";
};
+
environment = mapAttrs (name: value:
+
if isBool value then boolToString value else toString value)
+
cfg.environment;
path = [ pkgs.bash ] ++ cfg.extraPackages;
wantedBy = [ "default.target" ];
};
+6 -4
nixos/tests/livebook-service.nix
···
services.livebook = {
enableUserService = true;
-
port = 20123;
+
environment = {
+
LIVEBOOK_PORT = 20123;
+
LIVEBOOK_COOKIE = "chocolate chip";
+
LIVEBOOK_TOKEN_ENABLED = true;
+
+
};
environmentFile = pkgs.writeText "livebook.env" ''
LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
'';
-
options = {
-
cookie = "chocolate chip";
-
};
};
};
};
+3 -7
pkgs/servers/web-apps/livebook/default.nix
···
hash = "sha256-dyKhrbb7vazBV6LFERtGHLQXEx29vTgn074mY4fsHy4=";
};
-
installPhase = ''
-
mix escript.build
-
mkdir -p $out/bin
-
mv ./livebook $out/bin
-
+
postInstall = ''
wrapProgram $out/bin/livebook \
-
--prefix PATH : ${lib.makeBinPath [ elixir ]} \
+
--prefix PATH : ${lib.makeBinPath [ elixir erlang ]} \
--set MIX_REBAR3 ${rebar3}/bin/rebar3
-
'';
+
'';
passthru.tests = {
livebook-service = nixosTests.livebook-service;