How to Set Up an Nginx Certbot

If you are looking to automate the process of obtaining, installing, and updating TLS/SSL certificates on your web server, then Let’s Encrypt is a very useful tool. It is a certificate authority (CA) that comes packaged with a corresponding software client, Certbot, that will automatically install TLS/SSL certificates. This means that you can run encrypted HTTPS on a web server without having to worry about constant maintenance.

Right now, Certbot is able to fully automate the process of obtaining and installing a certificate using the two most commonly used web servers: Nginx and Apache. Which of these you are using will depend on your personal preference and needs, but for those coming to this topic for the first time, I recommend looking at the differences between Nginx and Apache to work out which one is best for you.

In this tutorial, I will show you how to use Certbot to automatically download, configure, and renew certificates from Let’s Encrypt, a free and open certificate authority developed by the Internet Security Research Group, and which is trusted by almost all web browsers in use today.

 

What We Will Do

In this tutorial, we are going to install Certbot and then use it to get a free SSL certificate for Nginx on Ubuntu 22.04. We will also set up this certificate to renew automatically, so you don’t have to spend hours maintaining it. We will then test the system to make sure that everything is running smoothly.

The best practice for doing this is to use a separate Nginx server block file, rather than the default Nginx file. Setting up a distinct server block file for each domain helps to avoid a number of common mistakes, and it also means that if anything goes wrong, you will have the default block file as a backup.

 

Prerequisites

Before starting this tutorial, you are going to need a few things. To my mind, the best solution to using your Ubuntu setup as a HTTPS server is to use a LEMP stack, and this is what I’m using in the following tutorial. I know that some people prefer a different setup, however, so I’ll list the absolute minimum requirements here:

  • First, an Ubuntu 22.04 server set up and running. You will also need this server to have a sudo non-root user, and an operational firewall.
  • A registered, working, and tested domain name. In this tutorial, I’m going to use example.com. There are plenty of ways to get a domain name cheaply, or even for free, or you can just use your existing registrar.
  • For your domain name, you are going to need to set up two DNS records. One should be an A record with example.com pointing to your server’s public IP, and the other another A record with example.com pointing to the same place.
  • Once you have all this, go ahead and install Nginx on your server. This is pretty straightforward, but there are plenty of guides available if you get stuck. Make sure, when you install Nginx, that you also have a server block for your domain. In this tutorial, I will use /etc/nginx/sites-available/example.com as my example, but install the server block wherever is easiest for you.

Keep in mind that Nginx can also be used as a proxy server within your network environment. If you are using a proxy configuration, it complicates the SSL setup process but can still be done with Let’s Encrypt. To secure external traffic from end to end, you will need to obtain two separate SSL certificates.

The first one, which will be used between external browsers and your Nginx proxy, must come from a certificate authority like Let’s Encrypt. The secondary certificate will encode the traffic between your proxy server and the back-end application server that responds to the request. This secondary certificate can be set up as a self-signed internal SSL certificate. Just make sure you add the “proxy_ssl_trusted_certificate” attribute to your Nginx configuration file.

 

Step 1: Install Certbot

Once you’ve got everything I’ve described, the first step is to install Certbot on your server. This will allow you to get an SSL certificate to use with Let’s Encrypt. Here are two ways to install Certbot on Ubuntu 22.04 LTS server:
(If you don’t like using Snap packages, you can remove Snap on Ubuntu 22.04 LTS.)

Using snap:

Certbot recommends using their snap package for installation. Snap packages are compatible with almost all Linux distributions, but prior to managing snap packages, you need to ensure that snapd is installed. Ubuntu 22.04 includes built-in support for snaps, so you can start by verifying that your snapd core is up to date with the following commands:

sudo snap install core ; sudo snap refresh core

If you are working on a server that previously had an older version of Certbot installed, it’s advisable to remove it before proceeding:

sudo apt remove certbot

Afterward, you can install the Certbot package using the following command:

sudo snap install --classic certbot

Finally, you can create a symbolic link for the Certbot command from the snap installation directory to your system’s path. This step ensures that you can run Certbot by simply typing “certbot” without any issues, as snaps are designed to minimize conflicts with other system packages:

sudo ln -s /snap/bin/certbot /usr/bin/certbot

Now that Certbot is installed move to step 2.

 

Using apt:

To install, run the following command :

sudo apt update; sudo apt install certbot python3-certbot-nginx

Verify that Certbot is installed and working properly:

certbot --version

You should see the version number of Certbot that you just installed:

certbot 1.21.0

And that’s it for now. You should have an installation of Certbot ready to use. However, in order for it to get SSL certificates for you, you are going to have to configure Nginx. Luckily, this is also pretty straightforward.

 

Step 2: Configure and Confirm Nginx

In order for Certbot to obtain and maintain SSL certificates for you, it needs to know where your server block is. The way it does this is to look for a server_name tag, and compare it to the domain that you are requesting a CA for. If you’ve installed Nginx with standard options, this should already be working. However, it’s good practice to check this before you go on to the next step.

