diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..c2ffdc7
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,33 @@
+version: '3'
+
+services:
+  jupyterhub:
+    build: jupyterhub
+    container_name: jupyterhub
+    volumes:
+      - "/var/run/docker.sock:/var/run/docker.sock"
+    environment:
+      - VIRTUAL_HOST=jupyter.floop.org.uk
+      - VIRTUAL_PORT=8000
+      - LETSENCRYPT_HOST=jupyter.floop.org.uk
+      - LETSENCRYPT_EMAIL=alex@floop.org.uk
+      - DOCKER_JUPYTER_IMAGE=jupyter/scipy-notebook
+      - DOCKER_NETWORK_NAME=${COMPOSE_PROJECT_NAME}_default
+      - HUB_IP=jupyterhub
+      - OAUTH_CALLBACK_URL
+      - OAUTH_CLIENT_ID
+      - OAUTH_CLIENT_SECRET
+    networks:
+      - cloudfluff_proxy
+      - default
+    restart: always
+
+  jupyterlab:
+    image: jupyter/scipy-notebook
+    command: echo
+    networks:
+      - default
+
+networks:
+  cloudfluff_proxy:
+    external: true
diff --git a/jupyterhub/Dockerfile b/jupyterhub/Dockerfile
new file mode 100644
index 0000000..e0a3f6e
--- /dev/null
+++ b/jupyterhub/Dockerfile
@@ -0,0 +1,8 @@
+FROM jupyterhub/jupyterhub:1.0.0
+
+COPY jupyterhub_config.py .
+RUN wget https://raw.githubusercontent.com/jupyterhub/jupyterhub/0.9.3/examples/cull-idle/cull_idle_servers.py
+
+RUN pip install \
+    dockerspawner==0.10.0 \
+    oauthenticator==0.8.0
\ No newline at end of file
diff --git a/jupyterhub/jupyterhub_config.py b/jupyterhub/jupyterhub_config.py
new file mode 100644
index 0000000..07b000d
--- /dev/null
+++ b/jupyterhub/jupyterhub_config.py
@@ -0,0 +1,18 @@
+import os
+
+c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
+c.DockerSpawner.image = os.environ['DOCKER_JUPYTER_IMAGE']
+c.DockerSpawner.network_name = os.environ['DOCKER_NETWORK_NAME']
+c.JupyterHub.hub_ip = '0.0.0.0'  # listen on all interfaces
+c.JupyterHub.hub_connect_ip = os.environ['HUB_IP']
+
+c.JupyterHub.services = [
+    {
+        'name': 'cull_idle',
+        'admin': True,
+        'command': 'python /srv/jupyterhub/cull_idle_servers.py --timeout=3600'.split(),
+    },
+]
+
+from oauthenticator.github import GitHubOAuthenticator
+c.JupyterHub.authenticator_class = GitHubOAuthenticator