Independent hosting operator since 2014 · New York · Dallas · Amsterdam Status Looking Glass Contact
D4 NetworksD4 Networks
Client area Deploy a server
Home / Resources / Serve your site over HTTPS with Nginx and Let's Encrypt

Tutorials

Serve your site over HTTPS with Nginx and Let's Encrypt

Jun 7, 2026 · 8 min read

A free certificate from Let's Encrypt takes about five minutes to set up and renews itself after that. This guide covers a plain website and a reverse proxy in front of an app.

1. Point your domain at the server first

Certificates are issued only after Let's Encrypt confirms that the domain points at your server. Create both records at your DNS provider before you start:

your DNS provider
example.com     A       203.0.113.10
example.com     AAAA    2001:db8:1:2::1

Use your server's own addresses, which are shown on your service page. Check that they resolve before continuing:

your machine
$ dig example.com A +short
$ dig example.com AAAA +short

2. Install Nginx and open the web ports

Ubuntu and Debian
$ sudo apt update && sudo apt install -y nginx
$ sudo ufw allow 80,443/tcp
RHEL-based
$ sudo dnf install -y nginx
$ sudo systemctl enable --now nginx
$ sudo firewall-cmd --permanent --add-service=http --add-service=https
$ sudo firewall-cmd --reload

Both firewall tools apply these rules to IPv4 and IPv6 at the same time, so there is nothing extra to do for IPv6.

3. Create a server block

/etc/nginx/conf.d/example.com.conf
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

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

The [::] line is the IPv6 listener. Without it your site answers on IPv4 only, and visitors on IPv6 networks get nothing.

ssh session
$ sudo mkdir -p /var/www/example.com
$ echo "it works" | sudo tee /var/www/example.com/index.html
$ sudo nginx -t && sudo systemctl reload nginx

Always run nginx -t before a reload. It checks the configuration and tells you the exact line if something is wrong.

4. Install Certbot and get the certificate

The Certbot project recommends installing from snap, because that version gets updates fastest.

Ubuntu and Debian
$ sudo apt install -y snapd
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
RHEL-based
$ sudo dnf install -y epel-release
$ sudo dnf install -y certbot python3-certbot-nginx

Then ask for the certificate. Certbot edits your Nginx configuration and reloads it:

ssh session
$ sudo certbot --nginx -d example.com -d www.example.com

Answer the email and terms questions. When it finishes, your site answers on HTTPS, and Nginx redirects HTTP to HTTPS.

Let's Encrypt has rate limits

Repeated failed attempts for the same domain will lock you out for a while. If you are testing, add --dry-run to your command first. It runs the whole process against a test server without issuing a real certificate.

5. Check that renewal works

Certificates last 90 days. The installation adds a timer that renews them automatically, so the only thing to verify is that the renewal itself succeeds:

ssh session
$ sudo certbot renew --dry-run
$ systemctl list-timers | grep -i certbot

If the dry run passes, renewal will work unattended.

6. Reverse proxy for an app on a local port

If you run an app in Docker or on a local port, Nginx sits in front of it and handles HTTPS. Replace the root and index lines with a proxy block:

/etc/nginx/conf.d/app.example.com.conf
server {
    listen 80;
    listen [::]:80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

The last three lines matter for any app with a live dashboard or chat, because those use WebSockets and will not load without them. Then run sudo nginx -t, reload, and run the same certbot --nginx command with -d app.example.com.

With the proxy working, close the app's own port in your firewall so the only way in is through Nginx over HTTPS.

Quick reference

TaskCommand
Test configsudo nginx -t
Reloadsudo systemctl reload nginx
Get a certificatesudo certbot --nginx -d example.com
Test issuance safelyadd --dry-run
Test renewalsudo certbot renew --dry-run
List certificatessudo certbot certificates

Where to go next

Add security headers and a stronger TLS configuration once the basics work. If your site is one of several on the same server, repeat step 3 with a new file per domain; Nginx picks the right one by server_name.

nginx tls https letsencrypt certbot ipv6

Related articles