Deployment

Generate Absolutely Free SSL Certificate for Your Setup (Let’s Encrypt on Ubuntu) with Auto-Renew Script

MYLINEHUB Team • 2026-02-16 • 12 min

Step-by-step Let’s Encrypt SSL generation on Ubuntu plus automated renewal script and verification for long-term secure deployments.

Generate Absolutely Free SSL Certificate for Your Setup (Let’s Encrypt on Ubuntu) with Auto-Renew Script

HTTPS is not optional anymore. Browsers warn users, APIs reject insecure callbacks, and WebSockets often fail behind proxies without valid TLS.

This guide shows the most reliable way to generate a free SSL certificate using Let’s Encrypt + Certbot on Ubuntu, configure it with NGINX, and set up automatic renewal that you can actually verify.

It also covers the real-world problems people hit: DNS issues, ports blocked, “too many redirects”, failed renewals, broken WebSockets, and how to debug each one.

Official references you can trust: Let’s Encrypt Docs, Certbot (EFF) Instructions, NGINX Docs.

Architecture: What You’re Setting Up (So You Don’t Break Routing)

Let’s Encrypt validates domain ownership using HTTP on port 80 (HTTP-01) or DNS records (DNS-01). The most common production flow with NGINX is:

User Browser / API Client https://yourdomain NGINX on your server :80 (HTTP) → ACME challenge :443 (HTTPS) → your app Your App / Backend Reverse-proxied by NGINX Let’s Encrypt (ACME) Validates domain via HTTP-01 HTTPS requests proxy_pass ACME HTTP check

The key idea: port 80 must be reachable from the public internet for HTTP-01 validation (unless you use DNS validation). Most failures happen because port 80 is blocked or DNS is wrong.

Before You Start: Checklist That Prevents 90% of SSL Failures

1) Your DNS must point to the correct public IP

Confirm the domain resolves to your server’s public IP. From your local machine:

dig +short yourdomain.com
dig +short www.yourdomain.com

The output should match your server’s public IPv4 (or IPv6 if you’re using IPv6). If it doesn’t, fix DNS first (or wait for propagation).

2) Ports 80 and 443 must be open

On Ubuntu with UFW:

sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload

If you’re behind a router/NAT, also ensure router port forwarding is correct. (Port 80 is required for HTTP-01 challenge.)

3) NGINX should already serve your domain on HTTP (temporary is fine)

Make sure this works before SSL:

curl -I http://yourdomain.com

You should see a response (200/301/302 is okay). A timeout usually means networking/firewall.

Step 1: Install NGINX + Certbot (Ubuntu)

Install NGINX

sudo apt update
sudo apt install -y nginx

Verify NGINX is running:

systemctl status nginx --no-pager

Install Certbot for NGINX

On Ubuntu, the common production approach is using the packaged Certbot with the NGINX plugin:

sudo apt install -y certbot python3-certbot-nginx

If your environment uses snap for certbot, follow the official EFF flow here: certbot.eff.org

Step 2: Create a Clean HTTP Server Block (So Certbot Can Upgrade It)

Create (or edit) an NGINX server block for your domain. Example:

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

Use this minimal HTTP config first:

server {
  listen 80;
  listen [::]:80;
  server_name yourdomain.com www.yourdomain.com;

  # Temporary safe root for ACME challenge
  root /var/www/html;

  location / {
    return 200 "OK - HTTP reachable\n";
    add_header Content-Type text/plain;
  }
}

Enable it:

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

Test from the internet (or at least from your laptop):

curl -i http://yourdomain.com

This command will:

  • Request a certificate for your domain(s)
  • Prove ownership using HTTP-01 validation
  • Modify your NGINX config to enable HTTPS
  • Optionally configure HTTP → HTTPS redirect
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

If prompted for redirect, choosing redirect is usually correct for production websites and dashboards. For some telecom APIs (callbacks) you may intentionally keep HTTP endpoints — but then you must manage that safely.

Where certificates are stored

Certbot typically stores certificates here:

/etc/letsencrypt/live/yourdomain.com/fullchain.pem
/etc/letsencrypt/live/yourdomain.com/privkey.pem

Check the certificate:

sudo certbot certificates

Step 4: Confirm HTTPS Works (Real Checks, Not Guessing)

1) Confirm the certificate is served

curl -Iv https://yourdomain.com

Look for:

  • subject: yourdomain.com
  • issuer: Let’s Encrypt
  • HTTP/2 (optional but common)

2) Confirm auto-redirect (if enabled)

curl -I http://yourdomain.com

You should see a 301/308 redirect to https://...

3) Confirm NGINX config

