How to get a free SSL certificate with Certbot and Nginx on Ubuntu 24
Certbot with Nginx is the usual way to put a free Let’s Encrypt SSL certificate on an Ubuntu server: Certbot gets the certificate, writes the HTTPS lines into your site’s config and renews it on schedule. This guide follows the instructions on certbot.eff.org for Ubuntu 24.04 and 22.04. It also lists the errors people run into most and what each one means.
What you need before you start
- A domain whose A record (and AAAA record, if it has one) points to this server. Let’s Encrypt checks the domain from the internet.
- Nginx with a site whose
server_namenames that domain. If you don’t have one yet, see how to install Nginx on Ubuntu. - Ports 80 and 443 open. Let’s Encrypt connects on port 80 to check that the domain is yours.
If UFW is on (its status says Status: active), allow Nginx on both ports:
sudo ufw allow 'Nginx Full'
sudo ufw statusOn a cloud server, open ports 80 and 443 in the provider’s firewall or security group too. UFW doesn’t control that one.
Install Certbot with snap
certbot.eff.org recommends the snap package: it is always the current version and renews certificates on its own. Ubuntu has snap built in. The first command removes an older Certbot installed from apt, if there is one. Your certificates in /etc/letsencrypt/ stay where they are.
sudo apt remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
certbot --versionThe link puts the certbot command on the usual path. If apt says Package 'certbot' is not installed, so not removed, there was nothing to remove.
Run Certbot with Nginx
Name every domain the certificate should cover with its own -d. On the first run Certbot asks for an email address and for you to accept the Let’s Encrypt terms.
sudo certbot --nginx -d example.com -d www.example.comCertbot finds the server block with that server_name, adds the certificate lines and a redirect from HTTP to HTTPS, and reloads Nginx. At the end it reports Successfully received certificate and Successfully deployed certificate. Open https://example.com: the browser shows the padlock.
If you’d rather edit the Nginx config yourself, run this instead. Certbot then only gets the certificate and leaves your files alone:
sudo certbot certonly --nginxCheck that the certificate renews
Let’s Encrypt certificates last 90 days, and Let’s Encrypt plans to shorten that to 45 days over the next years. The snap package installs a systemd timer that runs certbot twice a day and renews any certificate close to expiry. Run a test renewal once and see the timer:
sudo certbot renew --dry-run
systemctl list-timers | grep certbotThe test should end with Congratulations, all simulated renewals succeeded. It talks to the Let’s Encrypt test server and changes nothing.
Since June 2025 Let’s Encrypt no longer emails reminders before a certificate expires. Now and then check each certificate’s expiry date with: sudo certbot certificates
Where Certbot keeps its files
/etc/letsencrypt/live/example.com/: the current certificate. Nginx readsfullchain.pemandprivkey.pemfrom here./etc/letsencrypt/renewal/example.com.conf: how this certificate renews./var/log/letsencrypt/letsencrypt.log: the full log of every run.- All certificates, their domains and expiry dates:
sudo certbot certificates
Keep privkey.pem private: anyone who has it can pretend to be your site. Don’t copy it to other servers or into a Git repository.
If Certbot fails
Could not automatically find a matching server block for example.com. Set the server_name directive to use the Nginx installer.: the certificate was issued, but no site has that name. Addserver_name example.com;to your site and check the config:sudo nginx -tReload Nginx, then install the saved certificate:sudo certbot install --cert-name example.comTimeout during connect (likely firewall problem): Let’s Encrypt couldn’t reach port 80. Check UFW and the cloud provider’s firewall, and that Nginx is running.DNS problem: NXDOMAIN looking up A for example.com: the domain has no A record yet, or the new record hasn’t spread. Check it at your DNS provider and try again later. A stale AAAA record pointing elsewhere causes failures too.too many certificateswithalready issued for this exact set of identifiers: Let’s Encrypt issues at most 5 certificates for the same set of names in 7 days. Wait, and test changes with--dry-run, which doesn’t count.- For any other error, read the end of
/var/log/letsencrypt/letsencrypt.log.
If you also work on a Mac

System Junk in MacWashing finds the caches of every app it knows, including those hidden inside app data, plus logs, Xcode junk and leftovers of deleted apps. It shows how much each takes and clears them in one go. Anything debatable stays unchecked until you decide.
Free trial · macOS 14 or later
Questions and answers
How do I use Certbot with Nginx?
Install Certbot: sudo snap install --classic certbot Then run: sudo certbot --nginx -d example.com It gets the certificate, edits your Nginx site and sets up renewal.
Is a Let’s Encrypt certificate really free?
Yes. Let’s Encrypt is a nonprofit certificate authority and doesn’t charge for certificates. Browsers trust them the same way as paid ones.
Do I need to renew the certificate by hand?
No. The Certbot timer renews it before it expires and reloads Nginx. Run this once to make sure renewal works: sudo certbot renew --dry-run