From d9b877957c52789e494aeee1ffd4d3128dd9e597 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Mon, 5 Mar 2018 19:27:06 +0800 Subject: web: create files/{acme,nginx} to organize files better --- roles/web/files/acme-client.sh | 117 --------------------- roles/web/files/acme/acme-client.sh | 117 +++++++++++++++++++++ roles/web/files/acme/deploy.sh | 21 ++++ roles/web/files/conf.d/security_headers.conf | 79 -------------- roles/web/files/conf.d/ssl.conf | 69 ------------ roles/web/files/deploy.sh | 21 ---- roles/web/files/nginx.conf | 94 ----------------- roles/web/files/nginx/conf.d/security_headers.conf | 79 ++++++++++++++ roles/web/files/nginx/conf.d/ssl.conf | 69 ++++++++++++ roles/web/files/nginx/nginx.conf | 94 +++++++++++++++++ roles/web/tasks/main.yml | 9 +- 11 files changed, 384 insertions(+), 385 deletions(-) delete mode 100755 roles/web/files/acme-client.sh create mode 100755 roles/web/files/acme/acme-client.sh create mode 100755 roles/web/files/acme/deploy.sh delete mode 100644 roles/web/files/conf.d/security_headers.conf delete mode 100644 roles/web/files/conf.d/ssl.conf delete mode 100755 roles/web/files/deploy.sh delete mode 100644 roles/web/files/nginx.conf create mode 100644 roles/web/files/nginx/conf.d/security_headers.conf create mode 100644 roles/web/files/nginx/conf.d/ssl.conf create mode 100644 roles/web/files/nginx/nginx.conf (limited to 'roles') diff --git a/roles/web/files/acme-client.sh b/roles/web/files/acme-client.sh deleted file mode 100755 index 1f4b15d..0000000 --- a/roles/web/files/acme-client.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/sh -# -# This script can be both used to request/obtain new certificate(s) from -# Let's Encrypt through ACME challenges: -# $ ./acme-client.sh -n -N -# to expand the domains listed in the certificate: -# $ ./acme-client.sh -e -# and be used to renew the obtained certificate(s) (default action): -# $ ./acme-client.sh -# which can be called by periodic(8). -# -# This script will be weekly executed in order to renew the certificate(s). -# See "/etc/periodic.conf". -# -# Output files: -# * .../etc/acme/privkey.pem : account private key -# * .../etc/ssl/acme/private/.pem : domain private key -# -# XXX/TODO: -# * How to remove/revoke a SAN from the certificate? -# -# -# Aaron LI -# 2017-04-19 -# - -umask 027 - -BASEDIR="/usr/local/etc/acme" -SSLDIR="/usr/local/etc/ssl/acme" -DOMAINSFILE="${BASEDIR}/domains.txt" -CHALLENGEDIR="/usr/local/www/acme/.well-known/acme-challenge" -# Default to show verbose information -VERBOSE="true" -# Additional arguments for "acme-client" -ARGS="" - - -usage() { - cat << _EOF_ -usage: -`basename $0` [-h] [-efLnNv] [-d domains.txt] - - -e : allow expanding the domains listed in the certificate - -f : force updating the certificate signature even if its too soon - -n : create a new 4096-bit RSA account key if one does not already exist - -N : create a new 4096-bit RSA domain key if one does not already exist - -q : be quiet (default to show verbose information) - - -d domains.txt : text file with one domain and its sub-domains per line - (default: ${DOMAINSFILE}) -_EOF_ -} - - -while getopts "efhnNqd:" opt; do - case "$opt" in - h) - usage - exit 1 - ;; - e) - ARGS="${ARGS} -e" - ;; - f) - ARGS="${ARGS} -F" - ;; - n) - ARGS="${ARGS} -n" - ;; - N) - ARGS="${ARGS} -N" - ;; - q) - VERBOSE="false" - ;; - d) - DOMAINSFILE="${OPTARG}" - ;; - [?]) - usage - exit 2 - ;; - esac -done - -if [ "${VERBOSE}" = "true" ]; then - ARGS="${ARGS} -v" -fi - -# HACK??? -[ ! -f "/etc/ssl/cert.pem" ] && \ - ln -sv /usr/local/etc/ssl/cert.pem /etc/ssl/cert.pem - -[ ! -d "${CHALLENGEDIR}" ] && mkdir -pv ${CHALLENGEDIR} -[ ! -d "${SSLDIR}/private" ] && mkdir -pvm700 "${SSLDIR}/private" - -printf "\n=== $(date) ===\n=== CMD: $0 $* ===\n" - -grep -v '^\s*#' "${DOMAINSFILE}" | while read domain line; do - printf "-------------------------------------------------------------\n" - printf "[${domain}] ${line}\n" - printf "-------------------------------------------------------------\n" - CERTSDIR="${SSLDIR}/${domain}" - [ ! -d "${CERTSDIR}" ] && mkdir -pm755 "${CERTSDIR}" - set +e # RC=2 when time to expire > 30 days - acme-client -b -C "${CHALLENGEDIR}" \ - -k "${SSLDIR}/private/${domain}.pem" \ - -c "${CERTSDIR}" \ - ${ARGS} \ - ${domain} ${line} - RC=$? - set -e - [ $RC -ne 0 -a $RC -ne 2 ] && exit $RC -done - -exit 0 diff --git a/roles/web/files/acme/acme-client.sh b/roles/web/files/acme/acme-client.sh new file mode 100755 index 0000000..1f4b15d --- /dev/null +++ b/roles/web/files/acme/acme-client.sh @@ -0,0 +1,117 @@ +#!/bin/sh +# +# This script can be both used to request/obtain new certificate(s) from +# Let's Encrypt through ACME challenges: +# $ ./acme-client.sh -n -N +# to expand the domains listed in the certificate: +# $ ./acme-client.sh -e +# and be used to renew the obtained certificate(s) (default action): +# $ ./acme-client.sh +# which can be called by periodic(8). +# +# This script will be weekly executed in order to renew the certificate(s). +# See "/etc/periodic.conf". +# +# Output files: +# * .../etc/acme/privkey.pem : account private key +# * .../etc/ssl/acme/private/.pem : domain private key +# +# XXX/TODO: +# * How to remove/revoke a SAN from the certificate? +# +# +# Aaron LI +# 2017-04-19 +# + +umask 027 + +BASEDIR="/usr/local/etc/acme" +SSLDIR="/usr/local/etc/ssl/acme" +DOMAINSFILE="${BASEDIR}/domains.txt" +CHALLENGEDIR="/usr/local/www/acme/.well-known/acme-challenge" +# Default to show verbose information +VERBOSE="true" +# Additional arguments for "acme-client" +ARGS="" + + +usage() { + cat << _EOF_ +usage: +`basename $0` [-h] [-efLnNv] [-d domains.txt] + + -e : allow expanding the domains listed in the certificate + -f : force updating the certificate signature even if its too soon + -n : create a new 4096-bit RSA account key if one does not already exist + -N : create a new 4096-bit RSA domain key if one does not already exist + -q : be quiet (default to show verbose information) + + -d domains.txt : text file with one domain and its sub-domains per line + (default: ${DOMAINSFILE}) +_EOF_ +} + + +while getopts "efhnNqd:" opt; do + case "$opt" in + h) + usage + exit 1 + ;; + e) + ARGS="${ARGS} -e" + ;; + f) + ARGS="${ARGS} -F" + ;; + n) + ARGS="${ARGS} -n" + ;; + N) + ARGS="${ARGS} -N" + ;; + q) + VERBOSE="false" + ;; + d) + DOMAINSFILE="${OPTARG}" + ;; + [?]) + usage + exit 2 + ;; + esac +done + +if [ "${VERBOSE}" = "true" ]; then + ARGS="${ARGS} -v" +fi + +# HACK??? +[ ! -f "/etc/ssl/cert.pem" ] && \ + ln -sv /usr/local/etc/ssl/cert.pem /etc/ssl/cert.pem + +[ ! -d "${CHALLENGEDIR}" ] && mkdir -pv ${CHALLENGEDIR} +[ ! -d "${SSLDIR}/private" ] && mkdir -pvm700 "${SSLDIR}/private" + +printf "\n=== $(date) ===\n=== CMD: $0 $* ===\n" + +grep -v '^\s*#' "${DOMAINSFILE}" | while read domain line; do + printf "-------------------------------------------------------------\n" + printf "[${domain}] ${line}\n" + printf "-------------------------------------------------------------\n" + CERTSDIR="${SSLDIR}/${domain}" + [ ! -d "${CERTSDIR}" ] && mkdir -pm755 "${CERTSDIR}" + set +e # RC=2 when time to expire > 30 days + acme-client -b -C "${CHALLENGEDIR}" \ + -k "${SSLDIR}/private/${domain}.pem" \ + -c "${CERTSDIR}" \ + ${ARGS} \ + ${domain} ${line} + RC=$? + set -e + [ $RC -ne 0 -a $RC -ne 2 ] && exit $RC +done + +exit 0 diff --git a/roles/web/files/acme/deploy.sh b/roles/web/files/acme/deploy.sh new file mode 100755 index 0000000..9c6fff2 --- /dev/null +++ b/roles/web/files/acme/deploy.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e +# +# Restart the services after renewing the certificate(s) to deploy the +# changed certificate(s). +# +# This script will be weekly executed. See "/etc/periodic.conf". +# +# Aaron LI +# + +# Services to be restarted after ACME certificate update +SERVICES="nginx dovecot postfix" + +for srv in ${SERVICES}; do + if service ${srv} status >/dev/null 2>&1; then + echo "ACME deploy: restarting ${srv} ..." + service ${srv} restart + else + echo "ACME deploy: service ${srv} not running" + fi +done diff --git a/roles/web/files/conf.d/security_headers.conf b/roles/web/files/conf.d/security_headers.conf deleted file mode 100644 index f4a7135..0000000 --- a/roles/web/files/conf.d/security_headers.conf +++ /dev/null @@ -1,79 +0,0 @@ -# -# /usr/local/etc/nginx/security_headers -# -# Security headers for Nginx/HTTP(s) -# -# Aaron LI -# 2017-11-22 -# -# Credits -# ------- -# * Hardening your HTTP response headers -# https://scotthelme.co.uk/hardening-your-http-response-headers/ -# * Nginx add_header configuration pitfall -# https://blog.g3rt.nl/nginx-add_header-pitfall.html -# * Nginx - ngx_http_headers_module - add_header -# https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header -# -# Tools -# ----- -# * Security Headers Analyzer -# https://securityheaders.io/ -# -# 2017-11-23: Be less paranoid, due to the reverse proxy services ... -# - -# -# NOTE: Use "always" for security headers. -# -# WARNING: The "add_header" directive (and some others) are inherited -# from the *previous* level *IF AND ONLY IF* there are NO -# "add_header" directives defined on the *current* level. -# Such behavior leads to the *pitfall* that the added headers -# may get *cleared*! In consequence, this common header -# configuration file *must* be included within every context -# that has "add_header" directives! -# - -# Instruct the client to force a HTTPS connection to the domain and all -# its subdomains for 2 year. -# See also: https://hstspreload.org/ -#add_header Strict-Transport-Security -# "max-age=63072000; includeSubdomains; preload" always; -add_header Strict-Transport-Security - "max-age=31536000; includeSubdomains" always; - -# The Content Security Policy (CSP) header allows to define a whitelist -# of approved sources of content for the site. By restricting the assets -# that a browser can load, CSP can act as an effective countermeasure to -# XSS attacks. -# -# Enforce TLS on all assets and prevent mixed content warnings. -add_header Content-Security-Policy - "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always; -# Only allow to load assets from self! -#add_header Content-Security-Policy "default-src 'self'" always; - -# The X-Frame-Options (XFO) header protects the visitors against -# clickjacking attacks. -# Only allow yourselves to frame your own site. -add_header X-Frame-Options "SAMEORIGIN" always; -# Do not allow the site to be framed at all! -#add_header X-Frame-Options "DENY" always; - -# Enable the cross-site scripting filter built into most browsers, and -# tell the browser to block the response if it detects an attack rather -# than sanitizing the script. -add_header X-XSS-Protection "1; mode=block" always; - -# Prevent a browser from trying to MIME-sniff the content type and forces -# it to stick with the declared content-type. -add_header X-Content-Type-Options "nosniff" always; - -# Allow a site to control how much information the browser includes with -# navigations away from a document. -# -# The browser will send the full URL to requests to the same origin, but -# only send the origin when requests are cross-origin. No information -# allowed to be sent when a scheme downgrade happens. -add_header Referrer-Policy "strict-origin-when-cross-origin" always; diff --git a/roles/web/files/conf.d/ssl.conf b/roles/web/files/conf.d/ssl.conf deleted file mode 100644 index acda0eb..0000000 --- a/roles/web/files/conf.d/ssl.conf +++ /dev/null @@ -1,69 +0,0 @@ -# -# /usr/local/etc/nginx/conf.d/ssl.conf -# -# SSL/TLS settings for Nginx -# -# Aaron LI -# 2017-04-25 -# -# Credits -# ------- -# * Cipherli.st - Strong Ciphers for Apache, nginx and Lighttpd -# https://cipherli.st/ -# * Strong SSL Security on nginx -# https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html -# * Mozilla - Security - Server Side TLS -# https://wiki.mozilla.org/Security/Server_Side_TLS -# https://mozilla.github.io/server-side-tls/ssl-config-generator/ -# * Let's Encrypt & Nginx -# https://letsecure.me/secure-web-deployment-with-lets-encrypt-and-nginx/ -# * Nginx SSL and TLS Deployment Best Practice -# https://www.linode.com/docs/web-servers/nginx/nginx-ssl-and-tls-deployment-best-practices -# * Best nginx configuration for improved security (and performance) -# https://gist.github.com/plentz/6737338 -# * Hardening your HTTP response headers -# https://scotthelme.co.uk/hardening-your-http-response-headers/ -# -# Tools -# ----- -# * Qualys SSL Labs SSL Server Test -# https://www.ssllabs.com/ssltest/ -# * Security Headers Analyzer -# https://securityheaders.io/ -# - - -# Diffie-Hellman group: -# $ openssl dhparam -out /usr/local/etc/ssl/dhparam2048.pem 2048 -# or even go with 4096-bit DH pool: -# $ openssl dhparam -out /usr/local/etc/ssl/dhparam4096.pem 4096 -# NOTE: This may take up to tens of minutes ... -#ssl_dhparam /usr/local/etc/ssl/dhparam2048.pem; -ssl_dhparam /usr/local/etc/ssl/dhparam4096.pem; - -# Only use the latest TLS protocols -# TLSv1.3 requires nginx >= 1.13 -#ssl_protocols TLSv1.2 TLSv1.3; -ssl_protocols TLSv1.2; -ssl_prefer_server_ciphers on; -# Credit: https://mozilla.github.io/server-side-tls/ssl-config-generator/ -ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; - -ssl_session_timeout 1d; -ssl_session_cache shared:SSL:50m; -# Credit: https://github.com/mozilla/server-side-tls/issues/135 -ssl_session_tickets off; - -# The Online Certificate Status Protocol (OCSP) was created to speed up -# the process that operating systems and browsers use to check for -# certificate revocation. -# Allow the server to send its cached OCSP record to the client during -# the TLS handshake, bypassing the OCSP responder and saving a roundtrip -# between the client and the OCSP responder. -# -# NOTE: If the "ssl_certificate" file does NOT contain intermediate -# certificates, the certificate of the server certificate issuer -# should be present in the "ssl_trusted_certificate" file. -# -ssl_stapling on; -ssl_stapling_verify on; diff --git a/roles/web/files/deploy.sh b/roles/web/files/deploy.sh deleted file mode 100755 index 9c6fff2..0000000 --- a/roles/web/files/deploy.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -e -# -# Restart the services after renewing the certificate(s) to deploy the -# changed certificate(s). -# -# This script will be weekly executed. See "/etc/periodic.conf". -# -# Aaron LI -# - -# Services to be restarted after ACME certificate update -SERVICES="nginx dovecot postfix" - -for srv in ${SERVICES}; do - if service ${srv} status >/dev/null 2>&1; then - echo "ACME deploy: restarting ${srv} ..." - service ${srv} restart - else - echo "ACME deploy: service ${srv} not running" - fi -done diff --git a/roles/web/files/nginx.conf b/roles/web/files/nginx.conf deleted file mode 100644 index 760ca02..0000000 --- a/roles/web/files/nginx.conf +++ /dev/null @@ -1,94 +0,0 @@ -# -# /usr/local/etc/nginx/nginx.conf -# DragonFly BSD -# -# -# References -# ---------- -# * A Guide to Caching with NGINX and NGINX Plus -# https://www.nginx.com/blog/nginx-caching-guide/ -# * Reverse Proxy with Caching -# https://www.nginx.com/resources/wiki/start/topics/examples/reverseproxycachingexample/ -# * Compression and Decompression -# https://www.nginx.com/resources/admin-guide/compression-and-decompression/ -# * Nginx location priority -# https://stackoverflow.com/a/5238430/4856091 -# * Nginx add_header configuration pitfall -# https://blog.g3rt.nl/nginx-add_header-pitfall.html -# -# Tools -# ----- -# * Qualys SSL Labs SSL Server Test -# https://www.ssllabs.com/ssltest/ -# * Security Headers Analyzer -# https://securityheaders.io/ -# * KeyCDN HTTP/2 Test -# https://tools.keycdn.com/http2-test -# -# -# Aaron LI -# 2017-04-16 -# - -worker_processes 1; - -events { - worker_connections 1024; -} - - -http { - include mime.types; - default_type application/octet-stream; - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - - # Compression - gzip on; - gzip_types text/plain application/xml; # text/html always compressed - gzip_proxied no-cache no-store private expired auth; - gzip_min_length 1000; - - # Don't show the Nginx version number (in error pages / headers) - server_tokens off; - - # SSL/TLS settings - include conf.d/ssl.conf; - - # Security headers - # - # WARNING: The "add_header" directive (and some others) are inherited - # from the *previous* level *IF AND ONLY IF* there are NO - # "add_header" directives defined on the *current* level. - # Such behavior leads to the *pitfall* that the added headers - # may get *cleared*! In consequence, this common header - # configuration file *must* be included within every context - # that has "add_header" directives! - # - include conf.d/security_headers.conf; - - # Proxy Caching - # - # This setup a cache zone named "CACHE" given 10 MB for metadata storage, - # maximum 1 GB for cached contents which will be cleared after 24 hours - # without access. - # - # NOTE: The `proxy_cache_path` directive must be placed in `http` context. - # - # NOTE: The caching is not efficient since the traffic is rather low. - # So disable caching to save a bit memory. - # - #proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m - # inactive=24h max_size=1g use_temp_path=off; - #proxy_cache_valid 200 302 60m; - #proxy_cache_valid any 1m; - #proxy_cache_use_stale error timeout invalid_header updating - # http_500 http_502 http_503 http_504; - #add_header X-Cache-Status $upstream_cache_status; - - # Site-specific settings - include sites/*.conf; -} diff --git a/roles/web/files/nginx/conf.d/security_headers.conf b/roles/web/files/nginx/conf.d/security_headers.conf new file mode 100644 index 0000000..f4a7135 --- /dev/null +++ b/roles/web/files/nginx/conf.d/security_headers.conf @@ -0,0 +1,79 @@ +# +# /usr/local/etc/nginx/security_headers +# +# Security headers for Nginx/HTTP(s) +# +# Aaron LI +# 2017-11-22 +# +# Credits +# ------- +# * Hardening your HTTP response headers +# https://scotthelme.co.uk/hardening-your-http-response-headers/ +# * Nginx add_header configuration pitfall +# https://blog.g3rt.nl/nginx-add_header-pitfall.html +# * Nginx - ngx_http_headers_module - add_header +# https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header +# +# Tools +# ----- +# * Security Headers Analyzer +# https://securityheaders.io/ +# +# 2017-11-23: Be less paranoid, due to the reverse proxy services ... +# + +# +# NOTE: Use "always" for security headers. +# +# WARNING: The "add_header" directive (and some others) are inherited +# from the *previous* level *IF AND ONLY IF* there are NO +# "add_header" directives defined on the *current* level. +# Such behavior leads to the *pitfall* that the added headers +# may get *cleared*! In consequence, this common header +# configuration file *must* be included within every context +# that has "add_header" directives! +# + +# Instruct the client to force a HTTPS connection to the domain and all +# its subdomains for 2 year. +# See also: https://hstspreload.org/ +#add_header Strict-Transport-Security +# "max-age=63072000; includeSubdomains; preload" always; +add_header Strict-Transport-Security + "max-age=31536000; includeSubdomains" always; + +# The Content Security Policy (CSP) header allows to define a whitelist +# of approved sources of content for the site. By restricting the assets +# that a browser can load, CSP can act as an effective countermeasure to +# XSS attacks. +# +# Enforce TLS on all assets and prevent mixed content warnings. +add_header Content-Security-Policy + "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always; +# Only allow to load assets from self! +#add_header Content-Security-Policy "default-src 'self'" always; + +# The X-Frame-Options (XFO) header protects the visitors against +# clickjacking attacks. +# Only allow yourselves to frame your own site. +add_header X-Frame-Options "SAMEORIGIN" always; +# Do not allow the site to be framed at all! +#add_header X-Frame-Options "DENY" always; + +# Enable the cross-site scripting filter built into most browsers, and +# tell the browser to block the response if it detects an attack rather +# than sanitizing the script. +add_header X-XSS-Protection "1; mode=block" always; + +# Prevent a browser from trying to MIME-sniff the content type and forces +# it to stick with the declared content-type. +add_header X-Content-Type-Options "nosniff" always; + +# Allow a site to control how much information the browser includes with +# navigations away from a document. +# +# The browser will send the full URL to requests to the same origin, but +# only send the origin when requests are cross-origin. No information +# allowed to be sent when a scheme downgrade happens. +add_header Referrer-Policy "strict-origin-when-cross-origin" always; diff --git a/roles/web/files/nginx/conf.d/ssl.conf b/roles/web/files/nginx/conf.d/ssl.conf new file mode 100644 index 0000000..acda0eb --- /dev/null +++ b/roles/web/files/nginx/conf.d/ssl.conf @@ -0,0 +1,69 @@ +# +# /usr/local/etc/nginx/conf.d/ssl.conf +# +# SSL/TLS settings for Nginx +# +# Aaron LI +# 2017-04-25 +# +# Credits +# ------- +# * Cipherli.st - Strong Ciphers for Apache, nginx and Lighttpd +# https://cipherli.st/ +# * Strong SSL Security on nginx +# https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html +# * Mozilla - Security - Server Side TLS +# https://wiki.mozilla.org/Security/Server_Side_TLS +# https://mozilla.github.io/server-side-tls/ssl-config-generator/ +# * Let's Encrypt & Nginx +# https://letsecure.me/secure-web-deployment-with-lets-encrypt-and-nginx/ +# * Nginx SSL and TLS Deployment Best Practice +# https://www.linode.com/docs/web-servers/nginx/nginx-ssl-and-tls-deployment-best-practices +# * Best nginx configuration for improved security (and performance) +# https://gist.github.com/plentz/6737338 +# * Hardening your HTTP response headers +# https://scotthelme.co.uk/hardening-your-http-response-headers/ +# +# Tools +# ----- +# * Qualys SSL Labs SSL Server Test +# https://www.ssllabs.com/ssltest/ +# * Security Headers Analyzer +# https://securityheaders.io/ +# + + +# Diffie-Hellman group: +# $ openssl dhparam -out /usr/local/etc/ssl/dhparam2048.pem 2048 +# or even go with 4096-bit DH pool: +# $ openssl dhparam -out /usr/local/etc/ssl/dhparam4096.pem 4096 +# NOTE: This may take up to tens of minutes ... +#ssl_dhparam /usr/local/etc/ssl/dhparam2048.pem; +ssl_dhparam /usr/local/etc/ssl/dhparam4096.pem; + +# Only use the latest TLS protocols +# TLSv1.3 requires nginx >= 1.13 +#ssl_protocols TLSv1.2 TLSv1.3; +ssl_protocols TLSv1.2; +ssl_prefer_server_ciphers on; +# Credit: https://mozilla.github.io/server-side-tls/ssl-config-generator/ +ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; + +ssl_session_timeout 1d; +ssl_session_cache shared:SSL:50m; +# Credit: https://github.com/mozilla/server-side-tls/issues/135 +ssl_session_tickets off; + +# The Online Certificate Status Protocol (OCSP) was created to speed up +# the process that operating systems and browsers use to check for +# certificate revocation. +# Allow the server to send its cached OCSP record to the client during +# the TLS handshake, bypassing the OCSP responder and saving a roundtrip +# between the client and the OCSP responder. +# +# NOTE: If the "ssl_certificate" file does NOT contain intermediate +# certificates, the certificate of the server certificate issuer +# should be present in the "ssl_trusted_certificate" file. +# +ssl_stapling on; +ssl_stapling_verify on; diff --git a/roles/web/files/nginx/nginx.conf b/roles/web/files/nginx/nginx.conf new file mode 100644 index 0000000..760ca02 --- /dev/null +++ b/roles/web/files/nginx/nginx.conf @@ -0,0 +1,94 @@ +# +# /usr/local/etc/nginx/nginx.conf +# DragonFly BSD +# +# +# References +# ---------- +# * A Guide to Caching with NGINX and NGINX Plus +# https://www.nginx.com/blog/nginx-caching-guide/ +# * Reverse Proxy with Caching +# https://www.nginx.com/resources/wiki/start/topics/examples/reverseproxycachingexample/ +# * Compression and Decompression +# https://www.nginx.com/resources/admin-guide/compression-and-decompression/ +# * Nginx location priority +# https://stackoverflow.com/a/5238430/4856091 +# * Nginx add_header configuration pitfall +# https://blog.g3rt.nl/nginx-add_header-pitfall.html +# +# Tools +# ----- +# * Qualys SSL Labs SSL Server Test +# https://www.ssllabs.com/ssltest/ +# * Security Headers Analyzer +# https://securityheaders.io/ +# * KeyCDN HTTP/2 Test +# https://tools.keycdn.com/http2-test +# +# +# Aaron LI +# 2017-04-16 +# + +worker_processes 1; + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + + # Compression + gzip on; + gzip_types text/plain application/xml; # text/html always compressed + gzip_proxied no-cache no-store private expired auth; + gzip_min_length 1000; + + # Don't show the Nginx version number (in error pages / headers) + server_tokens off; + + # SSL/TLS settings + include conf.d/ssl.conf; + + # Security headers + # + # WARNING: The "add_header" directive (and some others) are inherited + # from the *previous* level *IF AND ONLY IF* there are NO + # "add_header" directives defined on the *current* level. + # Such behavior leads to the *pitfall* that the added headers + # may get *cleared*! In consequence, this common header + # configuration file *must* be included within every context + # that has "add_header" directives! + # + include conf.d/security_headers.conf; + + # Proxy Caching + # + # This setup a cache zone named "CACHE" given 10 MB for metadata storage, + # maximum 1 GB for cached contents which will be cleared after 24 hours + # without access. + # + # NOTE: The `proxy_cache_path` directive must be placed in `http` context. + # + # NOTE: The caching is not efficient since the traffic is rather low. + # So disable caching to save a bit memory. + # + #proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m + # inactive=24h max_size=1g use_temp_path=off; + #proxy_cache_valid 200 302 60m; + #proxy_cache_valid any 1m; + #proxy_cache_use_stale error timeout invalid_header updating + # http_500 http_502 http_503 http_504; + #add_header X-Cache-Status $upstream_cache_status; + + # Site-specific settings + include sites/*.conf; +} diff --git a/roles/web/tasks/main.yml b/roles/web/tasks/main.yml index c1d6b17..d554db1 100644 --- a/roles/web/tasks/main.yml +++ b/roles/web/tasks/main.yml @@ -30,7 +30,7 @@ - name: nginx - copy conf.d/ config directory copy: - src: conf.d/ # trailing '/' -> directory contents + src: nginx/conf.d/ # trailing '/' -> directory contents dest: /usr/local/etc/nginx/conf.d/ - name: nginx - create sites/ directory @@ -43,7 +43,7 @@ - name: nginx - copy nginx.conf copy: - src: nginx.conf + src: nginx/nginx.conf dest: /usr/local/etc/nginx/nginx.conf # XXX: Validation runs aganist a temporary file, thus nginx fails to # include other config files! @@ -69,9 +69,8 @@ src: "{{ item }}" dest: /usr/local/etc/acme/{{ item | basename }} mode: 0755 - with_items: - - acme-client.sh - - deploy.sh + with_fileglob: + - "acme/*.sh" - name: (local) acme - check account private key existence become: false -- cgit v1.2.2