mirror of
https://github.com/jupyter/docker-stacks.git
synced 2025-10-13 21:12:57 +00:00
More options for securing the notebook
* letencrypt workflow * Don't mount self-signed secrets directory over runtime dir where nbextensions might be preinstalled from Dockerfile (c) Copyright IBM Corp. 2015
This commit is contained in:
@@ -1,13 +1,11 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
.PHONY: help check image notebook secure-notebook
|
||||
.PHONY: help check image notebook
|
||||
|
||||
IMAGE:=my-notebook
|
||||
|
||||
# OK to re-run volume create, noop if volume already exists
|
||||
# Destroy the old notebook container, consider it temporary
|
||||
# Show the ports at the end
|
||||
# Common, extensible docker run command
|
||||
define RUN_NOTEBOOK
|
||||
@docker volume create --name $(WORK_VOLUME) > /dev/null
|
||||
-@docker rm -f $(NAME) 2> /dev/null
|
||||
@@ -15,16 +13,13 @@ define RUN_NOTEBOOK
|
||||
--name $(NAME) \
|
||||
-v $(WORK_VOLUME):/home/jovyan/work \
|
||||
$(DOCKER_ARGS) \
|
||||
$(IMAGE) bash -c "$(PRE_CMD) chown jovyan /home/jovyan/work && start-notebook.sh" > /dev/null
|
||||
$(IMAGE) bash -c "$(PRE_CMD) chown jovyan /home/jovyan/work && start-notebook.sh $(ARGS)" > /dev/null
|
||||
@echo "DONE: Notebook '$(NAME)' listening on $$(docker-machine ip $$(docker-machine active)):$(PORT)"
|
||||
endef
|
||||
|
||||
help:
|
||||
@cat README.md
|
||||
|
||||
include virtualbox.makefile
|
||||
include softlayer.makefile
|
||||
|
||||
check:
|
||||
@which docker-machine > /dev/null || (echo "ERROR: docker-machine not found (brew install docker-machine)"; exit 1)
|
||||
@which docker > /dev/null || (echo "ERROR: docker not found (brew install docker)"; exit 1)
|
||||
@@ -34,24 +29,16 @@ image: DOCKER_ARGS?=
|
||||
image:
|
||||
@docker build --rm $(DOCKER_ARGS) -t $(IMAGE) .
|
||||
|
||||
password-check:
|
||||
@test -n "$(PASSWORD)" || \
|
||||
(echo "ERROR: PASSWORD not defined or blank"; exit 1)
|
||||
|
||||
notebook: PORT?=80
|
||||
notebook: NAME?=notebook
|
||||
notebook: WORK_VOLUME?=$(NAME)-data
|
||||
notebook: check
|
||||
$(RUN_NOTEBOOK)
|
||||
|
||||
secure-notebook: PORT?=443
|
||||
secure-notebook: NAME?=notebook
|
||||
secure-notebook: WORK_VOLUME?=$(NAME)-data
|
||||
secure-notebook: SECRETS_VOLUME?=$(NAME)-secrets
|
||||
secure-notebook: DOCKER_ARGS:=-e USE_HTTPS=yes \
|
||||
-e PASSWORD=$(PASSWORD) \
|
||||
-v $(NAME)-secrets:/home/jovyan/.local/share/jupyter
|
||||
secure-notebook: PRE_CMD:=chown jovyan /home/jovyan/.local/share/jupyter;
|
||||
secure-notebook: check password-check
|
||||
@docker volume create --name $(SECRETS_VOLUME) > /dev/null
|
||||
$(RUN_NOTEBOOK)
|
||||
# docker-machine drivers
|
||||
include virtualbox.makefile
|
||||
include softlayer.makefile
|
||||
|
||||
# Preset notebook configurations
|
||||
include self-signed.makefile
|
||||
include letsencrypt.makefile
|
@@ -45,7 +45,22 @@ make notebook NAME=your-notebook PORT=9001 WORK_VOLUME=our-work
|
||||
|
||||
### How do I run over HTTPS?
|
||||
|
||||
Instead of `make notebook` run `make secure-notebook PASSWORD=your_desired_password`.
|
||||
Instead of `make notebook`, run `make self-signed-notebook PASSWORD=your_desired_password`. This target gives you a notebook wtih a self-signed certificate.
|
||||
|
||||
### That self-signed certificate is a pain. Let's Encrypt?
|
||||
|
||||
Yes. Please.
|
||||
|
||||
```
|
||||
make letsencrypt FQDN=host.mydomain.com EMAIL=myemail@somewhere.com
|
||||
make letsencrypt-notebook
|
||||
```
|
||||
|
||||
The first command creates a Docker volume named after the notebook container with a `-secrets` suffix. It then runs the `letsencrypt` client with a slew of options (one of which has you automatically agreeing to the Let's Encrypt Terms of Service, see the Makefile). The second command mounts the secrets volume and configures Jupyter to use the full-chain certificate and private key.
|
||||
|
||||
Be aware: Let's Encrypt has a pretty [low rate limit per domain](https://community.letsencrypt.org/t/public-beta-rate-limits/4772/3) at the moment. Don't exhaust your requests playing around!
|
||||
|
||||
Also, keep in mind Let's Encrypt certificates are short lived: 90 days at the moment. You'll need to manually setup a cron job to run the renewal steps at the moment. (You can reuse the first command above.)
|
||||
|
||||
### My pip/conda/apt-get installs disappear every time I restart the container. Can I make them permanent?
|
||||
|
||||
@@ -88,10 +103,6 @@ If you'd like to add support for another docker-machine driver, use the `softlay
|
||||
|
||||
`make notebook` creates a Docker volume named after the notebook container with a `-data` suffix.
|
||||
|
||||
### Where are my HTTPS certificate and key stored?
|
||||
|
||||
`make secure-notebook` creates a Docker volume named after the notebook container with a `-secrets` suffix.
|
||||
|
||||
### Uh ... make?
|
||||
|
||||
Yes, sorry Windows users. It got the job done for a simple example. We can certainly accept other deployment mechanism examples in the parent folder or in other repos.
|
||||
|
44
examples/make-deploy/letsencrypt.makefile
Normal file
44
examples/make-deploy/letsencrypt.makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
letsencrypt: NAME?=notebook
|
||||
letsencrypt: SECRETS_VOLUME?=$(NAME)-secrets
|
||||
letsencrypt:
|
||||
@test -n "$(FQDN)" || \
|
||||
(echo "ERROR: FQDN not defined or blank"; exit 1)
|
||||
@test -n "$(EMAIL)" || \
|
||||
(echo "ERROR: EMAIL not defined or blank"; exit 1)
|
||||
@docker volume create --name $(SECRETS_VOLUME) > /dev/null
|
||||
-@docker rm letsencrypt 2> /dev/null
|
||||
@docker run -it -p 80:80 --name letsencrypt \
|
||||
-v $(SECRETS_VOLUME):/secrets \
|
||||
quay.io/letsencrypt/letsencrypt:latest \
|
||||
certonly \
|
||||
--standalone \
|
||||
--standalone-supported-challenges http-01 \
|
||||
--cert-path /secrets/cert.pem \
|
||||
--key-path /secrets/privkey.pem \
|
||||
--chain-path /secrets/chain.pem \
|
||||
--fullchain-path /secrets/fullchain.pem \
|
||||
--agree-tos \
|
||||
--duplicate \
|
||||
--domain '$(FQDN)' \
|
||||
--email '$(EMAIL)'
|
||||
@docker rm letsencrypt > /dev/null
|
||||
|
||||
letsencrypt-notebook: PORT?=443
|
||||
letsencrypt-notebook: NAME?=notebook
|
||||
letsencrypt-notebook: WORK_VOLUME?=$(NAME)-data
|
||||
letsencrypt-notebook: SECRETS_VOLUME?=$(NAME)-secrets
|
||||
letsencrypt-notebook: DOCKER_ARGS:=-e USE_HTTPS=yes \
|
||||
-e PASSWORD=$(PASSWORD) \
|
||||
-v $(SECRETS_VOLUME):/secrets
|
||||
letsencrypt-notebook: PRE_CMD:=chown -R jovyan /secrets; \
|
||||
chmod 600 /secrets/*;
|
||||
letsencrypt-notebook: ARGS:=\
|
||||
--NotebookApp.certfile=/secrets/fullchain.pem \
|
||||
--NotebookApp.keyfile=/secrets/privkey.pem
|
||||
letsencrypt-notebook: check
|
||||
@test -n "$(PASSWORD)" || \
|
||||
(echo "ERROR: PASSWORD not defined or blank"; exit 1)
|
||||
$(RUN_NOTEBOOK)
|
12
examples/make-deploy/self-signed.makefile
Normal file
12
examples/make-deploy/self-signed.makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
self-signed-notebook: PORT?=443
|
||||
self-signed-notebook: NAME?=notebook
|
||||
self-signed-notebook: WORK_VOLUME?=$(NAME)-data
|
||||
self-signed-notebook: DOCKER_ARGS:=-e USE_HTTPS=yes \
|
||||
-e PASSWORD=$(PASSWORD)
|
||||
self-signed-notebook: check
|
||||
@test -n "$(PASSWORD)" || \
|
||||
(echo "ERROR: PASSWORD not defined or blank"; exit 1)
|
||||
$(RUN_NOTEBOOK)
|
Reference in New Issue
Block a user