Skip to content
This repository has been archived by the owner on Aug 10, 2022. It is now read-only.

Commit

Permalink
docs: add Let's Encrypt docker example
Browse files Browse the repository at this point in the history
This change adds an auto-renewing configuration of Let's Encrypt used
with the wrapper.
  • Loading branch information
dekobon committed Oct 21, 2020
1 parent 3977b27 commit bae1be3
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 0 deletions.
31 changes: 31 additions & 0 deletions recipes/letsencrypt/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
FROM nginx:1.19.3

ENV LETS_ENCRYPT_DIR /etc/letsencrypt/live
ENV NGINX_CONF_DIR /etc/nginx
ENV NGINX_WRAPPER_VERSION v0.0.2
ENV NGINX_WRAPPER_CHECKSUM baad2c58df709688fed24c345e05d647c669aa025273f192f445c73869353f79

COPY opt /opt

RUN set -eux \
export DEBIAN_FRONTEND=noninteractive; \
rm /etc/machine-id; \
curl --retry 6 -Ls -o "${NGINX_CONF_DIR}/options-ssl-nginx.conf" \
"https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf"; \
curl --retry 6 -Ls -o "${NGINX_CONF_DIR}/ssl-dhparams.pem" \
"https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem"; \
mkdir -p /opt/nginx-wrapper/bin /opt/nginx-wrapper/plugins /opt/nginx-wrapper/run; \
curl -o /opt/nginx-wrapper/bin/nginx-wrapper.gz --retry 6 -Ls "https://github.com/nginxinc/nginx-wrapper/releases/download/${NGINX_WRAPPER_VERSION}/nginx-wrapper-linux_amd64-${NGINX_WRAPPER_VERSION}.gz"; \
echo "${NGINX_WRAPPER_CHECKSUM} /opt/nginx-wrapper/bin/nginx-wrapper.gz" | sha256sum -c; \
gunzip /opt/nginx-wrapper/bin/nginx-wrapper.gz; \
chmod +x /opt/nginx-wrapper/bin/*; \
apt-get update -qq; \
apt-get install -y -qq uuid certbot python3-certbot-nginx; \
rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/*

WORKDIR /opt/nginx-wrapper

CMD [ "bin/launch_wrapper.sh" ]

EXPOSE 80
EXPOSE 443
53 changes: 53 additions & 0 deletions recipes/letsencrypt/opt/nginx-wrapper/bin/launch_wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash

# Exit the script and an error is encountered
set -o errexit
# Exit the script when a pipe operation fails
set -o pipefail

if [ -z "${TLS_HOSTNAME}" ]; then
>&2 echo "TLS_HOSTNAME must be set to the domain you wish to use with Let's Encrypt"
exit 1
fi

if [ -z "${LETS_ENCRYPT_EMAIL}" ]; then
>&2 echo "LETS_ENCRYPT_EMAIL must be set to the email that you wish to use with Let's Encrypt"
exit 1
fi

if [ -z "${DNS_RESOLVER}" ]; then
>&2 echo "DNS_RESOLVER was not set - using default of 1.1.1.1"
export DNS_RESOLVER="1.1.1.1"
fi

# Path to the Let's Encrypt TLS certificates
export CERT_DIR="/etc/letsencrypt/live/${TLS_HOSTNAME}"
export PATH="${PATH}:/opt/nginx-wrapper/bin"

if [ "" = "${LETS_ENCRYPT_STAGING:-}" ] || [ "0" = "${LETS_ENCRYPT_STAGING}" ]; then
CERTBOT_STAGING_FLAG=""
else
CERTBOT_STAGING_FLAG="--staging"
fi

# Exit the script when there are undeclared variables
set -o nounset

if [ ! -f "${CERT_DIR}/fullchain.pem" ]; then
echo "Generating certificates with Let's Encrypt"
certbot certonly --standalone \
-m "${LETS_ENCRYPT_EMAIL}" \
${CERTBOT_STAGING_FLAG} \
--agree-tos --force-renewal --non-interactive \
-d "${TLS_HOSTNAME}"
fi

# Assigns a unique machine ID that can be read by the wrapper
if [ ! -f /etc/machine-id ]; then
uuid -F STR | tr -d '-' > /etc/machine-id
fi

# Start up the wrapper
exec /opt/nginx-wrapper/bin/nginx-wrapper \
--config /opt/nginx-wrapper/nginx-wrapper.toml \
run
6 changes: 6 additions & 0 deletions recipes/letsencrypt/opt/nginx-wrapper/bin/nginx_reload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env sh

# Issue a NGINX reload signal (SIGUSR2 indicates to the wrapper to ONLY reload
# NGINX and not other configuration) to the nginx-wrapper.
WRAPPER_PID="$(cat /opt/nginx-wrapper/run/nginx-wrapper.pid)"
kill -s SIGUSR2 "${WRAPPER_PID}"
82 changes: 82 additions & 0 deletions recipes/letsencrypt/opt/nginx-wrapper/nginx-wrapper.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Core configuration

# By default searches $PATH for the binary "nginx".
# Absolute and relative paths are also acceptable.
nginx_binary = "nginx"

# The runtime directory of the nginx process. Configuration and other
# related files will be copied into this directory.
# By default assigns the value of os.TempDir() + '/nginx-wrapper'.
run_path = "/opt/nginx-wrapper/run"

# Uses the value of --modules_path as returned by "nginx -V" by default.
modules_path = "/usr/lib/nginx/modules"

# Path to read nginx-wrapper plugins from.
# Default value is: ./plugins/
plugin_path = "./plugins"

# Array of plugins that are enabled to run in the NGINX Wrapper.
# By default no plugins are enabled.
enabled_plugins = [ "coprocess", "template" ]

# Logging configuration
[log]
# Log verbosity for output. Default value is INFO.
# Valid values are: TRACE, DEBUG, INFO, WARN, ERROR, PANIC, FATAL
level = "INFO"

# Log output destination. Default value is STDOUT.
# Valid values are: STDOUT, STDERR, file path
destination = "STDOUT"

# Log format for output. Default value is TextFormatter
# Valid values are: TextFormatter, JSONFormatter
formatter_name = "TextFormatter"

# Section containing options for the log formatter.
# Reference https://github.com/sirupsen/logrus for valid values
# Both snake case and title case are acceptable
[log.formatter_options]
full_timestamp = true
pad_level_text = true

# Plugin configuration configuration occurs in its own block named after the
# plugin.
[template]
# Subdirectories to create under the run_path.
# Default values are: "client_body", "proxy", "fastcgi", "uswsgi", "scgi"
run_path_subdirs = [ "client_body", "conf", "proxy", "fastcgi", "uswsgi", "scgi" ]

# By default we look in the current directory for the file
# 'nginx.conf.' + template_suffix. A directory path is also acceptable.
conf_template_path = "template"

# The suffix that for all files that will undergo templating. By default
# the value is: .tmpl
template_suffix = ".tmpl"

# The substitution characters used in templating. By default NGINX Wrapper
# uses two square brackets surrounding the templating directive. This differs
# from the default for go templates.
template_var_left_delim = "[["
template_var_right_delim = "]]"

# Flag indicating if we want to delete the templated configuration output
# when the wrapper exits.
# Default value: true
delete_templated_conf_on_exit = true

# Flag indicating if we want to delete the nginx run directory when the
# wrapper exits.
# Default value: false
delete_run_path_on_exit = false

[coprocess.certbot_renew]
name = "certbot_renew"
exec = [ "certbot", "renew", "--nginx", "--post-hook", "nginx_reload.sh" ]
restarts = "unlimited"
time_between_restarts = "24h"
background = true
exec_event = "pre-start"
stop_event = "exit"
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
server {
listen 80;
listen [::]:80;

# ACME-challenge used by CertBot for Let's Encrypt
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
}

location / {
return 301 https://[[index .env "TLS_HOSTNAME"]]\$request_uri;
}
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name [[index .env "TLS_HOSTNAME"]];

# Let's Encrypt configuration
ssl_certificate [[index .env "CERT_DIR"]]/fullchain.pem;
ssl_certificate_key [[index .env "CERT_DIR"]]/privkey.pem;
ssl_trusted_certificate [[index .env "CERT_DIR"]]/chain.pem;

include [[index .env "NGINX_CONF_DIR"]]/options-ssl-nginx.conf;
ssl_dhparam [[index .env "NGINX_CONF_DIR"]]/ssl-dhparams.pem;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
35 changes: 35 additions & 0 deletions recipes/letsencrypt/opt/nginx-wrapper/template/nginx.conf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Last reloaded: [[.last_reload_time]]

daemon off;
master_process on;
pid [[.run_path]]/nginx.pid;
error_log /dev/stdout info;
worker_processes 1;

events {
worker_connections 1024;
}

http {
include [[index .env "NGINX_CONF_DIR"]]/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /dev/stdout main;

client_body_temp_path [[.run_path]]/client_body;
proxy_temp_path [[.run_path]]/proxy;
fastcgi_temp_path [[.run_path]]/fastcgi;
uwsgi_temp_path [[.run_path]]/uwsgi;
scgi_temp_path [[.run_path]]/scgi;

sendfile on;
keepalive_timeout 65;

resolver [[index .env "DNS_RESOLVER"]];

include [[.template_conf_output_path]]/conf.d/*.conf;
}

0 comments on commit bae1be3

Please sign in to comment.