From e86bd1562dee8b1ee1914eb368ca88b017abfd1d Mon Sep 17 00:00:00 2001 From: Killian Kemps Date: Tue, 28 Apr 2020 17:12:51 +0200 Subject: [PATCH 1/2] [Docker] Add Dockerfile --- docker/Dockerfile | 35 ++++++++++++++++++++++++++ docker/entrypoint.sh | 17 +++++++++++++ web_config.production.py | 54 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 docker/Dockerfile create mode 100644 docker/entrypoint.sh create mode 100644 web_config.production.py diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..c8d5415 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,35 @@ +FROM python:3.7-slim-buster + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + make \ + && apt-get clean + +COPY Makefile /opt/snikket-web-portal/Makefile + +COPY requirements.txt /opt/snikket-web-portal/requirements.txt + +COPY build-requirements.txt /opt/snikket-web-portal/build-requirements.txt + +COPY snikket_web/ /opt/snikket-web-portal/snikket_web + +COPY babel.cfg /opt/snikket-web-portal/babel.cfg + +COPY web_config.production.py /opt/snikket-web-portal/.local/web_config.py + +WORKDIR /opt/snikket-web-portal + +RUN pip install -r requirements.txt \ + && pip install -r build-requirements.txt + +RUN make + +ENV SNIKKET_WEB_CONFIG "/opt/snikket-web-portal/.local/web_config.py" + +RUN pip install hypercorn + +ADD docker/entrypoint.sh /bin/entrypoint.sh + +ENTRYPOINT ["/bin/sh", "/bin/entrypoint.sh"] diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..06ff71d --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ -z "$SNIKKET_DOMAIN" ]; then + echo "Please provide SNIKKET_DOMAIN"; + exit 1; +fi + +if [ -z "$PROSODY_ENDPOINT" ]; then + echo "Please provide PROSODY_ENDPOINT"; + exit 1; +fi + +if [ -z "$SECRET_KEY" ]; then + echo "Please provide SECRET_KEY"; +fi + +exec hypercorn -b "0.0.0.0:8000" snikket_web:app diff --git a/web_config.production.py b/web_config.production.py new file mode 100644 index 0000000..c31a10d --- /dev/null +++ b/web_config.production.py @@ -0,0 +1,54 @@ +# REQUIRED SETTINGS +# ================= + +# Secret key used to guard forms and sessions. +# +# This must be both reasonably constant and secret. If the secret gets +# compromised, you can change it (without having to worry about the "constant" +# requirement). +# +# if not constant: +# - sessions will be lost on each server restart +# +# if not secret: +# - users may be able to forge sessions +# - attackers may be able to execute things on a properly authenticated user’s +# behalf. +# - other bad things. +import os +SECRET_KEY = os.environ['SECRET_KEY'] + +# URL (without trailing /) of the prosody HTTP server. +# +# This must be set for anything to work correctly. +# +# NOTE: If this does not point at localhost, it MUST use https. Otherwise, +# passwords will be transmitted in plaintext through insecure channels. +PROSODY_ENDPOINT = os.environ['PROSODY_ENDPOINT'] + +# The domain name of the Snikket server +# +# This must be set for login to work correctly. +SNIKKET_DOMAIN = os.environ['SNIKKET_DOMAIN'] + + +# OPTIONAL SETTINGS +# ================= + +# How long browers may cache avatars +# +# Setting this to zero forces browsers to check if their locally cached copy +# of an avatar is still up-to-date on every request; if it is, the avatar is +# not re-transferred. +# +# AVATAR_CACHE_TTL = 1800 + +# Which languages to offer +# +# Generally, the web portal will offer all languages it has available. There +# is little point in restricting this, unless if you’re in a situation where +# the release you’re on has a terrible translation of a specific language +# and not offering that language at all is better than having that terrible +# translation. +# +# LANGUAGES = ["de", "en"] From 9d1d516b5ed7043e16ad641955a31f80b8d1a7d6 Mon Sep 17 00:00:00 2001 From: Killian Kemps Date: Wed, 29 Apr 2020 21:32:05 +0200 Subject: [PATCH 2/2] [Docker] Display messages for missing envvars --- docker/entrypoint.sh | 14 -------------- web_config.production.py | 27 ++++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 06ff71d..0cab526 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,17 +1,3 @@ #!/bin/sh -if [ -z "$SNIKKET_DOMAIN" ]; then - echo "Please provide SNIKKET_DOMAIN"; - exit 1; -fi - -if [ -z "$PROSODY_ENDPOINT" ]; then - echo "Please provide PROSODY_ENDPOINT"; - exit 1; -fi - -if [ -z "$SECRET_KEY" ]; then - echo "Please provide SECRET_KEY"; -fi - exec hypercorn -b "0.0.0.0:8000" snikket_web:app diff --git a/web_config.production.py b/web_config.production.py index c31a10d..022beb9 100644 --- a/web_config.production.py +++ b/web_config.production.py @@ -16,7 +16,18 @@ # behalf. # - other bad things. import os -SECRET_KEY = os.environ['SECRET_KEY'] +import sys +import secrets + +try: + SECRET_KEY = os.environ['SECRET_KEY'] +except KeyError: + print('SECRET_KEY was not provided. It will be automatically generated. ' + 'To avoid losing sessions on each server restart, please provide ' + 'a SECRET_KEY.', + file=sys.stderr) + +SECRET_KEY = os.environ.get('SECRET_KEY', secrets.token_urlsafe(nbytes=32)) # URL (without trailing /) of the prosody HTTP server. # @@ -24,12 +35,22 @@ SECRET_KEY = os.environ['SECRET_KEY'] # # NOTE: If this does not point at localhost, it MUST use https. Otherwise, # passwords will be transmitted in plaintext through insecure channels. -PROSODY_ENDPOINT = os.environ['PROSODY_ENDPOINT'] +try: + PROSODY_ENDPOINT = os.environ['PROSODY_ENDPOINT'] +except KeyError as e: + print(f'Environment variable {e} must be set for the web portal to work', + file=sys.stderr) + sys.exit(2) # The domain name of the Snikket server # # This must be set for login to work correctly. -SNIKKET_DOMAIN = os.environ['SNIKKET_DOMAIN'] +try: + SNIKKET_DOMAIN = os.environ['SNIKKET_DOMAIN'] +except KeyError as e: + print(f'Environment variable {e} must be set for the web portal to work', + file=sys.stderr) + sys.exit(2) # OPTIONAL SETTINGS