1 { config, lib, pkgs, ... }:
4 cfg = config.services.jupyterhub;
6 kernels = (pkgs.jupyter-kernel.create {
7 definitions = if cfg.kernels != null
9 else pkgs.jupyter-kernel.default;
12 jupyterhubConfig = pkgs.writeText "jupyterhub_config.py" ''
13 c.JupyterHub.bind_url = "http://${cfg.host}:${toString cfg.port}"
15 c.JupyterHub.authenticator_class = "${cfg.authentication}"
16 c.JupyterHub.spawner_class = "${cfg.spawner}"
18 c.SystemdSpawner.default_url = '/lab'
19 c.SystemdSpawner.cmd = "${cfg.jupyterlabEnv}/bin/jupyterhub-singleuser"
20 c.SystemdSpawner.environment = {
21 'JUPYTER_PATH': '${kernels}'
27 meta.maintainers = with lib.maintainers; [ costrouc ];
29 options.services.jupyterhub = {
30 enable = lib.mkEnableOption "Jupyterhub development server";
32 authentication = lib.mkOption {
34 default = "jupyterhub.auth.PAMAuthenticator";
36 Jupyterhub authentication to use
38 There are many authenticators available including: oauth, pam,
43 spawner = lib.mkOption {
45 default = "systemdspawner.SystemdSpawner";
47 Jupyterhub spawner to use
49 There are many spawners available including: local process,
50 systemd, docker, kubernetes, yarn, batch, etc.
54 extraConfig = lib.mkOption {
55 type = lib.types.lines;
58 Extra contents appended to the jupyterhub configuration
60 Jupyterhub configuration is a normal python file using
61 Traitlets. https://jupyterhub.readthedocs.io/en/stable/getting-started/config-basics.html. The
62 base configuration of this module was designed to have sane
63 defaults for configuration but you can override anything since
64 this is a python file.
67 c.SystemdSpawner.mem_limit = '8G'
68 c.SystemdSpawner.cpu_limit = 2.0
72 jupyterhubEnv = lib.mkOption {
73 type = lib.types.package;
74 default = pkgs.python3.withPackages (p: with p; [
76 jupyterhub-systemdspawner
78 defaultText = lib.literalExpression ''
79 pkgs.python3.withPackages (p: with p; [
81 jupyterhub-systemdspawner
85 Python environment to run jupyterhub
87 Customizing will affect the packages available in the hub and
88 proxy. This will allow packages to be available for the
89 extraConfig that you may need. This will not normally need to
94 jupyterlabEnv = lib.mkOption {
95 type = lib.types.package;
96 default = pkgs.python3.withPackages (p: with p; [
100 defaultText = lib.literalExpression ''
101 pkgs.python3.withPackages (p: with p; [
107 Python environment to run jupyterlab
109 Customizing will affect the packages available in the
110 jupyterlab server and the default kernel provided. This is the
111 way to customize the jupyterlab extensions and jupyter
112 notebook extensions. This will not normally need to
117 kernels = lib.mkOption {
118 type = lib.types.nullOr (lib.types.attrsOf(lib.types.submodule (import ../jupyter/kernel-options.nix {
123 example = lib.literalExpression ''
126 env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
132 displayName = "Python 3 for machine learning";
134 "''${env.interpreter}"
141 logo32 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-32x32.png";
142 logo64 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-64x64.png";
147 Declarative kernel config
149 Kernels can be declared in any language that supports and has
150 the required dependencies to communicate with a jupyter server.
151 In python's case, it means that ipykernel package must always be
152 included in the list of packages of the targeted environment.
156 port = lib.mkOption {
157 type = lib.types.port;
160 Port number Jupyterhub will be listening on
164 host = lib.mkOption {
165 type = lib.types.str;
168 Bind IP JupyterHub will be listening on
172 stateDirectory = lib.mkOption {
173 type = lib.types.str;
174 default = "jupyterhub";
176 Directory for jupyterhub state (token + database)
181 config = lib.mkMerge [
182 (lib.mkIf cfg.enable {
183 systemd.services.jupyterhub = {
184 description = "Jupyterhub development server";
186 after = [ "network.target" ];
187 wantedBy = [ "multi-user.target" ];
191 ExecStart = "${cfg.jupyterhubEnv}/bin/jupyterhub --config ${jupyterhubConfig}";
193 StateDirectory = cfg.stateDirectory;
194 WorkingDirectory = "/var/lib/${cfg.stateDirectory}";