diff --git a/tljh/installer.py b/tljh/installer.py index 02980f1..d5875eb 100644 --- a/tljh/installer.py +++ b/tljh/installer.py @@ -3,6 +3,7 @@ import os import tljh.systemd as systemd import tljh.conda as conda from tljh import user +import secrets INSTALL_PREFIX = os.environ.get('TLJH_INSTALL_PREFIX', '/opt/tljh') HUB_ENV_PREFIX = os.path.join(INSTALL_PREFIX, 'hub') @@ -12,15 +13,27 @@ HERE = os.path.abspath(os.path.dirname(__file__)) def ensure_jupyterhub_service(prefix): + """ + Ensure JupyterHub & CHP Services are set up properly + """ with open(os.path.join(HERE, 'systemd-units', 'jupyterhub.service')) as f: - unit_template = f.read() + hub_unit_template = f.read() - unit = unit_template.format( + with open(os.path.join(HERE, 'systemd-units', 'configurable-http-proxy.service')) as f: + proxy_unit_template = f.read() + + unit_params = dict( python_interpreter_path=sys.executable, jupyterhub_config_path=os.path.join(HERE, 'jupyterhub_config.py'), install_prefix=INSTALL_PREFIX ) - systemd.install_unit('jupyterhub.service', unit) + systemd.install_unit('configurable-http-proxy.service', proxy_unit_template.format(**unit_params)) + systemd.install_unit('jupyterhub.service', hub_unit_template.format(**unit_params)) + + # Set up proxy / hub secret oken if it is not already setup + if not os.path.exists('/etc/jupyterhub/configurable-http-proxy.secret'): + with open('/etc/jupyterhub/configurable-http-proxy.secret', 'w') as f: + f.write('CONFIGPROXY_AUTH_TOKEN=' + secrets.token_hex(32)) def ensure_jupyterhub_package(prefix): @@ -53,4 +66,5 @@ conda.ensure_conda_packages(USER_ENV_PREFIX, [ 'notebook==5.5.0' ]) systemd.reload_daemon() +systemd.start_service('configurable-http-proxy') systemd.start_service('jupyterhub') diff --git a/tljh/jupyterhub_config.py b/tljh/jupyterhub_config.py index 12ec5f3..c17bc5a 100644 --- a/tljh/jupyterhub_config.py +++ b/tljh/jupyterhub_config.py @@ -24,6 +24,8 @@ class CustomSpawner(SystemdSpawner): c.JupyterHub.spawner_class = CustomSpawner +c.ConfigurableHTTPProxy.should_start = False + c.SystemdSpawner.extra_paths = [os.path.join(USER_ENV_PREFIX, 'bin')] c.SystemdSpawner.use_sudo = True diff --git a/tljh/systemd-units/configurable-http-proxy.service b/tljh/systemd-units/configurable-http-proxy.service new file mode 100644 index 0000000..d0ddd9c --- /dev/null +++ b/tljh/systemd-units/configurable-http-proxy.service @@ -0,0 +1,22 @@ +# Template file for Configurable HTTP Proxy systemd service +# Uses simple string.format() for 'templating' +[Unit] +Wants=network-online.target + +[Service] +User=root +Restart=always +# chp process should have no write access anywhere on disk +ProtectHome=tmpfs +ProtectSystem=strict +PrivateTmp=yes +PrivateDevices=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +EnvironmentFile=/etc/jupyterhub/configurable-http-proxy.secret +ExecStart={install_prefix}/hub/bin/configurable-http-proxy \ + --ip 0.0.0.0 \ + --port 80 \ + --api-ip 127.0.0.1 \ + --api-port 8001 \ + --error-target http://127.0.0.1:8081/hub/error diff --git a/tljh/systemd-units/jupyterhub.service b/tljh/systemd-units/jupyterhub.service index f4f5f47..6ea4cf0 100644 --- a/tljh/systemd-units/jupyterhub.service +++ b/tljh/systemd-units/jupyterhub.service @@ -1,13 +1,22 @@ # Template file for JupyterHub systemd service -# Runs both JupyterHub and ConfigurableHTTPProxy # Uses simple string.format() for 'templating' [Unit] -Wants=network-online.target +Wants=configurable-http-proxy.service [Service] User=root Restart=always -Environment=TLJH_INSTALL_PREFIX={install_prefix} +# jupyterhub process should have no access to home directories +ProtectHome=tmpfs +# Use a persistent, permissioned state directory for db + cookie secrets StateDirectory=jupyterhub WorkingDirectory=/var/lib/jupyterhub +# Protect bits that are normally shared across the system +PrivateTmp=yes +PrivateDevices=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +# Source CONFIGPROXY_AUTH_TOKEN from here! +EnvironmentFile=/etc/jupyterhub/configurable-http-proxy.secret +Environment=TLJH_INSTALL_PREFIX={install_prefix} ExecStart={python_interpreter_path} -m jupyterhub.app -f {jupyterhub_config_path}