OpenSSL & Cert9 min read

How to Set Up HTTPS on Nginx with Let's Encrypt

Step-by-step guide to enabling HTTPS on Nginx using Let's Encrypt and Certbot — installation, certificate generation, auto-renewal, HTTP to HTTPS redirect, and security header configuration.

This guide walks through enabling HTTPS on an Nginx server using Let's Encrypt and Certbot — from installation to auto-renewal and security headers. By the end, your site will have a valid TLS certificate that renews automatically.

Prerequisites

  • Ubuntu 20.04+ or Debian 11+ server
  • Nginx installed and serving your site on port 80
  • A domain pointing to your server's IP (A record)
  • Port 80 and 443 open in your firewall

Step 1: Install Certbot

sudo apt update
sudo apt install certbot python3-certbot-nginx

Step 2: Obtain a Certificate

Certbot can configure Nginx automatically. Run with the --nginx flag and specify your domains:

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot will: verify domain ownership via HTTP challenge, obtain the certificate, and modify your Nginx config to enable HTTPS with a redirect from HTTP.

For a wildcard certificate (covers all subdomains), use the DNS challenge instead:

sudo certbot certonly --manual --preferred-challenges dns \
  -d "*.yourdomain.com" -d "yourdomain.com"
# You'll need to add a TXT DNS record to your domain

Step 3: Verify Your Nginx Config

After Certbot runs, your Nginx server block will look similar to this:

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

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

    root /var/www/html;
    index index.html;
    location / { try_files $uri $uri/ =404; }
}

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;  # Redirect HTTP → HTTPS
}

Step 4: Test and Reload Nginx

sudo nginx -t          # Test config for syntax errors
sudo systemctl reload nginx  # Apply changes

Step 5: Verify Auto-renewal

Certbot installs a systemd timer that runs twice daily. Test that it works:

sudo certbot renew --dry-run  # Simulates renewal without making changes
sudo systemctl status certbot.timer  # Check timer is active

Certificates will auto-renew when they have less than 30 days remaining.

Step 6: Add Security Headers

Add these headers to your Nginx config for a better security posture:

server {
    # ... SSL config from above ...

    # HSTS — tell browsers to always use HTTPS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Prevent clickjacking
    add_header X-Frame-Options "SAMEORIGIN" always;

    # Prevent MIME type sniffing
    add_header X-Content-Type-Options "nosniff" always;

    # Control referrer information
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

Checking Your SSL Configuration

# Check certificate details and expiry
openssl s_client -connect yourdomain.com:443 -showcerts 2>/dev/null | openssl x509 -noout -dates

# Check which TLS versions are supported
nmap --script ssl-enum-ciphers -p 443 yourdomain.com

You can also test your configuration at SSL Labs (ssllabs.com/ssltest/) for a detailed security report and grade.

TRY THE FREE TOOL

OpenSSL Command Builder

Build OpenSSL commands visually without memorizing syntax

Open Tool →
N

Nattapon Tonapan

Developer & creator of FreeUtil. Building free tools for developers and Thai users.

About the author →

RELATED ARTICLES

OpenSSL & Cert7 min read

SSL Certificate Types Explained: PEM, DER, PKCS12, and More

OpenSSL & Cert8 min read

How to Create a Self-signed SSL Certificate for Local Development

OpenSSL & Cert7 min read

What is a CSR? How to Generate and Submit a Certificate Signing Request

← Back to all articles