Nginx as reverse proxy with acme (letsencrypt): Difference between revisions
m (Replaced openssl with libressl) |
m (→Installation: Fixed broken link) |
||
Line 5: | Line 5: | ||
== Installation == | == Installation == | ||
For this howto, we need three tools: [[NGINX]], {{pkg|acme-client}} and {{pkg|libressl}} (to generate [https://wiki.openssl.org/index.php/Diffie-Hellman_parameters Diffie–Hellman Parameters]). | For this howto, we need three tools: [[Nginx|NGINX]], {{pkg|acme-client}} and {{pkg|libressl}} (to generate [https://wiki.openssl.org/index.php/Diffie-Hellman_parameters Diffie–Hellman Parameters]). | ||
{{Cmd|apk add nginx acme-client libressl}} | {{Cmd|apk add nginx acme-client libressl}} |
Revision as of 07:06, 9 December 2017
Introduction
This setup will allow you to have multiple servers/containers accessible via a single IP address with the added benefit of a centralized generation of letsencrypt certificates and secure https (according to ssllabs ssltest). Be aware that you first need to setup a regular HTTP server in order to be able to generate your HTTPS certificates and keys. After you have generated them, you can then add your HTTPS host based configuration.
Installation
For this howto, we need three tools: NGINX, acme-client and libressl (to generate Diffie–Hellman Parameters).
apk add nginx acme-client libressl
Setup
NGINX HTTP
Global configuration
First step is to refactor our global nginx.conf
. Its target at a low traffic http server, to increase performance make changes at top level.
The security settings are taken from https://cipherli.st. Please also read https://hstspreload.org for details about HSTS.
# ngnix configuration file user nginx; worker_processes 1; # use "auto" to use all available cores (high performance) events { worker_connections 1024; # increase if you need more connections } http { # server_names_hash_bucket_size controls the maximum length # of a virtual host entry (ie the length of the domain name). server_names_hash_bucket_size 64; server_tokens off; # hide who we are sendfile off; # can cause issues # secure nginx according to https://cipherli.st/ ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000"; # https://hstspreload.org add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; ssl_dhparam dhparam.pem; # nginx will find this file in the config directory set at nginx build time include mime.types; #fallback in case we can't determine a type default_type application/octet-stream; # buffering causes issues proxy_buffering off; # include hosts include conf.d/*.conf; }
Diffie–Hellman Parameters
In the above configuration ssl_dhparam is used, so we need to generate a global dhparam
file. We want to use a 4096 key size, but this can take a very long time. Because of this, we are adding an extra option (dsaparam) to generate our dhparam
file (see this wiki section):
openssl dhparam -dsaparam -out /etc/nginx/dhparam.pem 4096
At this point, you should be able to (re)start your nginx server, but it will not use any of the security features yet.
Per site configuration files (conf.d)
Since Alpine v3.5, we ship NGINX with a default.conf
within the /etc/nginx/conf.d directory.
To add support for another website, you can add files with the .conf extension to this directory:
Contents of /etc/nginx/conf.d/alpinelinux.org.conf
Common configuration includes
If you need to setup multiple proxy setups, you can include duplicated data such as shown below:
/etc/nginx/conf.d/proxy_set_header.inc:
proxy_set_header X-Forwarded-By $server_addr:$server_port; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host;
acme-client
To allow NGINX to support https, we need to add certificates and support for ACME (Automatic Certificate Management Environment) responses.
ACME responses
/etc/nginx/conf.d/acme.inc:
location /.well-known/acme-challenge { alias /var/www/acme; }
And add this to your proxy configuration:
/etc/nginx/conf.d/alpinelinux.org.conf
server { listen 80; server_name alpinelinux.org; include conf.d/acme.inc; location / { include conf.d/proxy_set_header.inc; proxy_pass http://downstream_http_server_host; } }
Automatic generation of certificates
Create the following file:
Contents of /etc/periodic/weekly/acme-client
Make it executable:
chmod +x /etc/periodic/weekly/acme-client
This script will run weekly to verify whether one of your certificates is outdated and renew them when needed.
If you have several domains, you can add them to the hosts= variable with a space between each domain. This will create a separate certificate and key for each:
hosts="alpinelinux.org example.com foo.org bar.io"
Initial generation of keys and certificates
To create your initial certificates and keys, you have to run this manually the first time:
/etc/periodic/weekly/acme-client
Watch the output and see if all goes well. When it's finished, you should have files in:
/etc/ssl/acme/alpinelinux.nl/fullchain.pem /etc/ssl/acme/private/alpinelinux.org/privkey.pem
NGINX HTTPS
Per site HTTPS configuration
Add the following below the previous HTTP configuration:
/etc/nginx/conf.d/alpinelinux.org.conf
server { listen 443 ssl; server_name alpinelinux.org ssl on; ssl_certificate /etc/ssl/acme/alpinelinux.org/fullchain.pem; ssl_certificate_key /etc/ssl/acme/private/alpinelinux.org/privkey.pem; location / { include conf.d/proxy_set_header.inc; proxy_pass http://downstream_http_server_host; } }
Redirect HTTP to HTTPS
Create the following file:
Contents of /etc/nginx/conf.d/redirect_http.inc
Update host configuration
/etc/nginx/conf.d/alpinelinux.org.conf
server { listen 80; server_name alpinelinux.org; include conf.d/acme.inc; include conf.d/redirect_http.inc; }
Complete host example with IPv6 support
/etc/nginx/conf.d/alpinelinux.org.conf
# alpinelinux.org server { listen 80; listen [::]:80; server_name alpinelinux.org; include conf.d/acme.inc; include conf.d/redirect_http.inc; } server { listen 443 ssl; listen [::]:443 ssl; server_name alpinelinux.org; ssl on; ssl_certificate /etc/ssl/acme/alpinelinux.org/fullchain.pem; ssl_certificate_key /etc/ssl/acme/private/alpinelinux.org/privkey.pem; location / { include conf.d/proxy_set_header.inc; proxy_pass http://downstream_http_server_host; } }