Let's Encrypt
At this stage, we will consider how to obtain free certificates from Let's Encrypt on Ubuntu 20.04 to create a secure connection. We will also complete the configuration file setup for Nginx to connect to the previously downloaded website "online store" via the https protocol on your domain name.
Let's Encrypt is a certificate authority (CA) that provides an affordable way to obtain and install free TLS/SSL certificates, thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing the Certbot software client, which attempts to automate most (if not all) of the required steps. Currently, the entire process of obtaining and installing the certificate is fully automated for both Apache and Nginx.
In this guide, you will use Certbot to obtain a free SSL certificate for Nginx on Ubuntu and set up automatic certificate renewal.
We will consider the separate configuration file for Nginx created for your domain name that was made in the previous step!
Step 1 — Installing Certbot
Certbot recommends using their snap package for installation. Snap packages work on almost all Linux distributions, but their installation is required first to manage snap packages. Ubuntu comes with snap support out of the box, so you can start by checking the snap kernel's relevance:
sudo snap install core; sudo snap refresh core
If you are working on a server that previously had an old version of Certbot installed, you should remove it before proceeding:
sudo apt remove certbot
After that, you can install the certbot package:
sudo snap install --classic certbot
Finally, you can link the certbot command from the snap installation directory to your path, so you can run it by simply typing certbot. This is not necessary for all packages, but snap packages are generally less intrusive by default, so they do not accidentally conflict with other system packages:
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Now that Certbot is installed, let's run it to obtain our certificate.
Step 2 — Confirming the Nginx configuration
Certbot must be able to find the correct server block in your Nginx configuration in order to automatically configure SSL. Specifically, it does this by looking for the server_name directive that matches the domain for which you are requesting a certificate.
In the previous step of configuring Nginx, we set up the server block your_domain; let's assume it will be called example.com, and for you, it should be your domain name!
Installing and configuring Nginx
To verify, open your domain's configuration file using nano or your favorite text editor:
sudo nano /etc/nginx/sites-available/example.com
Here and everywhere else, example.com, you should replace with your domain name!
Find the existing server_name line. It should look like this:
...
server_name example.com www.example.com;
...
If so, exit the editor and proceed to the next step.
Step 3 — Allowing HTTPS through the firewall
If you have the UFW firewall enabled, as recommended in the prerequisites guides, you will need to configure the settings to allow HTTPS traffic. Fortunately, Nginx registers several profiles upon UFW installation.
Current settings can be viewed by entering:
sudo ufw status
It will likely look something like this, which means that only HTTP traffic is allowed on the web server:
Output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
To additionally allow HTTPS traffic, enable the Nginx Full profile and remove the redundant allowance of the Nginx HTTP profile:
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
Now your status should look like this:
sudo ufw status
Output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
Next, we will run Certbot and obtain our certificates.
Step 4 — Obtaining an SSL certificate
Certbot provides many ways to obtain SSL certificates through plugins. The Nginx plugin will take care of reconfiguring Nginx and reloading the configuration if necessary. To use this plugin, enter the following:
sudo certbot --nginx -d example.com -d www.example.com
It runs certbot with the --nginx plugin, which allows you to specify the domain names for which the certificate should be valid using -d.
When you run the command, you will be prompted to enter your email address and agree to the terms of service. After this, you should see a message indicating the successful completion of the process and where your certificates are stored:
Output
IMPORTANT NOTES:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem
Key is saved at: /etc/letsencrypt/live/your_domain/privkey.pem
This certificate expires on 2022-06-01.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
Your certificates have been uploaded, installed, and loaded, and your Nginx configuration will now automatically redirect all web requests to https://. Try reloading your site and pay attention to your browser's security indicator. It should indicate that the site is securely protected, usually with a lock icon. If you test your server using the SSL Labs Server Test, it will receive an A rating.
Let's finish testing the update process.
Step 5 — Checking the automatic renewal of Certbot
Let's Encrypt certificates are only valid for ninety days. This is done to encourage users to automate the certificate renewal process. The certbot package that we installed took care of this for us by adding a systemd timer that will run twice a day and automatically renew any certificate that is expiring within thirty days.
You can check the status of the timer using systemctl:
sudo systemctl status snap.certbot.renew.service
version certbot 3.X.X
sudo systemctl status snap.certbot.renew.timer
Output
○ snap.certbot.renew.service - Service for snap application certbot.renew
Loaded: loaded (/etc/systemd/system/snap.certbot.renew.service; static)
Active: inactive (dead)
TriggeredBy: ● snap.certbot.renew.timer
snap.certbot.renew.timer - Timer renew for snap application certbot.renew
Loaded: loaded (/etc/systemd/system/snap.certbot.renew.timer; enabled; preset: enabled)
Active: active (waiting) since Wed 2025-01-15 10:22:57 UTC; 6min ago
Trigger: Wed 2025-01-15 22:04:00 UTC; 11h left
Triggers: ● snap.certbot.renew.service
To test the update process, you can perform a trial run using certbot:
sudo certbot renew --dry-run
If you do not see any errors, everything is ready. If necessary, Certbot will update your certificates and reload Nginx to apply the changes. If the automatic renewal process ever fails, Let's Encrypt will send a message to the email address you provided, warning you that your certificate is about to expire.
To ensure Certbot automatically renews certificates every 3 months, the http and https ports must be open on the server!
Step 6 — Completing the server configuration
In the previous stages, we installed Docker and Docker Compose on the server. We created the installation file docker-compose.yml. With the docker-compose.yml file, we learned to deploy the online store application and its database. We set up a proxy server and configured it to use the domain name. We also created an encrypted connection for our domain name using the https protocol, with automatic issuance and renewal of free certificates.
Now we need to configure our previously created Nginx server block to connect it with our website application "online store."
Open the configuration file for your domain using nano or your favorite text editor:
sudo nano /etc/nginx/sites-available/example.com
Here and everywhere else, example.com, you should replace with your domain name!
You will see that certbot has added information about the certificates being used here:
...
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
...
Now your task is to modify the server block configuration as shown below; the only thing you cannot change is the lines above that were generated by certbot!
server {
listen 80;
listen [::]:80;
server_name example.com;
# For update Certbot
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri; # Redirement to HTTPS
}
}
server {
server_name example.com;
#Domain check
if ($http_host != "example.com") {
return 403;
}
#Your code lines issued Setbot
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Don't forget, in the example provided, to replace example.com everywhere with your domain name. The block highlighted in green must contain the certificate data issued by your certbot in the previous steps!
Next, check for any syntax errors in the Nginx files:
sudo nginx -t
If there are no issues, restart Nginx for the changes to take effect:
sudo systemctl restart nginx
If you have done everything correctly, then when entering the URL address of your domain:
http://your_domain
The page of your instance of the site "online store" installed on your server will open!