nixos/preload: init
[NixPkgs.git] / nixos / modules / services / development / jupyterhub / default.nix
blobcebc35a50476057bf2cc37ba6ed02be57a7da8d0
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   cfg = config.services.jupyterhub;
9   kernels = (pkgs.jupyter-kernel.create  {
10     definitions = if cfg.kernels != null
11       then cfg.kernels
12       else  pkgs.jupyter-kernel.default;
13   });
15   jupyterhubConfig = pkgs.writeText "jupyterhub_config.py" ''
16     c.JupyterHub.bind_url = "http://${cfg.host}:${toString cfg.port}"
18     c.JupyterHub.authenticator_class = "${cfg.authentication}"
19     c.JupyterHub.spawner_class = "${cfg.spawner}"
21     c.SystemdSpawner.default_url = '/lab'
22     c.SystemdSpawner.cmd = "${cfg.jupyterlabEnv}/bin/jupyterhub-singleuser"
23     c.SystemdSpawner.environment = {
24       'JUPYTER_PATH': '${kernels}'
25     }
27     ${cfg.extraConfig}
28   '';
29 in {
30   meta.maintainers = with maintainers; [ costrouc ];
32   options.services.jupyterhub = {
33     enable = mkEnableOption (lib.mdDoc "Jupyterhub development server");
35     authentication = mkOption {
36       type = types.str;
37       default = "jupyterhub.auth.PAMAuthenticator";
38       description = lib.mdDoc ''
39         Jupyterhub authentication to use
41         There are many authenticators available including: oauth, pam,
42         ldap, kerberos, etc.
43       '';
44     };
46     spawner = mkOption {
47       type = types.str;
48       default = "systemdspawner.SystemdSpawner";
49       description = lib.mdDoc ''
50         Jupyterhub spawner to use
52         There are many spawners available including: local process,
53         systemd, docker, kubernetes, yarn, batch, etc.
54       '';
55     };
57     extraConfig = mkOption {
58       type = types.lines;
59       default = "";
60       description = lib.mdDoc ''
61         Extra contents appended to the jupyterhub configuration
63         Jupyterhub configuration is a normal python file using
64         Traitlets. https://jupyterhub.readthedocs.io/en/stable/getting-started/config-basics.html. The
65         base configuration of this module was designed to have sane
66         defaults for configuration but you can override anything since
67         this is a python file.
68       '';
69       example = ''
70         c.SystemdSpawner.mem_limit = '8G'
71         c.SystemdSpawner.cpu_limit = 2.0
72       '';
73     };
75     jupyterhubEnv = mkOption {
76       type = types.package;
77       default = pkgs.python3.withPackages (p: with p; [
78         jupyterhub
79         jupyterhub-systemdspawner
80       ]);
81       defaultText = literalExpression ''
82         pkgs.python3.withPackages (p: with p; [
83           jupyterhub
84           jupyterhub-systemdspawner
85         ])
86       '';
87       description = lib.mdDoc ''
88         Python environment to run jupyterhub
90         Customizing will affect the packages available in the hub and
91         proxy. This will allow packages to be available for the
92         extraConfig that you may need. This will not normally need to
93         be changed.
94       '';
95     };
97     jupyterlabEnv = mkOption {
98       type = types.package;
99       default = pkgs.python3.withPackages (p: with p; [
100         jupyterhub
101         jupyterlab
102       ]);
103       defaultText = literalExpression ''
104         pkgs.python3.withPackages (p: with p; [
105           jupyterhub
106           jupyterlab
107         ])
108       '';
109       description = lib.mdDoc ''
110         Python environment to run jupyterlab
112         Customizing will affect the packages available in the
113         jupyterlab server and the default kernel provided. This is the
114         way to customize the jupyterlab extensions and jupyter
115         notebook extensions. This will not normally need to
116         be changed.
117       '';
118     };
120     kernels = mkOption {
121       type = types.nullOr (types.attrsOf(types.submodule (import ../jupyter/kernel-options.nix {
122         inherit lib pkgs;
123       })));
125       default = null;
126       example = literalExpression ''
127         {
128           python3 = let
129             env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
130                     ipykernel
131                     pandas
132                     scikit-learn
133                   ]));
134           in {
135             displayName = "Python 3 for machine learning";
136             argv = [
137               "''${env.interpreter}"
138               "-m"
139               "ipykernel_launcher"
140               "-f"
141               "{connection_file}"
142             ];
143             language = "python";
144             logo32 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-32x32.png";
145             logo64 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-64x64.png";
146           };
147         }
148       '';
149       description = lib.mdDoc ''
150         Declarative kernel config
152         Kernels can be declared in any language that supports and has
153         the required dependencies to communicate with a jupyter server.
154         In python's case, it means that ipykernel package must always be
155         included in the list of packages of the targeted environment.
156       '';
157     };
159     port = mkOption {
160       type = types.port;
161       default = 8000;
162       description = lib.mdDoc ''
163         Port number Jupyterhub will be listening on
164       '';
165     };
167     host = mkOption {
168       type = types.str;
169       default = "0.0.0.0";
170       description = lib.mdDoc ''
171         Bind IP JupyterHub will be listening on
172       '';
173     };
175     stateDirectory = mkOption {
176       type = types.str;
177       default = "jupyterhub";
178       description = lib.mdDoc ''
179         Directory for jupyterhub state (token + database)
180       '';
181     };
182   };
184   config = mkMerge [
185     (mkIf cfg.enable  {
186       systemd.services.jupyterhub = {
187         description = "Jupyterhub development server";
189         after = [ "network.target" ];
190         wantedBy = [ "multi-user.target" ];
192         serviceConfig = {
193           Restart = "always";
194           ExecStart = "${cfg.jupyterhubEnv}/bin/jupyterhub --config ${jupyterhubConfig}";
195           User = "root";
196           StateDirectory = cfg.stateDirectory;
197           WorkingDirectory = "/var/lib/${cfg.stateDirectory}";
198         };
199       };
200     })
201   ];