sudo nginx -T | sed -n '1,200p'

Production-Safe NGINX TLS Settings (Modern Defaults)

Certbot will generate a working HTTPS config, but production systems often tighten TLS. You can add/confirm these settings inside your HTTPS server block.

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  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;

  # Modern TLS: keep it simple and compatible
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_prefer_server_ciphers off;

  # Optional security headers (adjust based on your app)
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  add_header X-Content-Type-Options nosniff always;

  location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;

    # WebSocket support (common in dashboards/telecom apps)
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    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;
  }
}

Reload:

sudo nginx -t
sudo systemctl reload nginx

If your app uses long-running requests or streaming: configure proxy timeouts (common with telecom reports or media control APIs).

Auto-Renewal: Make Sure It Actually Renews (And Prove It)

Let’s Encrypt certificates expire (typically 90 days). Auto-renewal is mandatory. On Ubuntu, certbot usually installs a systemd timer automatically.

1) Check the systemd timer

systemctl list-timers | grep certbot || true
systemctl status certbot.timer --no-pager || true

2) Dry-run renewal test (must succeed)

sudo certbot renew --dry-run

You want to see output indicating renewal simulation succeeded. If dry-run fails, your real renewal will fail too.

3) Reload NGINX after renewal (if not already handled)

Many setups already reload automatically, but you can ensure it by adding a deploy hook:

sudo certbot renew --deploy-hook "systemctl reload nginx"

For a permanent hook:

sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/sh
systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Most Common SSL Problems People Search For (And Exact Fixes)

Problem: “Certbot failed authorization procedure”

Usually one of these:

  • DNS A record points to wrong IP
  • Port 80 blocked (UFW / cloud security group / router)
  • NGINX not serving the requested domain (wrong server_name)
  • Another service is using port 80

Quick checks:

sudo ss -lntp | grep -E ':80|:443' || true
curl -I http://yourdomain.com
dig +short yourdomain.com

Problem: “Too many redirects” after enabling SSL

This often happens when:

  • Your app forces HTTPS while NGINX already redirects HTTP→HTTPS
  • Reverse proxy doesn’t set X-Forwarded-Proto so the app thinks it’s HTTP

Fix in NGINX:

proxy_set_header X-Forwarded-Proto $scheme;

Problem: WebSockets fail after SSL (telecom dashboards / real-time UI)

Usually missing Upgrade/Connection headers:

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

Problem: Renewal fails later even though initial issuance worked

Common causes:

  • Port 80 was later closed by firewall changes
  • Domain moved to a different IP without updating DNS
  • NGINX config changed and broke ACME location handling

Always run:

sudo certbot renew --dry-run

Alternative: DNS Validation (When Port 80 Cannot Be Open)

Some environments cannot expose port 80 publicly (strict enterprises, certain network policies). In that case, use DNS-01 validation. This requires adding TXT records in DNS.

Start here: Let’s Encrypt Challenge Types

DNS validation is powerful but depends on your DNS provider automation. If you do it manually, you must carefully manage TXT records.

Certificate Files for Apps That Need PEM (Common in Telecom Integrations)

Many telecom components (WebRTC gateways, SIP-related dashboards, Java services) require separate PEM files. Let’s Encrypt already provides PEM. Usually you will use:

  • fullchain.pem (server cert + chain)
  • privkey.pem (private key)

If a tool demands a combined file:

sudo sh -c 'cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
/etc/letsencrypt/live/yourdomain.com/privkey.pem > /etc/ssl/private/yourdomain.com-combined.pem'

sudo chmod 600 /etc/ssl/private/yourdomain.com-combined.pem

Keep private keys locked down. Never copy them into world-readable folders.

Final Verification Checklist (Use This Before Calling It “Done”)

  • HTTP works: curl -I http://yourdomain.com
  • HTTPS works: curl -Iv https://yourdomain.com
  • NGINX reload ok: sudo nginx -t
  • Certbot sees cert: sudo certbot certificates
  • Renewal dry-run passes: sudo certbot renew --dry-run
  • Timer exists: systemctl status certbot.timer

If all checks pass, you have a production-grade free SSL setup with automatic renewal.

Try it

Want to see API-driven CRM + Telecom workflows in action? Try the WhatsApp bot or explore the demos.

💬 Try WhatsApp Bot ▶️ Watch CRM YouTube Demos
Tip: Comment “Try the bot” on our YouTube videos to see automation in action.
M
MYLINEHUB Team
Published: 2026-02-16
Quick feedback
Was this helpful? (Yes 0 • No 0)
Reaction

Comments (0)

Be the first to comment.