1 { config, lib, pkgs, ... }:
7 cfg = config.services.jupyterhub;
9 kernels = (pkgs.jupyter-kernel.create {
10 definitions = if cfg.kernels != null
12 else pkgs.jupyter-kernel.default;
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}'
30 meta.maintainers = with maintainers; [ costrouc ];
32 options.services.jupyterhub = {
33 enable = mkEnableOption (lib.mdDoc "Jupyterhub development server");
35 authentication = mkOption {
37 default = "jupyterhub.auth.PAMAuthenticator";
38 description = lib.mdDoc ''
39 Jupyterhub authentication to use
41 There are many authenticators available including: oauth, pam,
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.
57 extraConfig = mkOption {
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.
70 c.SystemdSpawner.mem_limit = '8G'
71 c.SystemdSpawner.cpu_limit = 2.0
75 jupyterhubEnv = mkOption {
77 default = pkgs.python3.withPackages (p: with p; [
79 jupyterhub-systemdspawner
81 defaultText = literalExpression ''
82 pkgs.python3.withPackages (p: with p; [
84 jupyterhub-systemdspawner
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
97 jupyterlabEnv = mkOption {
99 default = pkgs.python3.withPackages (p: with p; [
103 defaultText = literalExpression ''
104 pkgs.python3.withPackages (p: with p; [
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
121 type = types.nullOr (types.attrsOf(types.submodule (import ../jupyter/kernel-options.nix {
126 example = literalExpression ''
129 env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
135 displayName = "Python 3 for machine learning";
137 "''${env.interpreter}"
144 logo32 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-32x32.png";
145 logo64 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-64x64.png";
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.
162 description = lib.mdDoc ''
163 Port number Jupyterhub will be listening on
170 description = lib.mdDoc ''
171 Bind IP JupyterHub will be listening on
175 stateDirectory = mkOption {
177 default = "jupyterhub";
178 description = lib.mdDoc ''
179 Directory for jupyterhub state (token + database)
186 systemd.services.jupyterhub = {
187 description = "Jupyterhub development server";
189 after = [ "network.target" ];
190 wantedBy = [ "multi-user.target" ];
194 ExecStart = "${cfg.jupyterhubEnv}/bin/jupyterhub --config ${jupyterhubConfig}";
196 StateDirectory = cfg.stateDirectory;
197 WorkingDirectory = "/var/lib/${cfg.stateDirectory}";