2023-09-18 13:59:48 +02:00
|
|
|
{ config, pkgs, lib, ... }: let
|
|
|
|
cfg = config.services.jupyter;
|
|
|
|
in {
|
|
|
|
sops.secrets."jupyter/password" = {
|
|
|
|
restartUnits = [ "jupyter.service" ];
|
|
|
|
owner = cfg.user;
|
|
|
|
group = cfg.group;
|
|
|
|
};
|
|
|
|
|
|
|
|
users.users."jupyter".group = "jupyter";
|
|
|
|
users.groups."jupyter".members = [ "nginx" ];
|
|
|
|
|
|
|
|
services.jupyter = {
|
|
|
|
enable = true;
|
|
|
|
group = "jupyter";
|
|
|
|
password = let
|
|
|
|
readFile = f: "open('${f}', 'r', encoding='utf8').read().strip()";
|
|
|
|
in
|
|
|
|
readFile config.sops.secrets."jupyter/password".path;
|
|
|
|
|
2023-10-03 01:23:45 +02:00
|
|
|
/* kernels = { */
|
|
|
|
/* pythonDS = let */
|
|
|
|
/* env = (pkgs.python310.withPackages (pythonPackages: with pythonPackages; [ */
|
|
|
|
/* numpy */
|
|
|
|
/* matplotlib */
|
|
|
|
/* ipykernel */
|
|
|
|
/* ])); */
|
|
|
|
/* in { */
|
|
|
|
/* displayName = "Python for data science"; */
|
|
|
|
/* argv = [ */
|
|
|
|
/* "${env.interpreter}" */
|
|
|
|
/* "-m" */
|
|
|
|
/* "ipykernel_launcher" */
|
|
|
|
/* "-f" */
|
|
|
|
/* "{connection_file}" */
|
|
|
|
/* ]; */
|
|
|
|
/* language = "python"; */
|
|
|
|
/* logo32 = "${env}/${env.sitePackages}/ipykernel/resources/logo-32x32.png"; */
|
|
|
|
/* logo64 = "${env}/${env.sitePackages}/ipykernel/resources/logo-64x64.png"; */
|
|
|
|
/* }; */
|
|
|
|
/* }; */
|
2023-09-18 13:59:48 +02:00
|
|
|
kernels = {
|
2023-10-03 01:23:45 +02:00
|
|
|
python3 = let
|
2023-09-18 13:59:48 +02:00
|
|
|
env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
|
2023-10-03 01:23:45 +02:00
|
|
|
ipykernel
|
|
|
|
pandas
|
|
|
|
numpy
|
|
|
|
scipy
|
|
|
|
scikit-learn
|
|
|
|
]));
|
2023-09-18 13:59:48 +02:00
|
|
|
in {
|
2023-10-03 01:23:45 +02:00
|
|
|
displayName = "Python 3 for statistics";
|
2023-09-18 13:59:48 +02:00
|
|
|
argv = [
|
|
|
|
"${env.interpreter}"
|
|
|
|
"-m"
|
|
|
|
"ipykernel_launcher"
|
|
|
|
"-f"
|
|
|
|
"{connection_file}"
|
|
|
|
];
|
|
|
|
language = "python";
|
|
|
|
logo32 = "${env}/${env.sitePackages}/ipykernel/resources/logo-32x32.png";
|
|
|
|
logo64 = "${env}/${env.sitePackages}/ipykernel/resources/logo-64x64.png";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.services.jupyter = let
|
|
|
|
notebookConfig = pkgs.writeText "jupyter_config.py" ''
|
|
|
|
c.NotebookApp.notebook_dir = 'notebooks'
|
|
|
|
c.NotebookApp.open_browser = False
|
|
|
|
c.NotebookApp.password = ${cfg.password}
|
|
|
|
c.NotebookApp.password_required = True
|
|
|
|
|
|
|
|
c.NotebookApp.sock = '/run/jupyter/jupyter.sock'
|
|
|
|
c.NotebookApp.sock_mode = '0660'
|
|
|
|
c.NotebookApp.local_hostnames = ['jupyter.feal.no']
|
|
|
|
|
|
|
|
c.ConnectionFileMixin.transport = 'ipc'
|
|
|
|
|
|
|
|
${cfg.notebookConfig}
|
|
|
|
'';
|
|
|
|
in {
|
|
|
|
environment = {
|
|
|
|
JUPYTER_DATA_DIR = "$STATE_DIRECTORY/data";
|
|
|
|
JUPYTER_RUNTIME_DIR = "$RUNTIME_DIRECTORY";
|
|
|
|
};
|
|
|
|
serviceConfig = {
|
|
|
|
RuntimeDirectory = "jupyter";
|
|
|
|
StateDirectory = "jupyter";
|
|
|
|
|
|
|
|
# Hardening
|
|
|
|
CapabilityBoundingSet = "";
|
|
|
|
LockPersonality = true;
|
|
|
|
NoNewPrivileges = true;
|
|
|
|
PrivateDevices = true;
|
|
|
|
PrivateMounts = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
PrivateUsers = true;
|
|
|
|
ProtectClock = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
ProtectHostname = true;
|
|
|
|
ProtectKernelLogs = true;
|
|
|
|
ProtectKernelModules = true;
|
|
|
|
ProtectKernelTunables = true;
|
|
|
|
ProtectProc = "invisible";
|
|
|
|
ProtectSystem = "strict";
|
|
|
|
RemoveIPC = true;
|
|
|
|
RestrictSUIDSGID = true;
|
|
|
|
UMask = "0007";
|
|
|
|
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
|
|
|
SystemCallArchitectures = "native";
|
|
|
|
|
|
|
|
ExecStartPre = ''
|
|
|
|
${pkgs.coreutils}/bin/mkdir -p /var/lib/jupyter/{notebooks,data}
|
|
|
|
'';
|
|
|
|
ExecStart = lib.mkForce ''
|
|
|
|
${cfg.package}/bin/${cfg.command} --NotebookApp.config_file=${notebookConfig}
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
services.nginx.virtualHosts."jupyter.feal.no" = {
|
2023-10-03 01:23:45 +02:00
|
|
|
locations."/" = {
|
|
|
|
proxyPass = "http://unix:/run/jupyter/jupyter.sock:/";
|
|
|
|
proxyWebsockets = true;
|
|
|
|
};
|
2023-09-18 13:59:48 +02:00
|
|
|
};
|
|
|
|
}
|