livebook: add systemd user service, test, and docs
Co-authored-by: Yt <happysalada@tuta.io>
This commit is contained in:
parent
0fa36ea34f
commit
fa54eeea5c
7 changed files with 181 additions and 1 deletions
|
@ -72,6 +72,8 @@
|
|||
|
||||
- [LibreNMS](https://www.librenms.org), a auto-discovering PHP/MySQL/SNMP based network monitoring. Available as [services.librenms](#opt-services.librenms.enable).
|
||||
|
||||
- [Livebook](https://livebook.dev/), an interactive notebook with support for Elixir, graphs, machine learning, and more.
|
||||
|
||||
- [sitespeed-io](https://sitespeed.io), a tool that can generate metrics (timings, diagnostics) for websites. Available as [services.sitespeed-io](#opt-services.sitespeed-io.enable).
|
||||
|
||||
- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP, JMAP). Available as [services.stalwart-mail](#opt-services.stalwart-mail.enable).
|
||||
|
|
|
@ -485,6 +485,7 @@
|
|||
./services/development/hoogle.nix
|
||||
./services/development/jupyter/default.nix
|
||||
./services/development/jupyterhub/default.nix
|
||||
./services/development/livebook.nix
|
||||
./services/development/lorri.nix
|
||||
./services/development/rstudio-server/default.nix
|
||||
./services/development/zammad.nix
|
||||
|
|
39
nixos/modules/services/development/livebook.md
Normal file
39
nixos/modules/services/development/livebook.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Livebook {#module-services-livebook}
|
||||
|
||||
[Livebook](https://livebook.dev/) is a web application for writing
|
||||
interactive and collaborative code notebooks.
|
||||
|
||||
## Basic Usage {#module-services-livebook-basic-usage}
|
||||
|
||||
Enabling the `livebook` service creates a user
|
||||
[`systemd`](https://www.freedesktop.org/wiki/Software/systemd/) unit
|
||||
which runs the server.
|
||||
|
||||
```
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
services.livebook = {
|
||||
enableUserService = true;
|
||||
port = 20123;
|
||||
# See note below about security
|
||||
environmentFile = pkgs.writeText "livebook.env" ''
|
||||
LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
'';
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
|
||||
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`.
|
||||
|
||||
:::
|
90
nixos/modules/services/development/livebook.nix
Normal file
90
nixos/modules/services/development/livebook.nix
Normal file
|
@ -0,0 +1,90 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.livebook;
|
||||
in
|
||||
{
|
||||
options.services.livebook = {
|
||||
# Since livebook doesn't have a granular permission system (a user
|
||||
# either has access to all the data or none at all), the decision
|
||||
# was made to run this as a user service. If that changes in the
|
||||
# future, this can be changed to a system service.
|
||||
enableUserService = mkEnableOption "a user service for Livebook";
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
Environment file as defined in {manpage}`systemd.exec(5)` passed to the service.
|
||||
|
||||
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.";
|
||||
};
|
||||
|
||||
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.
|
||||
'';
|
||||
};
|
||||
|
||||
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";
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enableUserService {
|
||||
systemd.user.services.livebook = {
|
||||
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
|
||||
"${pkgs.livebook}/bin/livebook server ${args}";
|
||||
};
|
||||
path = [ pkgs.bash ];
|
||||
wantedBy = [ "default.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
meta.doc = ./livebook.md;
|
||||
}
|
|
@ -371,6 +371,7 @@ in {
|
|||
honk = runTest ./honk.nix;
|
||||
installed-tests = pkgs.recurseIntoAttrs (handleTest ./installed-tests {});
|
||||
invidious = handleTest ./invidious.nix {};
|
||||
livebook-service = handleTest ./livebook-service.nix {};
|
||||
oci-containers = handleTestOn ["aarch64-linux" "x86_64-linux"] ./oci-containers.nix {};
|
||||
odoo = handleTest ./odoo.nix {};
|
||||
odoo15 = handleTest ./odoo.nix { package = pkgs.odoo15; };
|
||||
|
|
43
nixos/tests/livebook-service.nix
Normal file
43
nixos/tests/livebook-service.nix
Normal file
|
@ -0,0 +1,43 @@
|
|||
import ./make-test-python.nix ({ lib, pkgs, ... }: {
|
||||
name = "livebook-service";
|
||||
|
||||
nodes = {
|
||||
machine = { config, pkgs, ... }: {
|
||||
imports = [
|
||||
./common/user-account.nix
|
||||
];
|
||||
|
||||
services.livebook = {
|
||||
enableUserService = true;
|
||||
port = 20123;
|
||||
environmentFile = pkgs.writeText "livebook.env" ''
|
||||
LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
'';
|
||||
options = {
|
||||
cookie = "chocolate chip";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }:
|
||||
let
|
||||
user = nodes.machine.config.users.users.alice;
|
||||
sudo = lib.concatStringsSep " " [
|
||||
"XDG_RUNTIME_DIR=/run/user/${toString user.uid}"
|
||||
"sudo"
|
||||
"--preserve-env=XDG_RUNTIME_DIR"
|
||||
"-u"
|
||||
"alice"
|
||||
];
|
||||
in
|
||||
''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("loginctl enable-linger alice")
|
||||
machine.wait_until_succeeds("${sudo} systemctl --user is-active livebook.service")
|
||||
machine.wait_for_open_port(20123)
|
||||
|
||||
machine.succeed("curl -L localhost:20123 | grep 'Type password'")
|
||||
'';
|
||||
})
|
|
@ -1,4 +1,4 @@
|
|||
{ lib, beamPackages, makeWrapper, rebar3, elixir, erlang, fetchFromGitHub }:
|
||||
{ lib, beamPackages, makeWrapper, rebar3, elixir, erlang, fetchFromGitHub, nixosTests }:
|
||||
beamPackages.mixRelease rec {
|
||||
pname = "livebook";
|
||||
version = "0.11.3";
|
||||
|
@ -32,6 +32,10 @@ beamPackages.mixRelease rec {
|
|||
--set MIX_REBAR3 ${rebar3}/bin/rebar3
|
||||
'';
|
||||
|
||||
passthru.tests = {
|
||||
livebook-service = nixosTests.livebook-service;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
license = licenses.asl20;
|
||||
homepage = "https://livebook.dev/";
|
||||
|
|
Loading…
Reference in a new issue