Merge pull request 'Add a sftpgo server and a web server' (#3) from push-xmzwrlqxnvns into master
Reviewed-on: #3
This commit was merged in pull request #3.
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/jupyterhub_volumes/users
|
||||||
|
/jupyterhub_volumes/shared
|
||||||
|
/jupyterhub_volumes/jupyterhub
|
||||||
|
/jupyterhub_volumes/caddy
|
||||||
43
Caddyfile
Normal file
43
Caddyfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
http:// {
|
||||||
|
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
|
||||||
|
# Proxy pour SFTPGo avec réécriture du chemin
|
||||||
|
# Proxy pour l'interface Web de SFTPGo
|
||||||
|
# SFTPGo n'a pas de support natif pour les sous-chemins
|
||||||
|
# Il faut proxy /web/ et /static/ séparément
|
||||||
|
handle /web/* {
|
||||||
|
reverse_proxy http://jupytersftp:8080 {
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-For {remote_host}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /static/* {
|
||||||
|
reverse_proxy http://jupytersftp:8080 {
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-For {remote_host}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /api/* {
|
||||||
|
reverse_proxy http://jupytersftp:8080 {
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-For {remote_host}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle /sftp/* {
|
||||||
|
uri strip_prefix /sftp
|
||||||
|
reverse_proxy http://jupytersftp:8080 {
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-For {remote_host}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proxy vers JupyterHub
|
||||||
|
handle /jupyter/* {
|
||||||
|
reverse_proxy http://jupyterhub:8000
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,10 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.hub
|
dockerfile: Dockerfile.hub
|
||||||
container_name: jupyterhub
|
container_name: jupyterhub
|
||||||
|
hostname: jupyterhub
|
||||||
image: jupyterhub-hub:latest
|
image: jupyterhub-hub:latest
|
||||||
ports:
|
expose:
|
||||||
- "8888:8000"
|
- "8000"
|
||||||
volumes:
|
volumes:
|
||||||
# Access to Docker socket to spawn student containers
|
# Access to Docker socket to spawn student containers
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
@@ -25,6 +26,47 @@ services:
|
|||||||
# Optional environment variables
|
# Optional environment variables
|
||||||
DOCKER_NOTEBOOK_DIR: /home/jovyan/work
|
DOCKER_NOTEBOOK_DIR: /home/jovyan/work
|
||||||
|
|
||||||
|
# ---------- Nginx ----------
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
container_name: jupyterhub-caddy
|
||||||
|
hostname: jupytercaddy
|
||||||
|
image: caddy:latest
|
||||||
|
ports:
|
||||||
|
- "8888:80"
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||||
|
- jupyterhub-caddy-data:/data
|
||||||
|
- jupyterhub-caddy-config:/config
|
||||||
|
- jupyterhub-web:/srv # Votre app
|
||||||
|
networks:
|
||||||
|
- jupyterhub-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ---------- SFTPGo ----------
|
||||||
|
sftpgo:
|
||||||
|
image: drakkan/sftpgo:latest
|
||||||
|
container_name: jupyterhub-sftpgo
|
||||||
|
hostname: jupytersftp
|
||||||
|
command: sftpgo serve --loaddata-from /config/local_config.json --loaddata-clean
|
||||||
|
expose:
|
||||||
|
- "2022"
|
||||||
|
- "8080"
|
||||||
|
environment:
|
||||||
|
SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN: true
|
||||||
|
SFTPGO_DEFAULT_ADMIN_USERNAME: admin
|
||||||
|
SFTPGO_DEFAULT_ADMIN_PASSWORD: admin2025
|
||||||
|
SFTPGO_HTTPD__BINDINGS__0__CLIENT_IP_PROXY_HEADER: X-Real-IP
|
||||||
|
volumes:
|
||||||
|
- jupyterhub-shared:/volumes/shared
|
||||||
|
- jupyterhub-course:/volumes/course
|
||||||
|
- jupyterhub-web:/volumes/web
|
||||||
|
- ./sftpgo_config.json:/config/local_config.json:ro
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- jupyterhub-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
jupyterhub-network:
|
jupyterhub-network:
|
||||||
name: jupyterhub-network
|
name: jupyterhub-network
|
||||||
@@ -32,6 +74,44 @@ networks:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
jupyterhub-data:
|
jupyterhub-data:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/jupyterhub
|
||||||
jupyterhub-shared:
|
jupyterhub-shared:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/shared
|
||||||
jupyterhub-course:
|
jupyterhub-course:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/course
|
||||||
|
jupyterhub-web:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/web
|
||||||
|
jupyterhub-caddy-data:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/caddy/data
|
||||||
|
jupyterhub-caddy-config:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/caddy/config
|
||||||
|
jupyterhub-users:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./jupyterhub_volumes/users
|
||||||
0
install_packages.sh
Normal file → Executable file
0
install_packages.sh
Normal file → Executable file
@@ -1,6 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
# Base configuration
|
# Base configuration coucou
|
||||||
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
|
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
|
||||||
|
|
||||||
# Enable debug logs
|
# Enable debug logs
|
||||||
@@ -88,79 +88,8 @@ c.Authenticator.allow_all = True
|
|||||||
c.Authenticator.admin_users = {'admin'}
|
c.Authenticator.admin_users = {'admin'}
|
||||||
|
|
||||||
# Listening port
|
# Listening port
|
||||||
c.JupyterHub.bind_url = 'http://0.0.0.0:8000'
|
c.JupyterHub.bind_url = 'http://0.0.0.0:8000/jupyter/'
|
||||||
|
|
||||||
# Timeout
|
# Timeout
|
||||||
c.Spawner.start_timeout = 300
|
c.Spawner.start_timeout = 300
|
||||||
c.Spawner.http_timeout = 120
|
c.Spawner.http_timeout = 120
|
||||||
import os
|
|
||||||
|
|
||||||
# Configuration de base
|
|
||||||
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
|
|
||||||
|
|
||||||
# Activer les logs de debug
|
|
||||||
c.JupyterHub.log_level = 'DEBUG'
|
|
||||||
c.Spawner.debug = True
|
|
||||||
|
|
||||||
# Image Docker à utiliser pour les containers étudiants
|
|
||||||
c.DockerSpawner.image = 'jupyterhub-student:latest'
|
|
||||||
|
|
||||||
# Réseau Docker (créez-le avec: docker network create jupyterhub-network)
|
|
||||||
c.DockerSpawner.network_name = 'jupyterhub-network'
|
|
||||||
|
|
||||||
# Connexion au socket Docker d'OrbStack depuis le container hub
|
|
||||||
c.DockerSpawner.client_kwargs = {'base_url': 'unix:///var/run/docker.sock'}
|
|
||||||
|
|
||||||
# IMPORTANT : URL interne pour communiquer entre containers
|
|
||||||
# Le hub container communique avec les user containers via le réseau Docker
|
|
||||||
c.JupyterHub.hub_ip = '0.0.0.0'
|
|
||||||
c.JupyterHub.hub_connect_ip = 'jupyterhub'
|
|
||||||
|
|
||||||
# Configuration réseau pour les containers étudiants
|
|
||||||
c.DockerSpawner.use_internal_ip = True
|
|
||||||
c.DockerSpawner.network_name = 'jupyterhub-network'
|
|
||||||
c.DockerSpawner.extra_host_config = {'network_mode': 'jupyterhub-network'}
|
|
||||||
|
|
||||||
# Supprimer les containers après déconnexion (optionnel, mettre False pour garder les containers)
|
|
||||||
c.DockerSpawner.remove = True
|
|
||||||
|
|
||||||
# Nommage des containers
|
|
||||||
c.DockerSpawner.name_template = "jupyter-{username}"
|
|
||||||
|
|
||||||
# Montage de volumes pour persister les données des étudiants
|
|
||||||
# Définir la racine à /home/jovyan pour voir tous les dossiers
|
|
||||||
notebook_dir = '/home/jovyan/work'
|
|
||||||
c.DockerSpawner.notebook_dir = notebook_dir
|
|
||||||
|
|
||||||
# Volume personnel pour chaque étudiant + volume partagé
|
|
||||||
c.DockerSpawner.volumes = {
|
|
||||||
# Volume personnel (persistant) - monté dans work/
|
|
||||||
'jupyterhub-user-{username}': '/home/jovyan/work',
|
|
||||||
# Volume partagé entre tous les étudiants
|
|
||||||
'jupyterhub-shared': '/home/jovyan/work/shared',
|
|
||||||
# Volume partagé en lecture seule pour les fichiers du cours (optionnel)
|
|
||||||
'jupyterhub-course': {
|
|
||||||
'bind': '/home/jovyan/work/course',
|
|
||||||
'mode': 'ro' # read-only
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Configuration de la mémoire et CPU (ajustez selon vos besoins)
|
|
||||||
c.DockerSpawner.mem_limit = '2G'
|
|
||||||
c.DockerSpawner.cpu_limit = 1.0
|
|
||||||
|
|
||||||
# Pour créer une liste d'utilisateurs autorisés, décommentez et modifiez:
|
|
||||||
# c.Authenticator.allowed_users = {'etudiant1', 'etudiant2', 'etudiant3'}
|
|
||||||
|
|
||||||
# Ou autoriser n'importe quel utilisateur avec le bon mot de passe:
|
|
||||||
c.Authenticator.allow_all = True
|
|
||||||
|
|
||||||
# Configuration admin
|
|
||||||
c.Authenticator.admin_users = {'admin'}
|
|
||||||
|
|
||||||
# Port d'écoute
|
|
||||||
c.JupyterHub.bind_url = 'http://0.0.0.0:8000'
|
|
||||||
|
|
||||||
# Timeout
|
|
||||||
c.Spawner.start_timeout = 300
|
|
||||||
c.Spawner.http_timeout = 120
|
|
||||||
13
jupyterhub_volumes/web/index.html
Normal file
13
jupyterhub_volumes/web/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Course Portal</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Welcome</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/jupyter/">JupyterHub</a></li>
|
||||||
|
<li><a href="/static/">Static Site</a></li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
45
sftpgo_config.json
Normal file
45
sftpgo_config.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"name": "shared_data",
|
||||||
|
"mapped_path": "/volumes/shared",
|
||||||
|
"description": "Dossier partagé entre utilisateurs",
|
||||||
|
"filesystem": {
|
||||||
|
"provider": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "web_site",
|
||||||
|
"mapped_path": "/volumes/web",
|
||||||
|
"description": "Site web static",
|
||||||
|
"filesystem": {
|
||||||
|
"provider": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"username": "admin",
|
||||||
|
"password": "admin2025",
|
||||||
|
"status": 1,
|
||||||
|
"home_dir": "/volumes/course",
|
||||||
|
"permissions": {
|
||||||
|
"/": ["*"]
|
||||||
|
},
|
||||||
|
"virtual_folders": [
|
||||||
|
{
|
||||||
|
"name": "shared_data",
|
||||||
|
"virtual_path": "/shared",
|
||||||
|
"quota_size": -1,
|
||||||
|
"quota_files": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "web_site",
|
||||||
|
"virtual_path": "/web",
|
||||||
|
"quota_size": -1,
|
||||||
|
"quota_files": -1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -39,16 +39,10 @@ echo ""
|
|||||||
echo -e "${BLUE}🔨 Building JupyterHub image...${NC}"
|
echo -e "${BLUE}🔨 Building JupyterHub image...${NC}"
|
||||||
docker build -t jupyterhub-hub:latest -f Dockerfile.hub .
|
docker build -t jupyterhub-hub:latest -f Dockerfile.hub .
|
||||||
|
|
||||||
# Create volumes if they don't exist
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}💾 Creating shared volumes...${NC}"
|
|
||||||
docker volume create jupyterhub-shared 2>/dev/null || echo " Volume jupyterhub-shared already exists"
|
|
||||||
docker volume create jupyterhub-course 2>/dev/null || echo " Volume jupyterhub-course already exists"
|
|
||||||
|
|
||||||
# Start the stack
|
# Start the stack
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BLUE}🚀 Starting JupyterHub...${NC}"
|
echo -e "${BLUE}🚀 Starting JupyterHub...${NC}"
|
||||||
docker-compose up -d
|
docker-compose up -d --remove-orphans
|
||||||
|
|
||||||
# Wait for service to be ready
|
# Wait for service to be ready
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Reference in New Issue
Block a user