Hassle free SSL with NGINX

Nginx is a reverse proxy and web-server which can handle SSL connections for your applications and web content. It is actually very easy to get SSL up an running for free with Let’s Encrypt as your certification authority. Even if you can’t or don’t want to use Nginx as your main web-server, your can simply terminate all SSL connections there and then connect locally via HTTP to your hosted applications.

Certbot

Certbot does most of the work for you, it’s basically a client for certificate authority servers. In our example we will use ACME, which means Certbot will place a magic file in our web-space which the CA-server can then query and therefore confirm that a certain DNS belongs to this server.

Installing should, usually, work via the package manager:

apt install certbot

If everything else fails, you can install Certbot via the python package manager:

python3 -m pip install cerbot

Preparing Nginx

Make sure Nginx is available via HTTP. Be careful if you have an HTTPS redirect, while most CAs will connect fine over HTTP (since they must assume you don’t have a certificate yet), some will not connect over a broken HTTPS connection, i.e. with an expired or self-signed certificate. If it is not yet installed, install Nginx with:

apt install nginx

You need the location /.well-known/acme-challenge/, this location must be writable for Nginx.

# inside ALL servers in sites-enabled/ or nginx.conf # 
# sites-enabled/ sometimes called vhosts.d/ or vservers.d/ #
location /.well-known/acme-challenge/ {
alias /var/www/.well-known/acme-challenge/;
}
set permissions and reload

Run Certbot

Run certbot and follow the instructions:

certbot certonly --webroot -w /var/www -d domain.toplevel -d domain2.toplevel --rsa-key-size 2048

..and you are done! Certbot will suggest you a command line which you can add to your crontab for regular certificate renewal. Let’s Encrypt certificates are valid for 3 months, executing the renewal jobs every months will be safe. Don’t forget to also add a systemctl reload nginx to the crontab or the certificates won't be reloaded.

Add SSL-configuration in Nginx

The following lines must be added to the http-block or into all server-blocks you want to use SSL. The location will be different if you don’t use Let’s Encrypt (which is the default though):

ssl_certificate /etc/letsencrypt/live/domain.toplevel/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.toplevel/privkey.pem;

Also, you must add an SSL-listen directive to the relevant server blocks:

listen 443 ssl; # ipv4
listen [::]:443 ssl; # ipv6

Common pitfalls

HTTPS redirect

If you employ a HTTP->HTTPS redirect on your page, make sure to place the acme-location block before the redirect or your renewal might fail, if your certificate ever becomes invalid for whatever reason.

nginx ACME-server-block

Basic-Auth/Deny-Directives

If you have basic auth or a deny-directive on one of your (sub-)domains you must disable those in the acme-location block:

auth_basic off;
allow all;

Adding new Subdomains

If you ever want to add more subdomains, add an --expand to the Certbot command, otherwise Certbot will create/symlink the new certificate with another name (something like domain.toplevel.002). Changing the initial domain will also cause Certbot to symlink certificates under a different name.

run certbot

Feel free to share your thoughts or ask a question!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Yannik Schmidt

Python programmer at heart, Linux Expert at work, GameDev on my good days, web developer on the bad days.