Skip to content

Integrate Let's Encrypt for TLS certificate generation #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
RUN chmod +x /verify.sh /start.sh

RUN apt-get install -y git
RUN git clone https://github.com/letsencrypt/letsencrypt.git /letsencrypt

41 changes: 36 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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 \
Expand All @@ -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=<appname>:backend \
--publish=443:443 \
-e TLS_GENERATE=true \
-e [email protected] \
-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

Expand Down
11 changes: 8 additions & 3 deletions lib/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;


Expand Down Expand Up @@ -71,5 +71,10 @@ http {
proxy_read_timeout 43200000;
proxy_send_timeout 43200000;
}

location ~ /.well-known {
root /;
allow all;
}
}
}
42 changes: 41 additions & 1 deletion lib/start.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,44 @@
#!/bin/bash

ulimit -n 32000
/opt/nginx/sbin/nginx

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