Free SSL Certificate for Your Website: Host a Site with Nginx and Let's Encrypt (Certbot) on Linux

12 min read 2 views 0
On this page

Every public website should load over HTTPS, and a free SSL certificate from Let's Encrypt makes that easy. This guide shows how to host a website on a JUSTG cloud server or dedicated server with Nginx, issue a Let's Encrypt certificate with certbot, confirm that automatic renewal works and force HTTPS. Commands are given for Debian/Ubuntu and for CentOS/Rocky Linux/AlmaLinux. The example domain is example.com and the server IP is 203.0.113.10; replace them with your own.

Step 1: Point the domain to your JUSTG server (A and AAAA records)

At your domain registrar or DNS provider, create an A record for the bare domain and for www pointing to the server's IPv4. JUSTG cloud servers also include free IPv6; add an AAAA record only if IPv6 is configured on the server and Nginx listens on it. Wait until the records resolve before requesting a certificate, because Let's Encrypt validates the domain over the internet.

# A    example.com       -> 203.0.113.10
# A    www.example.com   -> 203.0.113.10
# AAAA example.com       -> 2001:db8::10   (optional, only if IPv6 is configured)

# check from the server (Debian/Ubuntu: apt install -y dnsutils, Rocky: dnf install -y bind-utils)
dig +short example.com A
dig +short www.example.com A
dig +short example.com AAAA

Step 2: Install Nginx and certbot on Debian or Ubuntu

The certbot Nginx plugin can edit the Nginx configuration for you. Install everything from the standard repositories:

apt update
apt install -y nginx certbot python3-certbot-nginx
systemctl enable --now nginx
ufw allow 'Nginx Full'     # if UFW is enabled

Step 3: Install Nginx and certbot on Rocky Linux, AlmaLinux or CentOS

On RHEL-based systems, certbot comes from the EPEL repository. Open HTTP and HTTPS in firewalld as well:

dnf install -y epel-release
dnf install -y nginx certbot python3-certbot-nginx
systemctl enable --now nginx
firewall-cmd --permanent --add-service=http --add-service=https
firewall-cmd --reload

Step 4: Create the website and its Nginx server block

Create a document root with a test page. On SELinux systems, restorecon makes sure Nginx is allowed to read the files.

mkdir -p /var/www/example.com
echo '<h1>example.com is online</h1>' > /var/www/example.com/index.html
restorecon -Rv /var/www/example.com    # Rocky/Alma/CentOS with SELinux only

Then add a server block for the domain:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Save it in the right place for your distribution, test the syntax and reload Nginx:

# Debian / Ubuntu: save as /etc/nginx/sites-available/example.com, then
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# CentOS / Rocky / AlmaLinux: save as /etc/nginx/conf.d/example.com.conf

nginx -t && systemctl reload nginx
curl -I http://example.com

If curl -I returns 200 OK, the site is reachable over HTTP and you are ready for the certificate.

Step 5: Get a free Let's Encrypt SSL certificate with certbot --nginx

Run certbot with every domain name the certificate should cover. On the first run it asks for an email address for expiry notices and for agreement to the Let's Encrypt terms. The --redirect option adds an automatic HTTP to HTTPS redirect.

certbot --nginx -d example.com -d www.example.com --redirect

certbot proves control of the domain through a temporary file served by Nginx, installs the certificate in your server block and reloads Nginx.

Step 6: Check that automatic renewal works

Let's Encrypt certificates are valid for a short period, so renewal must be automatic. A dry run tests the whole process without changing the real certificate:

certbot renew --dry-run

# Debian / Ubuntu: the timer is enabled by the package
systemctl list-timers | grep certbot

# Rocky / AlmaLinux (EPEL): enable the renewal timer once
systemctl enable --now certbot-renew.timer

If the dry run reports success and the timer is active, nothing else is needed.

Step 7: Force HTTPS and verify the result

If you skipped --redirect, you can force HTTPS yourself by replacing the port 80 block with a redirect, keeping the HTTPS block that certbot created:

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

Reload Nginx and verify:

curl -I http://example.com      # expect 301 to https://
curl -I https://example.com     # expect 200
certbot certificates

Alternative: one-click SSL in aaPanel

If your server runs aaPanel, you can skip the manual steps. Add the site under Website, open its settings, go to the SSL section, choose Let's Encrypt, select the domain names and apply. Then turn on the Force HTTPS switch. aaPanel renews the certificate automatically. The DNS records from Step 1 are still required.

FAQ

certbot fails with a connection or timeout error. What should I check?

Make sure the A and AAAA records point to this server, that ports 80 and 443 are open in UFW or firewalld, and that Nginx is running. A wrong AAAA record is a common cause, because validation may use IPv6.

Can I use one certificate for several domains?

Yes. Add more -d options to the certbot command; every name must resolve to the server.

Do I need to restart Nginx after renewal?

No. The certbot Nginx plugin reloads Nginx automatically after a successful renewal.

If you still cannot resolve the issue, please submit a ticket to contact JUSTG technical support.

Was this answer helpful?