Let’s Encrypt + Nginx is simple easy!
Look, it’s 2020, and if your site isn’t provided under SSL/TLS then you are behind even the least sophisticated scammers out there.
Here is a quick walk through on using certbot
from
Let’s Encrypt, that provides easy to acquire, and
even renew your certificates if you’re using Nginx.
NOTE: These directions are geared toward Fedora users, but this is literally just as easy on Ubuntu, Arch, Gentoo, etc.
Direct DNS
One way Let’s Encrypt verifies you are the owner of a domain/site is they issue a challenge. To do this, Let’s Encrypt calls the domain submitted and looks for a specific answer. To ensure this works, you need to register your domain, and have the domain directed to your server. I host my server and DNS on DigitalOcean.com. My DNS record for this is
A example.utahcon.dev 159.203.86.63 300
AAAA example.utahcon.dev 2604:a880:800:a1::118:1001 300
Install the packages
Of course you need nginx
and certbot
installed for this to work.
Additionally you need to include the python-certbot
which depending on which
version of python you run on your server, you’ll need either python2-certbot
or python3-certbot
. I am running python 3.x.
$ sudo dnf install nginx certbot python3-certbot
Create static page
in /var/www/html/index.html
or any other directory you really want to use.
<!DOCTYPE html>
<html>
<head>
<title>example.utahcon.dev -- secured<title>
</head>
<body>
<p>example.utahcon.dev -- secured</p>
</body>
</html>
Configure nginx
Now we tell nginx where we want it to find this file, and how to serve it.
Fedora keeps things nice and clean so we will create a file under
/etc/nginx/conf.d/
called example.utahcon.dev.conf
. Literally you can name your
file anything, as long as it ends in .conf
.
First, let’s start by telling nginx where to listen for requests for our page:
listen 80;
listen [::]:80;
listen 443 ssl;
We also want to tell nginx the name of our server (incase we decide to host multiple sites on this server):
server_name example.utahcon.dev;
Now, when calls come in, how should nginx handle them? We want it to simple
serve up the static files in /var/www/html
, so we tell it the root
, and we
want it to automatically serve the index.html
page if no other page is
requested:
root /var/www/html;
index index.html;
When we put all this together in the server
declaration for nginx we get
this:
server {
listen 80;
listen [::]]:80;
listen 443 ssl;
server_name example.utahcon.dev;
root /var/www/html;
index index.html;
}
Get a cert
So the power of certbot
is that we can use it to call Let’s Encrypt, and make
a request for a certificate, accept a challenge, and return a challenge answer.
Additionally, it will update the nginx configuration for us!
Simply run:
$ sudo cerbot --nginx -d example.utahcon.dev
Your output might vary slightly, but you should see something like this:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.utahcon.dev
nginx: [warn] could not build optimal types_hash, you should increase either types_hash_max_size: 2048 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
Waiting for verification...
Cleaning up challenges
nginx: [warn] could not build optimal types_hash, you should increase either types_hash_max_size: 2048 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
Deploying Certificate to VirtualHost /etc/nginx/conf.d/example.utahcon.dev.conf
nginx: [warn] could not build optimal types_hash, you should increase either types_hash_max_size: 2048 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Here certbot is asking if we want to add a redirect, forcing traffic from port 80 to port 443. This is strongly suggested BTW.
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/example.utahcon.dev.conf
nginx: [warn] could not build optimal types_hash, you should increase either types_hash_max_size: 2048 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://example.utahcon.dev
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=example.utahcon.dev
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/example.utahcon.dev/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/example.utahcon.dev/privkey.pem
Your cert will expire on 2020-07-12. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
You can see that certbot was successful in obtaining a key, and placing it where it needs to be, and if we look at our configuration file now it will have changed slightly:
server {
listen 443 ssl;
server_name example.utahcon.dev;
root /var/www/html;
index index.html;
if ( $scheme != "https" ){
return 301 https://$host$request_uri;
}
ssl_certificate /etc/letsencrypt/live/example.utahcon.dev/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.utahcon.dev/privkey.pem; # managed by Certbot
if ($host = example.utahcon.dev) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.utahcon.dev;
return 404; # managed by Certbot
}
Now if you hit up your example.utahcon.dev
you’ll get a working page that is
forced through SSL\TLS.
Renewing Certs
Let’s Encrypt certificates have short shelf lives, just 90 days. This limits damage from compromised keys, or mis-issuance. It also encourages automation because humans hate having to do things every 90-days (like changing passwords or SSL keys).
However, the good folks at Let’s Encrypt built this into certbot too! We simply
need to tell certbot to run periodically to check for renewals. So we are going
to add the following to /etc/crontab
0 0 * * * root /usr/bin/certbot renew --post-hook "systemctl reload nginx"
This runs certbot, which checks renewals, and if needed updates keys, and then reload nginx.
That’s it!
Unless you ran into issues with SELinux, or firewalls, you should be all setup and running now. Let me know if you have questions, or if there is something here that isn’t accurate. Happy hosting!