First, find your server block and open it using your favorite text editor, again as su. I use vi, but you can also use nano:

sudo vi /etc/nginx/sites-available/example.com

With the file open, look or search for the server_name line. It should look like this:

server_name example.com www.example.com;

If it does, good.

If it doesn’t, you are going to have to tell Nginx where to look. To do so, update the line to point it to the right domain. Then, save and close the document. This should be all you have to do, but it is worth checking at this point that everything is well. You can check that your edits make sense to Nginx by running it from the command line:

sudo nginx -t

If you get an error, something went wrong. The most likely source is a typo in your own edits, so go back and check the file for those. Once you’ve got this command running with no errors, you can move on.

The next step is to restart Nginx so it will use the correct server block. To do this, you will need to make a system call. Run this command:

sudo systemctl reload nginx

At this point, Nginx should report that it found the correct server block.

So far so good.

 

Step 3: Allow HTTPS Traffic Through your Firewall

The next step is to allow HTTPS traffic through your existing firewall. This step will be a little different depending on which firewall you have, and how you have it configured. I would recommend, however, using ufw, because it plays nicely with Nginx, and this is the firewall that most Nginx installation guides recommend. This is largely because Nginx will register a few profiles with ufw when it is installed, which makes your life a whole lot easier.

You can check your current ufw settings directly from the command line, so go ahead and do that:

sudo ufw status

The output should look something like this:

Ubuntu firewall ufw

As you can see, at the moment, only HTTP traffic is allowed through your server, so you need to tell ufw to allow HTTPS through. Nginx already comes with a profile that will allow this, so all you need to do is enable it:

sudo ufw allow 'Nginx Full'

Then disable the obsolete Nginx HTTP profile by deleting it:

sudo ufw delete allow 'Nginx HTTP'

To check that these commands worked, you can verify the configuration settings for ufw in the same way as before. Run the same status command:

sudo ufw status

And you should see that the output has changed, so now HTTPs is permitted:

Status: active
To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

So you should now have Nginx installed, with a ufw setup that will allow HTTPs traffic through.

 

Step 4: Get an SSL Certificate

Certbot offers a few ways of getting SSL certificates, all of which run through plugins. The advantage of getting an SSL certificate in this way is that the plugin will take care of reconfiguring Nginx, and then reloading it, without you having to do anything.

I know, however, that some of you might want to increase the level of security offered by the standard method of key exchange available through Let’s Encrypt. For most of you, this will not be necessary, and you can skip to the next paragraph. However, if you want to secure your key exchange, you can, for instance, generate a Diffie-Hellman group at this point and secure your key exchange channel using this key. There are plenty of guides available on how to do this for those who are extra conscious about security, but in this tutorial, I will stick to the standard methods for key exchange.

To run the Nginx plugin for Certbot, use this command:

$ sudo certbot --nginx -d example.com -d www.example.com

Here, you are running Certbot with the –nginx tag to tell it to use the plugin and adding a -d tag in order to tell it which domains you want the certificate to be valid for.

If you are following this tutorial, this will probably be the first time you’ve run Certbot, and so it will prompt you for an email address and ask you to agree to its terms of service:

Let’s Encrypt

Once you’re past that, Certbot will contact the Let’s Encrypt server and ask you to verify that you own the domain that you are requesting a CA for.

Hopefully, all will go smoothly. The next step is to configure your HTTPs settings, and Certbot will prompt you to do so using the following output:

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.

——————————————————————————-

1: No redirect – Make no further changes to the web server 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):

Which of these options you choose will depend on your own needs, but if you are setting up a new site I’d recommend going with “2.” Whichever you select, Certbot will then reload Nginx to implement the new settings. It will then tell you where your certificates are stored:

certbot

If you’ve reached this point, your certificates should be downloaded, stored, and loaded. You can test if this is the case, though, by simply reloading your website and looking for the green ‘lock’ symbol. You should also notice that your domain name is now https://. One final check is to use a security check like that at SSL Labs Server Test, and check your security assessment. If your certificates are all up and running, it should return an “A” grade.

Technically, you should now have everything in place to run HTTPs through Nginx, with Certbot managing your SSL certificates. I will show you how to test that in just a minute, but before I do it is worth pointing out that the same process I’ve described here can be used to install, configure and maintain CAs on a wide variety of third-party server providers. A good example of this is Amazon’s popular EC2 service.

The process of setting up Nginx and Certbot to work with your EC2 server is essentially the same as with your own Ubuntu server. It is here, in fact, that Certbot really proves its worth, because the security configuration of EC2 servers can otherwise be quite complex, and the security of EC2 servers is particularly critical, given the ubiquity of AWS in the cloud share market: AWS/EC2 powers nearly 20% of the web, including many popular website builders like Wix and Squarespace.

 

Step 5: Verifying Auto-Renewal for Certbot

