How to Secure Nginx with Let’s Encrypt on Ubuntu 22.04

4 min read

This guide shows you how to secure Nginx with a free SSL certificate from Let’s Encrypt on Ubuntu 22.04 using Certbot. By the end, your site will serve traffic over HTTPS with automatic certificate renewal.

Prerequisites

  • An Ubuntu 22.04 server with a public IP — follow How to Deploy EC2 Ubuntu 22.04 LTS on AWS if you need one
  • Nginx installed and running
  • A domain name with DNS A records pointing to your server’s public IP (both example.com and www.example.com)
  • Port 80 and 443 open in your firewall or security group

Step 1: Set Up Your Nginx Server Block

Before requesting a certificate, Certbot needs to find your domain in the Nginx configuration. If you haven’t already, create a server block for your domain:

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

Add a basic configuration:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html index.php;
}

Enable the site and test the configuration:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

If nginx -t shows errors, fix them before continuing. Certbot will fail if Nginx can’t reload.

Step 2: Install Certbot via Snap

The Certbot team recommends installing via snap instead of apt. The snap package stays up to date automatically and is the officially supported method.

Remove any old Certbot packages

If you previously installed Certbot through apt, remove it first to avoid conflicts:

sudo apt remove certbot -y

Install Certbot with the Nginx plugin

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
  • snap install --classic certbot — installs Certbot with full system access (needed to modify Nginx configs and write certificates)
  • ln -s — creates a symlink so you can run certbot from anywhere

Step 3: Obtain and Install the SSL Certificate

Run Certbot with the --nginx plugin. This automatically verifies your domain, gets the certificate, updates your Nginx config, and sets up an HTTP-to-HTTPS redirect:

sudo certbot --nginx -d example.com -d www.example.com --non-interactive --agree-tos --no-eff-email --redirect -m you@example.com
  • -d — the domain names to secure (include both root and www)
  • --non-interactive — runs without prompts
  • --agree-tos — accepts the Let’s Encrypt terms of service
  • --no-eff-email — skips the EFF newsletter signup
  • --redirect — adds a 301 redirect from HTTP to HTTPS automatically
  • -m — email address for renewal notices and urgent security alerts

If successful, you’ll see output like:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem

Step 4: Verify the Nginx Configuration

Certbot modifies your server block automatically. Open it to confirm the SSL directives were added:

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

You should see a block like this for HTTPS:

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    root /var/www/example.com;
    index index.html index.php;
}

And a redirect block for HTTP:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Test and reload:

sudo nginx -t && sudo systemctl reload nginx

Step 5: Test HTTPS and Auto-Renewal

Open https://example.com in your browser. You should see the padlock icon confirming HTTPS is active. Also try http://example.com to verify it redirects to HTTPS.

Let’s Encrypt certificates expire every 90 days. The Certbot snap package includes a systemd timer that checks for renewal twice a day. Test that it works:

sudo certbot renew --dry-run

If the dry run completes without errors, renewal is working. No cron job needed — the snap handles it.

Troubleshooting

Common issues and quick fixes:

  • “Could not automatically find a matching server block” — your server_name in the Nginx config doesn’t match the -d domain you passed to Certbot. Fix the config and reload Nginx before retrying.
  • “Problem binding to port 80” — another process is using port 80, or Nginx isn’t running. Check with sudo ss -tlnp | grep :80.
  • “DNS problem: NXDOMAIN” — your domain’s A record doesn’t point to this server’s IP yet. Verify DNS propagation with dig example.com.
  • Rate limits — Let’s Encrypt allows 5 duplicate certificates per domain per week. If you hit this limit during testing, wait or use the --staging flag to test without rate limits.

Conclusion

Your Nginx server now serves traffic over HTTPS with a free Let’s Encrypt certificate that renews automatically. If you’re also running Apache on other servers, see How to Secure Apache2 with Let’s Encrypt on Ubuntu 22.04. For a full WordPress setup behind Nginx with SSL, check out How to Install WordPress on EC2 Ubuntu 22.04.