about summary refs log tree commit diff
path: root/nixos/modules/services/development
diff options
context:
space:
mode:
authorPhilip Munksgaard <philip@munksgaard.me>2024-01-23 22:36:52 +0100
committerPhilip Munksgaard <philip@munksgaard.me>2024-01-26 20:19:46 +0100
commit897d5670a3da4166ad87b115770ad7d587d7238d (patch)
tree5a980233628518e690aa6261aa0acb0cbac22904 /nixos/modules/services/development
parent6aee40bc7256753c40d10ee7b7e32dd10d89203e (diff)
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.
Diffstat (limited to 'nixos/modules/services/development')
-rw-r--r--nixos/modules/services/development/livebook.md24
-rw-r--r--nixos/modules/services/development/livebook.nix100
2 files changed, 65 insertions, 59 deletions
diff --git a/nixos/modules/services/development/livebook.md b/nixos/modules/services/development/livebook.md
index 5012e977a4f7f..5315f2c2755a0 100644
--- a/nixos/modules/services/development/livebook.md
+++ b/nixos/modules/services/development/livebook.md
@@ -15,11 +15,12 @@ which runs the server.
 {
   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";
   };
 }
 ```
@@ -30,14 +31,19 @@ The Livebook server has the ability to run any command as the user it
 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}
 
 By default, the Livebook service is run with minimum dependencies, but
diff --git a/nixos/modules/services/development/livebook.nix b/nixos/modules/services/development/livebook.nix
index 75729ff28efaf..30ab7ae3f1286 100644
--- a/nixos/modules/services/development/livebook.nix
+++ b/nixos/modules/services/development/livebook.nix
@@ -14,58 +14,64 @@ in
 
     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.'';
-    };
+        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).
 
-    erlang_node_short_name = mkOption {
-      type = with types; nullOr str;
-      default = null;
-      example = "livebook";
-      description = "A short name for the distributed node.";
-    };
+        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.
 
-    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.";
-    };
-
-    port = mkOption {
-      type = types.port;
-      default = 8080;
-      description = "The port to start the web application on.";
-    };
-
-    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 = [ ];
@@ -81,17 +87,11 @@ in
       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" ];
     };