···72727373- [LibreNMS](https://www.librenms.org), a auto-discovering PHP/MySQL/SNMP based network monitoring. Available as [services.librenms](#opt-services.librenms.enable).
74747575+- [Livebook](https://livebook.dev/), an interactive notebook with support for Elixir, graphs, machine learning, and more.
7676+7577- [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).
76787779- [stalwart-mail](https://stalw.art), an all-in-one email server (SMTP, IMAP, JMAP). Available as [services.stalwart-mail](#opt-services.stalwart-mail.enable).
···11+# Livebook {#module-services-livebook}
22+33+[Livebook](https://livebook.dev/) is a web application for writing
44+interactive and collaborative code notebooks.
55+66+## Basic Usage {#module-services-livebook-basic-usage}
77+88+Enabling the `livebook` service creates a user
99+[`systemd`](https://www.freedesktop.org/wiki/Software/systemd/) unit
1010+which runs the server.
1111+1212+```
1313+{ ... }:
1414+1515+{
1616+ services.livebook = {
1717+ enableUserService = true;
1818+ port = 20123;
1919+ # See note below about security
2020+ environmentFile = pkgs.writeText "livebook.env" ''
2121+ LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
2222+ '';
2323+ };
2424+}
2525+```
2626+2727+::: {.note}
2828+2929+The Livebook server has the ability to run any command as the user it
3030+is running under, so securing access to it with a password is highly
3131+recommended.
3232+3333+Putting the password in the Nix configuration like above is an easy
3434+way to get started but it is not recommended in the real world because
3535+the `livebook.env` file will be added to the world-readable Nix store.
3636+A better approach would be to put the password in some secure
3737+user-readable location and set `environmentFile = /home/user/secure/livebook.env`.
3838+3939+:::
+90
nixos/modules/services/development/livebook.nix
···11+{ config, lib, pkgs, ... }:
22+33+with lib;
44+let
55+ cfg = config.services.livebook;
66+in
77+{
88+ options.services.livebook = {
99+ # Since livebook doesn't have a granular permission system (a user
1010+ # either has access to all the data or none at all), the decision
1111+ # was made to run this as a user service. If that changes in the
1212+ # future, this can be changed to a system service.
1313+ enableUserService = mkEnableOption "a user service for Livebook";
1414+1515+ environmentFile = mkOption {
1616+ type = types.path;
1717+ description = lib.mdDoc ''
1818+ Environment file as defined in {manpage}`systemd.exec(5)` passed to the service.
1919+2020+ This must contain at least `LIVEBOOK_PASSWORD` or
2121+ `LIVEBOOK_TOKEN_ENABLED=false`. See `livebook server --help`
2222+ for other options.'';
2323+ };
2424+2525+ erlang_node_short_name = mkOption {
2626+ type = with types; nullOr str;
2727+ default = null;
2828+ example = "livebook";
2929+ description = "A short name for the distributed node.";
3030+ };
3131+3232+ erlang_node_name = mkOption {
3333+ type = with types; nullOr str;
3434+ default = null;
3535+ example = "livebook@127.0.0.1";
3636+ description = "The name for the app distributed node.";
3737+ };
3838+3939+ port = mkOption {
4040+ type = types.port;
4141+ default = 8080;
4242+ description = "The port to start the web application on.";
4343+ };
4444+4545+ address = mkOption {
4646+ type = types.str;
4747+ default = "127.0.0.1";
4848+ description = lib.mdDoc ''
4949+ The address to start the web application on. Must be a valid IPv4 or
5050+ IPv6 address.
5151+ '';
5252+ };
5353+5454+ options = mkOption {
5555+ type = with types; attrsOf str;
5656+ default = { };
5757+ description = lib.mdDoc ''
5858+ Additional options to pass as command-line arguments to the server.
5959+ '';
6060+ example = literalExpression ''
6161+ {
6262+ cookie = "a value shared by all nodes in this cluster";
6363+ }
6464+ '';
6565+ };
6666+ };
6767+6868+ config = mkIf cfg.enableUserService {
6969+ systemd.user.services.livebook = {
7070+ serviceConfig = {
7171+ Restart = "always";
7272+ EnvironmentFile = cfg.environmentFile;
7373+ ExecStart =
7474+ let
7575+ args = lib.cli.toGNUCommandLineShell { } ({
7676+ inherit (cfg) port;
7777+ ip = cfg.address;
7878+ name = cfg.erlang_node_name;
7979+ sname = cfg.erlang_node_short_name;
8080+ } // cfg.options);
8181+ in
8282+ "${pkgs.livebook}/bin/livebook server ${args}";
8383+ };
8484+ path = [ pkgs.bash ];
8585+ wantedBy = [ "default.target" ];
8686+ };
8787+ };
8888+8989+ meta.doc = ./livebook.md;
9090+}