Obtaining a Let's Encrypt Certificate and Configuring Nginx on Port 443

Securing your website with HTTPS is essential for trust, SEO, and data protection. Let's Encrypt provides free, automated, and trusted SSL/TLS certificates. Combined with Certbot and Nginx, you can enable HTTPS on port 443 quickly - and forget about it. Certificates renew automatically, so you only set it up once.

Key Benefit: Unlike commercial CAs, Let's Encrypt automates renewal. Once configured, your site stays secure without manual intervention - get it, set it, forget it.

Install Certbot

Update your system and install Certbot:

sudo apt update
sudo apt install certbot -y

Using the Webroot Method

We'll use the webroot plugin to validate domain ownership without stopping or reconfiguring Nginx. Certbot will place challenge files in a special directory (.well-known/acme-challenge) that must be publicly accessible via HTTP.

To avoid repeating long command-line options, create a configuration file:

sudo nano /etc/letsencrypt/cli.ini

Add the following (adjust as needed):

# /etc/letsencrypt/cli.ini
email = me@example.com
rsa-key-size = 2048
agree-tos = true
non-interactive = true
preferred-challenges = http

Prepare Nginx for ACME Challenges

Certbot needs to serve challenge files from:

http://example.com/.well-known/acme-challenge/

Create the directory and add a test file:

sudo mkdir -p /var/www/html/.well-known/acme-challenge
sudo echo "Success" > /var/www/html/.well-known/acme-challenge/example.html

To avoid repeating the same location block for every site, create a reusable Nginx snippet:

sudo nano /etc/nginx/acme

Add:

location ^~ /.well-known/acme-challenge/ {
    root /var/www/html;
    default_type "text/plain";
    try_files $uri =404;
}

Include this snippet in your server block before other location directives:

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

Reload Nginx and test access:

sudo nginx -t && sudo systemctl reload nginx
curl -I http://example.com/.well-known/acme-challenge/example.html

You should get a 200 OK response. Remove the test file afterward:

sudo rm /var/www/html/.well-known/acme-challenge/example.html

Register with Let's Encrypt (Optional)

Registration is optional but recommended for expiration reminders:

sudo certbot register --email admin@example.com --agree-tos --no-eff-email

Obtain the SSL Certificate

First, test the process in dry-run mode (no rate limits):

sudo certbot certonly --dry-run -d example.com -d www.example.com

If successful, request the real certificate:

sudo certbot certonly -d example.com -d www.example.com

Certificates are saved to:

/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem
Note: If you missed a domain, just re-run the command with all domains (including the original ones). Certbot will update the certificate.

Configure Nginx for HTTPS (Port 443)

Update your server block to listen on port 443 and serve the SSL certificate:

server {
    include acme;
    listen 80;
    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;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 127.0.0.1 8.8.8.8 valid=300s;
    resolver_timeout 5s;

    root /var/www/html;
    index index.html;
}
  • fullchain.pem = certificate + intermediate CA
  • privkey.pem = private key
  • chain.pem = intermediate certificate (used for stapling)

Test and reload Nginx:

sudo nginx -t && sudo systemctl reload nginx

Visit https://example.com - your site is now secure!

Automatic Certificate Renewal

Let's Encrypt certificates expire every 90 days. But renewal is fully automated.

On Debian-based systems, Certbot sets up a cron job or systemd timer. If not, add this to your root crontab:

sudo crontab -e

Add:

42 */12 * * * certbot renew --quiet --allow-subset-of-names

This runs twice daily. The --allow-subset-of-names flag ensures renewal continues even if one domain in a multi-domain cert fails validation.

Randomize the minute: To avoid server load spikes across the web, pick a random minute (0-59) instead of 42.

Verify Your Certificate

Check certificate details:

sudo openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -text -noout

Or use online tools like SSL Labs to test your configuration.

Security Impact: Reducing Your Attack Surface

Enabling HTTPS is a key step in attack surface reduction. Unencrypted HTTP exposes data, enables tampering, and increases the risk of interception.

By securing port 443 with a trusted certificate, you:

  • Protect user data in transit
  • Prevent downgrade attacks
  • Improve trust and compliance
  • Reduce exposure to passive eavesdropping

As noted in Wikipedia, minimizing exposed services (like unsecured HTTP) is a fundamental security principle. Tools like Shodan can scan for exposed HTTP services - make sure yours isn't one of them.

See Also

Published on Aug 19, 2025