How To Secure Nginx with a Free Let's Encrypt SSL Certificate on Ubuntu
Published on September 4, 2026

Introduction
Let's Encrypt is a Certificate Authority that provides free, automated SSL/TLS certificates. With the Certbot client you can obtain a certificate, configure Nginx and set up automatic renewal in a few minutes.
In this guide we will use Certbot to obtain an SSL certificate for a domain served by Nginx on Ubuntu, then verify that automatic renewal works.
Prerequisites
To follow this tutorial, you need:
- An Ubuntu 20.04 or 22.04 server with a
sudouser and theufwfirewall enabled. - A registered domain name. This guide uses
your_domainas an example; replace it with your own. - Two DNS records pointing at your server's public IP: an A record for
your_domainand an A record forwww.your_domain. - Nginx installed with a server block for
your_domain. If you have not done that yet, see How To Install Nginx on Ubuntu.
Step 1 — Installing Certbot
Certbot is under very active development, so the package in Ubuntu's default repository tends to be outdated. The recommended way to install it today is through snap, which ships with Ubuntu.
Make sure snapd is up to date:
sudo snap install core; sudo snap refresh coreIf you previously installed Certbot through apt, remove it to avoid conflicts:
sudo apt remove certbotInstall Certbot:
sudo snap install --classic certbotLink the certbot command so it can be run from anywhere:
sudo ln -s /snap/bin/certbot /usr/bin/certbotCheck it:
certbot --versionOutput
certbot 2.9.0Step 2 — Confirming Nginx's Configuration
Certbot needs to find the correct server block in your Nginx configuration to configure SSL automatically. It does that by looking for a server_name directive that matches the domain you request a certificate for.
Open the server block file for your domain:
sudo nano /etc/nginx/sites-available/your_domainFind the server_name line and make sure it looks like this:
...
server_name your_domain www.your_domain;
...If it does, exit the editor. If you had to change it, test the syntax and reload Nginx:
sudo nginx -t
sudo systemctl reload nginxStep 3 — Allowing HTTPS Through the Firewall
If ufw is enabled, check its current status:
sudo ufw statusOutput
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)Only HTTP (port 80) is open. To allow HTTPS (port 443) as well, enable the Nginx Full profile and remove the now redundant Nginx HTTP profile:
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'Check again:
sudo ufw statusOutput
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)Step 4 — Obtaining an SSL Certificate
Certbot offers several ways to obtain a certificate. The Nginx plugin reconfigures Nginx and reloads it whenever necessary. Run the following, listing every domain you want covered with -d flags:
sudo certbot --nginx -d your_domain -d www.your_domainOn the first run Certbot asks for your email address (for expiry notices) and asks you to agree to the terms of service. It then contacts the Let's Encrypt server and runs a challenge to verify that you control the domain before issuing the certificate.
If everything succeeds, you will see something like:
Output
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 2026-12-03.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for your_domain to /etc/nginx/sites-enabled/your_domain
Successfully deployed certificate for www.your_domain to /etc/nginx/sites-enabled/your_domain
Congratulations! You have successfully enabled HTTPS on https://your_domain and https://www.your_domainCertbot has edited your server block: it added listen 443 ssl, the certificate paths, and a block that redirects all HTTP traffic to HTTPS. Open the configuration to see the result:
sudo cat /etc/nginx/sites-available/your_domainserver {
server_name your_domain www.your_domain;
root /var/www/your_domain/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/your_domain/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
}
server {
if ($host = www.your_domain) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = your_domain) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
return 404; # managed by Certbot
}Open https://your_domain in your browser. You should see the padlock icon in the address bar. For a deeper check, run the Qualys SSL Labs Server Test; Certbot's default configuration usually scores an A.
Step 5 — Verifying Automatic Renewal
Let's Encrypt certificates are valid for 90 days, which is meant to encourage automated renewal. The snap-installed Certbot ships a systemd timer that runs twice a day and renews any certificate that is within 30 days of expiry.
Check that the timer is active:
sudo systemctl list-timers | grep certbotOutput
Thu 2026-09-04 23:07:00 UTC 9h left Thu 2026-09-04 11:07:00 UTC 3h ago snap.certbot.renew.timer snap.certbot.renew.serviceTo be sure renewal works, do a dry run (nothing is actually renewed):
sudo certbot renew --dry-runOutput
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Processing /etc/letsencrypt/renewal/your_domain.conf
Simulating renewal of an existing certificate for your_domain and www.your_domain
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/your_domain/fullchain.pem (success)If you see no errors, you are done. When the time comes, Certbot renews the certificate and reloads Nginx to pick up the new one. If renewal ever fails, Let's Encrypt emails a warning to the address you provided before the certificate expires.
Useful Certbot Commands
List the certificates issued on this server:
sudo certbot certificatesAdd a new domain to an existing certificate:
sudo certbot --nginx -d your_domain -d www.your_domain -d blog.your_domainRevoke and delete a certificate:
sudo certbot delete --cert-name your_domainConclusion
You have installed Certbot, obtained a free SSL certificate from Let's Encrypt, configured Nginx to redirect to HTTPS and confirmed automatic renewal. Your entire site is now encrypted at no cost. If you run into trouble, check the log at /var/log/letsencrypt/letsencrypt.log.