The final step in installing any new software is to check that it works. This is particularly critical when setting up Certbot, because the certificates it downloads from Let’s Encrypt are only valid for 90 days. This is partially to keep the certificates secure, but also acts to encourage users to automate their security renewal process. Happily, Certbot already comes with a script to automate this.

If you are curious, you can look at the script: it’s in /etc/cron.d. There, you can see that the script will run automatically twice a day, and will attempt to renew any certificate that is due to expire in the next 30 days.

This should mean that Certbot will automatically keep your CAs up to date. However, you can check that everything is working properly by running the following command:

sudo certbot renew --dry-run

Though the output of this command is not that helpful in itself, if it completes with no errors you can be certain that Certbot will renew your certificates when needed. If it is unable to do so, it will send you an email (to the address you gave it above) to warn you that something went wrong.

 

Next Steps and Extra Security

For most of us, the standard setup offered through Certbot and Nginx will offer a good level of security and adaptability. However, for some applications, a few further configuration steps may be required. If you want to allow an A+ SSL rating, for instance, Certbot will allow you to configure this also.

If you’ve followed the tutorial above, you should see that your server blocks contain these lines, which Certbot has generated:

ssl_certificate /etc/letsencrypt/live/YOUR-DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR-DOMAIN/privkey.pem;

This is great for most purposes, but there is a stronger configuration using OCSP stapling, which requires that each virtual host needs a trusted SSL certificate as well. To enable this, add this line after those above:

ssl_trusted_certificate /etc/letsencrypt/live/YOUR-DOMAIN/chain.pem;

After this, you will need to edit the shared SSL settings, which should be stored in /etc/letsencrypt/options-ssl-nginx.conf. Open this config file, and replace the contents to tell Nginx that you want to use stapling:

ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1d;
ssl_session_tickets off;

 

ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;

 

ssl_stapling on;
ssl_stapling_verify on;

 

add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload;";
add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none'; script-src 'self'; img-src 'self'; style-src 'self'; base-uri 'self'; form-action 'self';";
add_header Referrer-Policy "no-referrer, strict-origin-when-cross-origin";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

Save, exit, and restart Nginx, and you should be up to an A+ security rating. You can check this by running another test through the SSL Labs Server Test.

Beyond this, there are plenty of further steps you can take to make your system completely impregnable, such as using content-specific features like Content Security Policy and Subresource Integrity or even Brotli compression to replace gzip.

 

Final Thoughts

That’s it! You should now have a website secured through SSL certificates that Certbot downloaded from Let’s Encrypt, and these will be automatically updated when needed. Nginx, which you can tune even more if you like, is using these certificates, and Certbot will automatically update it when required. That’s the end of this tutorial, but certainly not the end of what you can do with Certbot, which has many applications beyond this quite simple setup. To have a look at just what the program can do, take a look at the Certbot documentation – you may be pleasantly surprised.

 

Guest post by Samuel Bocetta – a freelance journalist specializing in U.S. diplomacy and national security, with emphasis on technology trends in cyberwarfare, cyberdefense, and cryptography. Samuel is a former defense contractor for the Navy. Now a security analyst and freelance correspondent for a number of media outlets. – bocetta.com

 

Published: September 25th, 2019 | Updated: October 2nd, 2023

 

Tags: , ,

Discussion

  1. What if nginx is inside a docker container and everything is set up by docker compose? This is a common case in many installation guides.

  2. If Nginx is running inside a Docker container and your entire web server setup with Docker Compose, there are a few adjustments. Here’s how you can adapt the process outlined in the article for this common scenario:

    1. Docker Compose Configuration:
    • Make sure your Nginx container is defined in your docker-compose.yml file. You would typically have a service for Nginx and another for your application.
    • Ensure that the Nginx container is linked to your application container so that Nginx can route requests to your application.
    1. Port Mapping:
    • When defining the Nginx service in the docker-compose.yml file, map the ports appropriately. For example, if your Nginx container exposes port 80 for HTTP and 443 for HTTPS, map those ports to the host.
    1. Volumes:
    • Use Docker volumes to share the SSL certificates with the Nginx container. This ensures that your SSL certificates remain persistent even if the Nginx container is restarted.
    1. Nginx Configuration:
    • Inside the Nginx container, you should have a custom Nginx configuration file. This file should be mounted as a volume from your host machine or a volume container. This configuration file should specify the SSL certificate paths and other Nginx settings.
    1. Certbot and Renewal:
    • To use Certbot within a Dockerized Nginx setup, you would typically run Certbot in a separate container or use a Certbot image. When you run Certbot, it should be aware of the Nginx container, and it should share the necessary volumes for the SSL certificates.
    • To automate the certificate renewal process, you can create a cron job within a separate container that runs Certbot to renew the certificates as needed.
    1. Firewall Rules:
    • Ensure that your Docker host has the necessary firewall rules to allow traffic on ports 80 and 443, which are required for Let’s Encrypt’s challenges.

    The main difference is in how you handle the configuration and integration within the Docker ecosystem, but the core principles of SSL certificate management and Nginx setup remain the same.

    Let me know if/how you are able to get this to work



Top ↑