Linux VPS

Secure Nginx with a free Let's Encrypt SSL certificate

Install Certbot, issue a free certificate for your domain, redirect HTTP to HTTPS and make sure renewal runs on its own.

BeginnerLinux server2 min read

Let's Encrypt issues free, trusted TLS certificates. Certbot requests them, configures Nginx for HTTPS and renews them before they expire.

Before you start

  • Nginx serves your site over HTTP with a server_name that matches your domain. See Install Nginx.
  • Your domain's A record (and AAAA, if you use IPv6) points at the server. Check with dig +short example.com.
  • Ports 80 and 443 are open in your firewall. Let's Encrypt connects on port 80 to verify you control the domain.

1. Install Certbot

Ubuntu and Debian:

Bash
sudo apt install -y certbot python3-certbot-nginx

AlmaLinux and Rocky Linux get it from EPEL:

Bash
sudo dnf install -y epel-release
sudo dnf install -y certbot python3-certbot-nginx

2. Request the certificate

List every name the certificate should cover with -d:

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

Certbot asks for an email address for expiry warnings and for you to accept the terms. If it asks whether to redirect HTTP to HTTPS, choose redirect. It then edits your server block and reloads Nginx.

Open https://example.com. The browser should show a padlock.

3. Make sure renewal is automatic

Certificates last 90 days. Certbot installs a timer that renews them well before expiry. Check it:

Bash
systemctl list-timers | grep -i certbot

On AlmaLinux and Rocky the timer may need enabling:

Bash
sudo systemctl enable --now certbot-renew.timer

Then test a renewal without changing anything:

Bash
sudo certbot renew --dry-run

Add more names later

Run the same command with the full list of names, old and new. Certbot offers to expand the existing certificate:

Bash
sudo certbot --nginx -d example.com -d www.example.com -d shop.example.com

Warning: Let's Encrypt limits how many certificates you can request for the same names in a short time. While you experiment, use --dry-run (or --staging) so failed attempts do not count against the real limit.

Troubleshooting

  • Challenge failed / timeout: port 80 is blocked or the domain does not point at this server yet. Check dig +short example.com and your firewall.
  • "Could not automatically find a matching server block": the server_name in Nginx does not include the exact names you passed with -d.
  • Renewal dry run fails: something changed since the first request, often port 80 being closed or a redirect rule blocking /.well-known/acme-challenge/.
  • See your certificates: sudo certbot certificates lists names and expiry dates.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.