diff --git a/Dockerfile b/Dockerfile index 0a11882..ca9dfb0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,8 @@ RUN rm /tmp/install-nginx.sh COPY lib /tmp/lib RUN bash /tmp/lib/copy-files.sh -RUN chmod +x /verify.sh /start.sh \ No newline at end of file +RUN chmod +x /verify.sh /start.sh + +RUN apt-get install -y git +RUN git clone https://github.com/letsencrypt/letsencrypt.git /letsencrypt + diff --git a/README.md b/README.md index 52c1b3e..1cf2633 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Frontend Server for Meteor Up -This is the front end server used by Meteor Up in front of meteor apps. This is the latest version of nginx bundled as a docker image. It is configured to run with every app deployed with Meteor Up. But, this is not a Load Balancer. +This is the front end server used by Meteor Up in front of meteor apps. This is +the latest version of nginx bundled as a docker image. It is configured to +run with every app deployed with Meteor Up. But, this is not a Load Balancer. ## For SSL Support @@ -17,11 +19,16 @@ docker run \ meteorhacks/mup-frontend-server /start.sh ~~~ -As you've noticed, we need to add two volumes for the `bundle.crt` and `private.key`. +As you've noticed, we need to add two volumes for the `bundle.crt` and +`private.key`. #### bundle.crt -This is a bundle containing all of your certificates including the provided CA certificates. To create this file you need to concatenate all certificates starting from your domain certificate to the top level CA certificates. Here's an example: +This is a bundle containing all of your certificates including the provided CA +certificates. To create this file you need to concatenate all certificates +starting from your domain certificate to the top level CA certificates. + +Here's an example: ~~~shell cat \ @@ -46,11 +53,35 @@ docker run \ meteorhacks/mup-frontend-server /verify.sh ~~~ +### Generate automatic TLS certificate using Let's Encrypt + +This image integrates [letsencrypt](https://github.com/letsencrypt/letsencrypt) +for automated and free of cost generation of TLS certificates. + +In order to generate the certificate, it is needed to provide a valid email and +the domain(s) name that resolves to the machine exposing this containers port +443. + +Example of usage: + +~~~shell +docker run \ + --link=:backend \ + --publish=443:443 \ + -e TLS_GENERATE=true \ + -e TLS_EMAIL=example@example.com \ + -e TLS_DOMAINS=example.com \ + meteorhacks/mup-frontend-server /start.sh +~~~ + ### Why Nginx? -There's the question why we've chosen nginx for the SSL termination. We could've used something like `stud` or `bud`. +There's the question why we've chosen nginx for the SSL termination. We +could've used something like `stud` or `bud`. -We need to get the correct IP address of the real connection, which is required for certain apps such as Sikka. Normally SSL terminators like `stud` and `bud` do not support this or support it only partially. +We need to get the correct IP address of the real connection, which is +required for certain apps such as Sikka. Normally SSL terminators like +`stud` and `bud` do not support this or support it only partially. ## For Static File Caching diff --git a/lib/nginx.conf b/lib/nginx.conf index e511b04..978f7f2 100644 --- a/lib/nginx.conf +++ b/lib/nginx.conf @@ -9,7 +9,7 @@ events { http { include mime.types; default_type application/octet-stream; - + # to avoid SSL handshake time ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; @@ -39,8 +39,8 @@ http { # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify on; - - # Set upload to sensible value as defaults to 1M if not present + + # Set upload to sensible value as defaults to 1M if not present client_max_body_size 10M; @@ -71,5 +71,10 @@ http { proxy_read_timeout 43200000; proxy_send_timeout 43200000; } + + location ~ /.well-known { + root /; + allow all; + } } } diff --git a/lib/start.sh b/lib/start.sh index 24ca69c..27d1a63 100644 --- a/lib/start.sh +++ b/lib/start.sh @@ -1,4 +1,44 @@ #!/bin/bash ulimit -n 32000 -/opt/nginx/sbin/nginx \ No newline at end of file + +if [ ! -f /bundle.crt ] || [ ! -f /private.key ]; then + MISSING_CERT=true +fi + +if [ ! $MISSING_CERT ] && [ ! $TLS_GENERATE ]; then + /opt/nginx/sbin/nginx +fi + +if [ $TLS_GENERATE ]; then + echo "Generating TLS certificate..." + + mkdir /generated-tls + CONF_PATH=/generated-tls/config.ini + echo "rsa-key-size = 4096" > $CONF_PATH + echo "email = ${TLS_EMAIL:?Need to set TLS_EMAIL}" >> $CONF_PATH + echo "domains = ${TLS_DOMAINS:?Need to set TLS_DOMAINS}" >> $CONF_PATH + + if [ $MISSING_CERT ]; then + echo "authenticator = standalone" >> $CONF_PATH + echo "standalone-supported-challenges = tls-sni-01" >> $CONF_PATH + else + echo "authenticator = webroot" >> $CONF_PATH + echo "webroot-path = /" >> $CONF_PATH + fi + + echo "Using following configuration file for Let's encrypt:" + cat $CONF_PATH + echo "" + + /letsencrypt/letsencrypt-auto certonly --agree-tos -c $CONF_PATH + + # Generate the certificates for Nginx + IFS=',' read -ra DOMAIN <<< "$TLS_DOMAINS" + FULLCHAIN=/etc/letsencrypt/live/$DOMAIN/fullchain.pem + PRIVKEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem + cat $FULLCHAIN $PRIVKEY > /bundle.crt + cat $PRIVKEY > /private.key + + /opt/nginx/sbin/nginx +fi