Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit 30420bf

Browse files
authored
Merge pull request #73 from NERSC/19-10
19 10
2 parents a287c62 + dcaf08d commit 30420bf

39 files changed

Lines changed: 2026 additions & 283 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
jupyterhub.sqlite
22
jupyterhub_cookie_secret
33
/jupyter-compose/config
4+
/jupyter-compose-ssl/config

jupyter-compose-ssl/.env

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Name of JupyterHub container data volume
2+
SSL_VOLUME_HOST=jupyterhub-ssl
3+
4+
# Data volume container mount point
5+
SSL_VOLUME_CONTAINER=/jupyterhub-ssl

jupyter-compose-ssl/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Developing with docker-compose
2+
3+
These images are designed for local dev/debug/testing using docker-compose.
4+
This requires docker-compose.
5+
6+
## Preparation
7+
8+
Install Docker Compose (Just google for it).
9+
10+
Build the images
11+
12+
cd web-jupyterhub && bash build.sh && cd ..
13+
cd app-notebooks && bash build.sh && cd ..
14+
15+
You may want to pull the proxy image ahead of time
16+
17+
docker pull jupyterhub/configurable-http-proxy
18+
19+
Generate a key file
20+
21+
mkdir config
22+
ssh-keygen -t rsa -N '' -C ca@localhost -f config/newkey
23+
ssh-keygen -s config/newkey -h -I localhost config/newkey.pub
24+
25+
## Bring up the containers
26+
27+
docker-compose up -d
28+
29+
## Cleaning up and upgrading
30+
31+
In general a docker-compose up -d will refresh things. Some times that isn't enough. If all else fails, try...
32+
33+
docker-compose stop
34+
docker-compose rm -f
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
ARG branch=unknown
2+
3+
FROM registry.spin.nersc.gov/das/jupyter-base-${branch}:latest
4+
LABEL maintainer="Rollin Thomas <rcthomas@lbl.gov>"
5+
WORKDIR /tmp
6+
7+
RUN \
8+
apt-get update && \
9+
apt-get --yes upgrade && \
10+
apt-get --yes install \
11+
openssh-server
12+
13+
# Configure sshd
14+
15+
RUN \
16+
mkdir -p /var/run/sshd
17+
18+
# Python 3 Anaconda and additional packages
19+
20+
RUN \
21+
conda update --yes conda && \
22+
conda install --yes \
23+
ipykernel \
24+
ipywidgets \
25+
jupyterlab \
26+
notebook && \
27+
ipython kernel install && \
28+
conda clean --yes --all
29+
30+
ADD get_port.py /opt/anaconda3/bin
31+
32+
# Typical extensions
33+
34+
RUN \
35+
jupyter nbextension enable --sys-prefix --py widgetsnbextension
36+
37+
RUN \
38+
jupyter labextension install @jupyterlab/hub-extension
39+
40+
# Some dummy users
41+
42+
RUN \
43+
adduser -q --gecos "" --disabled-password torgo && \
44+
echo torgo:the-master-would-not-approve | chpasswd
45+
46+
RUN \
47+
adduser -q --gecos "" --disabled-password master && \
48+
echo master:you-have-failed-us-torgo | chpasswd
49+
50+
WORKDIR /srv
51+
ADD docker-entrypoint.sh .
52+
RUN chmod +x docker-entrypoint.sh
53+
ENTRYPOINT [ "./docker-entrypoint.sh" ]
54+
CMD [ "/usr/sbin/sshd", "-p", "22", "-D" ]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
branch=$(git symbolic-ref --short HEAD)
4+
5+
docker build \
6+
--build-arg branch=$branch \
7+
"$@" \
8+
--tag app-notebooks:latest .
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
for u in $(ls /home/) ; do
4+
mkdir /home/$u/.ssh/
5+
cat /config/newkey.pub > /home/$u/.ssh/authorized_keys
6+
chmod 700 /home/$u/.ssh/
7+
chown -R $u /home/$u/.ssh
8+
chmod 600 /home/$u/.ssh/authorized_keys
9+
done
10+
11+
exec "$@"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/opt/anaconda3/bin/python
2+
3+
import socket
4+
5+
def main():
6+
print(f"{ip()} {port()}")
7+
8+
def port():
9+
s = socket.socket()
10+
s.bind(('', 0))
11+
port = s.getsockname()[1]
12+
s.close()
13+
return port
14+
15+
def ip(address=("8.8.8.8", 80)):
16+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
17+
s.connect(address)
18+
ip = s.getsockname()[0]
19+
s.close()
20+
return ip
21+
22+
if __name__ == "__main__":
23+
main()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
version: "3"
2+
services:
3+
web:
4+
container_name: web
5+
depends_on:
6+
- proxy
7+
image: web-jupyterhub:latest
8+
environment:
9+
- CONFIGPROXY_AUTH_TOKEN=the-sign-pointed-this-way
10+
- ANNOUNCEMENT_JUPYTERHUB_API_TOKEN=the-hands-of-fate-have-doomed-this-man
11+
- INTERNAL_SSL_PATH=${SSL_VOLUME_CONTAINER}
12+
volumes:
13+
- ./config:/config
14+
- "ssl:${SSL_VOLUME_CONTAINER}:rw"
15+
ports:
16+
- 8081:8081
17+
restart: unless-stopped
18+
user: root
19+
app:
20+
container_name: app
21+
image: app-notebooks:latest
22+
volumes:
23+
- ./config:/config
24+
# - "ssl:${SSL_VOLUME_CONTAINER}:ro"
25+
announcement:
26+
container_name: announcement
27+
image: web-announcement:latest
28+
environment:
29+
- JUPYTERHUB_API_TOKEN=the-hands-of-fate-have-doomed-this-man
30+
- JUPYTERHUB_API_URL=https://web:8081/hub/api
31+
- JUPYTERHUB_SSL_KEYFILE=/jupyterhub-ssl/hub-internal/hub-internal.key
32+
- JUPYTERHUB_SSL_CERTFILE=/jupyterhub-ssl/hub-internal/hub-internal.crt
33+
- JUPYTERHUB_SSL_CLIENT_CA=/jupyterhub-ssl/hub-ca_trust.crt
34+
restart: always
35+
volumes:
36+
- "ssl:${SSL_VOLUME_CONTAINER}:ro"
37+
proxy:
38+
command: >
39+
configurable-http-proxy
40+
--port 8000
41+
--api-ip 0.0.0.0
42+
--api-port 8001
43+
--error-target https://web:8081/hub/error
44+
--api-ssl-key ${SSL_VOLUME_CONTAINER}/proxy-api/proxy-api.key
45+
--api-ssl-cert ${SSL_VOLUME_CONTAINER}/proxy-api/proxy-api.crt
46+
--api-ssl-ca ${SSL_VOLUME_CONTAINER}/proxy-api-ca_trust.crt
47+
--api-ssl-request-cert
48+
--api-ssl-reject-unauthorized
49+
--client-ssl-key ${SSL_VOLUME_CONTAINER}/proxy-client/proxy-client.key
50+
--client-ssl-cert ${SSL_VOLUME_CONTAINER}/proxy-client/proxy-client.crt
51+
--client-ssl-ca ${SSL_VOLUME_CONTAINER}/proxy-client-ca_trust.crt
52+
--client-ssl-request-cert
53+
--client-ssl-reject-unauthorized
54+
container_name: proxy
55+
image: jupyterhub/configurable-http-proxy:latest
56+
environment:
57+
- CONFIGPROXY_AUTH_TOKEN=the-sign-pointed-this-way
58+
ports:
59+
- 8000:8000
60+
restart: always
61+
user: root
62+
volumes:
63+
- "ssl:${SSL_VOLUME_CONTAINER}:ro"
64+
volumes:
65+
ssl:
66+
external:
67+
name: ${SSL_VOLUME_HOST}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ARG branch=unknown
2+
3+
FROM registry.spin.nersc.gov/das/jupyter-base-${branch}:latest
4+
LABEL maintainer="Rollin Thomas <rcthomas@lbl.gov>"
5+
6+
RUN \
7+
pip install git+https://github.com/rcthomas/jupyterhub-announcement.git@0.4.1
8+
9+
WORKDIR /srv
10+
11+
ADD docker-entrypoint.sh announcement_config.py ./
12+
RUN chmod +x docker-entrypoint.sh
13+
ENTRYPOINT ["./docker-entrypoint.sh"]
14+
CMD ["python", "-m", "jupyterhub_announcement"]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Configuration file for application.
2+
3+
#------------------------------------------------------------------------------
4+
# Application(SingletonConfigurable) configuration
5+
#------------------------------------------------------------------------------
6+
7+
## This is an application.
8+
9+
## The date format used by logging formatters for %(asctime)s
10+
#c.Application.log_datefmt = '%Y-%m-%d %H:%M:%S'
11+
12+
## The Logging format template
13+
#c.Application.log_format = '[%(name)s]%(highlevel)s %(message)s'
14+
15+
## Set the log level by value or name.
16+
#c.Application.log_level = 30
17+
c.Application.log_level = 0
18+
19+
#------------------------------------------------------------------------------
20+
# AnnouncementService(Application) configuration
21+
#------------------------------------------------------------------------------
22+
23+
## This is an application.
24+
25+
## Config file to load
26+
#c.AnnouncementService.config_file = 'announcement_config.py'
27+
28+
## Fixed message to show at the top of the page.
29+
#
30+
# A good use for this parameter would be a link to a more general live system
31+
# status page or MOTD.
32+
#c.AnnouncementService.fixed_message = ''
33+
34+
## Generate default config file
35+
#c.AnnouncementService.generate_config = False
36+
37+
## Logo path, can be used to override JupyterHub one
38+
#c.AnnouncementService.logo_file = ''
39+
40+
## Port this service will listen on
41+
#c.AnnouncementService.port = 8888
42+
43+
## Announcement service prefix
44+
#c.AnnouncementService.service_prefix = '/services/announcement/'
45+
46+
## Search paths for jinja templates, coming before default ones
47+
#c.AnnouncementService.template_paths = []
48+
49+
#------------------------------------------------------------------------------
50+
# AnnouncementQueue(LoggingConfigurable) configuration
51+
#------------------------------------------------------------------------------
52+
53+
## File path where announcements persist as JSON.
54+
#
55+
# For a persistent announcement queue, this parameter must be set to a non-empty
56+
# value and correspond to a read+write-accessible path. The announcement queue
57+
# is stored as a list of JSON objects. If this parameter is set to a non-empty
58+
# value:
59+
#
60+
# * The persistence file is used to initialize the announcement queue
61+
# at start-up. This is the only time the persistence file is read.
62+
# * If the persistence file does not exist at start-up, it is
63+
# created when an announcement is added to the queue.
64+
# * The persistence file is over-written with the contents of the
65+
# announcement queue each time a new announcement is added.
66+
#
67+
# If this parameter is set to an empty value (the default) then the queue is
68+
# just empty at initialization and the queue is ephemeral; announcements will
69+
# not be persisted on updates to the queue.
70+
#c.AnnouncementQueue.persist_path = ''
71+
c.AnnouncementQueue.persist_path = 'announcements.json'
72+

0 commit comments

Comments
 (0)