Skip to content

Commit

Permalink
Support http-configurable and nginx reverse proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
hungdinhxuan committed Nov 22, 2023
1 parent 8178110 commit 511bac6
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
matrix:
example:
- basic-example
- proxy-example

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 2 additions & 0 deletions proxy-example/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tests/
docker-compose.yaml
12 changes: 12 additions & 0 deletions proxy-example/Dockerfile.jupyterhub
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
ARG JUPYTERHUB_VERSION
FROM jupyterhub/jupyterhub:$JUPYTERHUB_VERSION

# Install dockerspawner, nativeauthenticator
# hadolint ignore=DL3013
RUN python3 -m pip install --no-cache-dir \
dockerspawner \
jupyterhub-nativeauthenticator

CMD ["jupyterhub", "-f", "/srv/jupyterhub/jupyterhub_config.py"]
36 changes: 36 additions & 0 deletions proxy-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# JupyterLab Deployment with Configurable HTTP Proxy and Nginx Reverse Proxy

## Introduction

This project extends the existing JupyterLab deployment by introducing a robust proxy setup using both Configurable HTTP Proxy and Nginx Reverse Proxy. This configuration enhances the flexibility and security of the deployment.

## Improvements

- Added **Configurable HTTP Proxy** for managing the internal routing of JupyterLab services.
- Integrated an **Nginx Reverse Proxy** layer for secure external access.
- Provided a sample Nginx configuration optimized for this setup.

## Deployment

The deployment is managed with `docker-compose`, ensuring ease of setup and consistency. The `docker-compose.yml` includes the following services:

- `hub`: The main JupyterHub service.
- `proxy`: The Configurable HTTP Proxy service.
- `reverse-proxy`: The Nginx Reverse Proxy service.

## Usage

To deploy the JupyterLab environment:

1. Clone this repository.
2. Navigate to the repository directory.
3. Run `docker-compose up -d`.
4. Once the deployment is complete, navigate to `http://localhost:8001` to access the JupyterHub interface through the Nginx Reverse Proxy.

## Contributing

Contributions are welcome! For major changes, please open an issue first to discuss what you would like to change.

## Acknowledgments

Improvement contributed by Hung Dinh Xuan @hungdinhxuan
63 changes: 63 additions & 0 deletions proxy-example/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
version: "3"

services:
hub:
build:
context: .
dockerfile: Dockerfile.jupyterhub
args:
JUPYTERHUB_VERSION: latest
restart: always
image: jupyterhub
container_name: jupyterhub
networks:
- jupyterhub-network
volumes:
# The JupyterHub configuration file
- "./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro"
# Bind Docker socket on the host so we can connect to the daemon from
# within the container
- "/var/run/docker.sock:/var/run/docker.sock:rw"
# Bind Docker volume on host for JupyterHub database and cookie secrets
- "jupyterhub-data:/data"
ports:
- "8000:8000"
environment:
# This username will be a JupyterHub admin
JUPYTERHUB_ADMIN: admin
# All containers will join this network
DOCKER_NETWORK_NAME: jupyterhub-network
# JupyterHub will spawn this Notebook image for users
DOCKER_NOTEBOOK_IMAGE: quay.io/jupyter/base-notebook:latest
# Notebook directory inside user image
DOCKER_NOTEBOOK_DIR: /home/jovyan/work

proxy:
image: jupyterhub/configurable-http-proxy:4.6.0
container_name: jupyterhub-proxy
restart: always
networks:
- jupyterhub-network
ports:
- "8002:8000"
command: ["--default-target=http://hub:8000"]

reverse-proxy:
image: nginx:1.25.3
container_name: jupyterhub-reverse-proxy
restart: always
networks:
- jupyterhub-network
ports:
- "8001:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- proxy

volumes:
jupyterhub-data:

networks:
jupyterhub-network:
name: jupyterhub-network
58 changes: 58 additions & 0 deletions proxy-example/jupyterhub_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

# Configuration file for JupyterHub
import os

c = get_config() # noqa: F821

# We rely on environment variables to configure JupyterHub so that we
# avoid having to rebuild the JupyterHub container every time we change a
# configuration parameter.

# Spawn single-user servers as Docker containers
c.JupyterHub.spawner_class = "dockerspawner.DockerSpawner"

# Spawn containers from this image
c.DockerSpawner.image = os.environ["DOCKER_NOTEBOOK_IMAGE"]

# Connect containers to this Docker network
network_name = os.environ["DOCKER_NETWORK_NAME"]
c.DockerSpawner.use_internal_ip = True
c.DockerSpawner.network_name = network_name

# Explicitly set notebook directory because we'll be mounting a volume to it.
# Most `jupyter/docker-stacks` *-notebook images run the Notebook server as
# user `jovyan`, and set the notebook directory to `/home/jovyan/work`.
# We follow the same convention.
notebook_dir = os.environ.get("DOCKER_NOTEBOOK_DIR", "/home/jovyan/work")
c.DockerSpawner.notebook_dir = notebook_dir

# Mount the real user's Docker volume on the host to the notebook user's
# notebook directory in the container
c.DockerSpawner.volumes = {"jupyterhub-user-{username}": notebook_dir}

# Remove containers once they are stopped
c.DockerSpawner.remove = True

# For debugging arguments passed to spawned containers
c.DockerSpawner.debug = True

# User containers will access hub by container name on the Docker network
c.JupyterHub.hub_ip = "jupyterhub"
c.JupyterHub.hub_port = 8080

# Persist hub data on volume mounted inside container
c.JupyterHub.cookie_secret_file = "/data/jupyterhub_cookie_secret"
c.JupyterHub.db_url = "sqlite:////data/jupyterhub.sqlite"

# Authenticate users with Native Authenticator
c.JupyterHub.authenticator_class = "nativeauthenticator.NativeAuthenticator"

# Allow anyone to sign-up without approval
c.NativeAuthenticator.open_signup = True

# Allowed admins
admin = os.environ.get("JUPYTERHUB_ADMIN")
if admin:
c.Authenticator.admin_users = [admin]
26 changes: 26 additions & 0 deletions proxy-example/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
events {
worker_connections 1024;
}

http {
server {
listen 80;

location / {
proxy_pass http://proxy:8000; # Assuming 'proxy' is the service name in docker-compose

# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;

# Handling real IP and scheme in proxied server
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
}

0 comments on commit 511bac6

Please sign in to comment.