Back to tutorials
Tutorial

TLS setup guide tutorial (2026): Configure HTTPS with Let’s Encrypt on a VPS (Nginx or Apache) and Fix Common SSL Errors

TLS setup guide tutorial for 2026: enable HTTPS on a VPS with Let’s Encrypt, automate renewals, and troubleshoot common SSL failures.

By Anurag Singh
Updated on Oct 15, 2026
Category: Tutorial
Share article
TLS setup guide tutorial (2026): Configure HTTPS with Let’s Encrypt on a VPS (Nginx or Apache) and Fix Common SSL Errors

TLS failures rarely look dramatic. They show up as redirect loops, browser warnings, or a certificate that expires at 2 a.m.

This TLS setup guide tutorial shows a production-ready HTTPS setup on a Linux VPS using Let’s Encrypt. You’ll get reliable renewals and quick checks for the problems you’ll actually hit in 2026.

The steps apply to Ubuntu 24.04/26.04 LTS and Debian 12/13, using either Nginx or Apache. By the end, you’ll have a valid certificate, safe HTTP→HTTPS redirects, modern TLS defaults, and a renewal process you can prove works.

Prerequisites (don’t skip these)

  • A VPS or dedicated server with root (or sudo) access.
  • A domain name pointing to your server’s public IP.
  • Ports 80 and 443 open to the internet.
  • Nginx or Apache installed and serving your site.

If you’re building a new host, start from a clean base image. Keep your firewall policy simple at first.

A HostMyCode VPS works well because you control DNS, the web server, and certificates end to end.

You avoid shared-hosting limits and hidden proxy layers.

Step 1: Confirm DNS is correct before issuing any certificate

Let’s Encrypt will not issue a certificate unless your domain resolves to the server making the request.

If DNS still points to an old server, validation will fail. The same happens if traffic goes through a proxy you forgot about.

Check A/AAAA records

dig +short A example.com
dig +short AAAA example.com

Compare the results with your server’s public IP:

curl -4s https://ifconfig.me; echo
curl -6s https://ifconfig.me; echo
  • If you publish an AAAA record but the server doesn’t have working IPv6, remove the AAAA record (or configure IPv6 properly). Some clients prefer IPv6 and will fail before they ever try IPv4.
  • If you’re migrating, drop TTL before the switch. This runbook covers a clean cutover: DNS cutover tutorial for zero-downtime migrations.

Sanity check: does HTTP reach your server?

curl -I http://example.com
curl -I http://www.example.com

You should get a response from your web server. A 301 is fine at this stage.

If you see a hosting-company landing page, you’re not hitting the right host.

Step 2: Open firewall ports 80/443 (UFW and nftables examples)

HTTP-01 validation needs inbound port 80. HTTPS needs 443.

If you open only 443, issuance and renewals often fail.

UFW (common on Ubuntu)

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

nftables (common on Debian/AlmaLinux/Rocky)

Exact rules depend on your baseline policy.

If you manage nftables directly, confirm your input chain allows inbound 80/tcp and 443/tcp.

If you want a solid production baseline for a hosting VPS (web + mail + DNS + SSH), follow: iptables/nftables tutorial for hosting VPS firewall rules.

Step 3: Install Certbot (recommended packages for 2026)

Install Certbot from your distribution packages when possible.

You’ll get security updates, and systemd timers usually work as expected.

Ubuntu / Debian

sudo apt update
sudo apt install -y certbot

Then add the plugin that matches your web server:

# For Nginx
sudo apt install -y python3-certbot-nginx

# For Apache
sudo apt install -y python3-certbot-apache

Confirm what you’re running:

certbot --version
nginx -v 2>&1 || true
apache2 -v 2>&1 || httpd -v 2>&1 || true

Step 4: Issue a certificate on Nginx (HTTP-01) + safe redirects

For most VPS-hosted sites, this is the quickest path.

Certbot can update your Nginx config and add an HTTP→HTTPS redirect.

Only enable the redirect if the site already works over HTTPS.

Before you run Certbot: ensure a working server block

Nginx site files typically live in /etc/nginx/sites-available/.

They usually have a symlink in /etc/nginx/sites-enabled/.

sudo nginx -t
sudo ls -lah /etc/nginx/sites-enabled/

A minimal HTTP server block (example):

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

  root /var/www/example.com/public;
  index index.html index.php;

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

Run Certbot for Nginx

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

During the prompts:

  • Use a real email address. Renewal and expiry notices save you later.
  • Only choose the redirect option if you’re ready to enforce HTTPS (or the site already works over HTTPS).

Verify the resulting config

sudo nginx -t
sudo systemctl reload nginx

Test from the server so you know what it’s actually serving:

curl -I https://example.com
curl -I http://example.com

HTTPS should return 200 (or a single 301 to your canonical URL). HTTP should redirect to HTTPS.

Step 5: Issue a certificate on Apache (HTTP-01) + VirtualHost checks

Apache still powers many VPS setups and older applications.

A common mistake is requesting a certificate for a name that is not mapped to the expected VirtualHost.

Confirm your enabled site

sudo apache2ctl -S

Check the ServerName and the vhost file path.

On Debian/Ubuntu, site configs usually live under /etc/apache2/sites-available/.

Run Certbot for Apache

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

Then reload Apache:

sudo apache2ctl configtest
sudo systemctl reload apache2

Step 6: Set modern TLS defaults (practical, not exotic)

Certbot gives you a valid certificate.

Your real TLS posture depends on what the web server allows.

Focus on protocol versions, redirects, and correct vhost wiring.

Keep it simple, but don’t leave legacy protocols enabled.

Nginx: confirm protocol settings

Many distributions store recommended settings in snippets or included files.

Don’t assume anything. Inspect the live config instead:

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

As a baseline, avoid TLS 1.0/1.1.

For general web hosting in 2026, TLS 1.2 and 1.3 are the expected minimum.

Apache: enable HTTP/2 where appropriate

HTTP/2 helps on asset-heavy sites and reduces request overhead. On Apache:

sudo a2enmod http2 headers ssl
sudo systemctl reload apache2

Then ensure your SSL vhost contains:

Protocols h2 http/1.1

Step 7: Automate renewals (and actually verify they work)

Let’s Encrypt certificates are short-lived on purpose.

If renewals fail, browsers will complain fast.

Set up automation, then validate it end to end.

Check the renewal timer

sudo systemctl list-timers | grep -E 'certbot|acme' || true

On many systems you’ll see certbot.timer.

If it exists, confirm it’s enabled and healthy:

sudo systemctl status certbot.timer

Dry-run a renewal

sudo certbot renew --dry-run

A successful dry run proves DNS, firewall rules, and web server integration are all working.

Keep the log path handy for future debugging:

sudo tail -n 80 /var/log/letsencrypt/letsencrypt.log

If you want stronger operational coverage (monitoring + restore testing), pair this with: server monitoring setup guide with alerts.

Step 8: Fix the SSL problems that waste the most time

This is the “stop guessing” section.

Identify the failure mode first. Then change the smallest thing that fixes it.

Problem: Certbot fails with “unauthorized” or “invalid response”

  • Cause: DNS points somewhere else, port 80 is blocked, or a reverse proxy intercepts the challenge.
  • Verify: curl -I http://example.com/.well-known/acme-challenge/test should reach your server (a 404 is fine; hitting the wrong host is not).
  • Fix: Correct A/AAAA records, open port 80, and remove forced HTTPS redirects that break /.well-known/ (rare with modern Certbot, common with hand-rolled rules).

Problem: Redirect loop (ERR_TOO_MANY_REDIRECTS)

  • Cause: You’re enforcing HTTP→HTTPS in multiple places (app + proxy), or you have competing canonical redirects (www vs non-www).
  • Quick test: curl -IL http://example.com and read every Location: hop.
  • Fix: Enforce canonical redirects in one layer only. For WordPress behind a proxy, make sure WordPress can detect HTTPS (often $_SERVER['HTTPS'] or correct X-Forwarded-Proto handling).

Problem: Mixed content warnings after enabling HTTPS

  • Cause: Your pages still reference http:// assets (images, JS, CSS).
  • Verify: Open DevTools → Console/Security and note the blocked URLs.
  • Fix: Update base URLs in your CMS, and ensure the app generates HTTPS links. For WordPress, update Site URL + Home URL, then replace hardcoded links carefully.

For WordPress-specific hardening and clean admin access once HTTPS is live, use: WordPress hardening tutorial.

Problem: “Certificate not valid for this domain”

  • Cause: You issued a cert for example.com but users visit www.example.com (or vice versa), or the vhost/server block points at the wrong certificate.
  • Verify: openssl s_client -connect example.com:443 -servername example.com and read the certificate SANs.
  • Fix: Reissue with both names: -d example.com -d www.example.com, then confirm the correct vhost is serving the correct cert.

Problem: Renewal succeeds but the server still serves the old certificate

  • Cause: The web server wasn’t reloaded, or you pinned ssl_certificate to an old path.
  • Verify: Check your Nginx/Apache config for ssl_certificate paths, then compare timestamps under /etc/letsencrypt/live/.
  • Fix: Ensure the renewal process reloads the service. On systemd systems, Certbot usually does this. If it doesn’t, add a deploy hook:
sudo certbot renew --deploy-hook "systemctl reload nginx"
# or
sudo certbot renew --deploy-hook "systemctl reload apache2"

Step 9: Add HSTS only after you’re sure (safe rollout)

HSTS tells browsers to stick to HTTPS for a set time.

That’s useful, but it also removes your ability to “temporarily fall back” if you break TLS.

Roll it out in stages.

Start with a short max-age (for example, one day):

Strict-Transport-Security: max-age=86400; includeSubDomains

After a week of clean operation and confirmed renewals, increase the value (30–180 days is common).

Avoid preload until HTTPS has been stable across all subdomains for a while.

Step 10: Operational checklist for hosting admins (repeatable)

  • DNS: A/AAAA records point to the correct server; remove AAAA if IPv6 isn’t configured.
  • Firewall: inbound 80/tcp and 443/tcp open; no upstream block.
  • Web server: HTTP vhost exists for each hostname you will certify.
  • Certificate: issued for all required names (apex + www, and any extra hostnames).
  • Redirects: one canonical policy (www or non-www), no redirect loops.
  • Renewals: certbot renew --dry-run passes; timer exists; deploy hook reloads web server.
  • Security headers: HSTS staged with short max-age first.
  • Monitoring: uptime check for https:// endpoint and certificate-expiry alerts.

Where HostMyCode fits (and when to choose managed hosting)

If you want full control over your TLS stack—custom Nginx rules, multi-site hosting, or non-standard ports—a self-managed VPS keeps everything in your hands.

If you’d rather offload OS patching and baseline hardening, managed VPS hosting is often the better trade.

Either way, treat TLS like routine operations, not a one-time setup.

Pair it with backups and alerting so a renewal failure doesn’t turn into downtime.

Need HTTPS that stays fixed after launch? Host your site on a HostMyCode VPS for full control of Nginx/Apache and Let’s Encrypt automation. If you prefer a team to handle patching, renewals, and baseline hardening, choose managed VPS hosting and keep your focus on the application.

FAQ

Do I need port 80 open forever if I only want HTTPS?

For HTTP-01 validation, yes—port 80 must be reachable during issuance and renewals.

If you have to close it, switch to DNS-01 validation. Expect extra DNS API work and more moving parts.

Should I use a wildcard certificate on a hosting VPS?

Only if you truly need lots of dynamic subdomains. Wildcards require DNS-01 validation.

For most sites, a standard SAN certificate for the hostnames you actually use is simpler and easier to troubleshoot.

How do I confirm which certificate the server is presenting?

Use OpenSSL with SNI:

openssl s_client -connect example.com:443 -servername example.com | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

What’s the safest way to migrate an HTTPS site to a new VPS?

Run both servers in parallel, lower TTL, issue the cert on the new VPS before cutover, and only flip DNS once you’ve tested HTTP and HTTPS end-to-end.

Follow: DNS cutover tutorial.

What if I’m using cPanel/WHM instead of raw Nginx/Apache?

WHM can manage AutoSSL, but the troubleshooting looks different (DCV checks, DNS issues, account-level conflicts).

Use: cPanel AutoSSL troubleshooting tutorial.

Summary

This tutorial walked you through a repeatable HTTPS setup: verify DNS, open 80/443, issue Let’s Encrypt certificates with Certbot, confirm modern TLS settings, and validate renewals with a dry run.

The habit that prevents outages is simple: check what’s live, not what you think you configured.

If you want predictable TLS behavior and the freedom to tune your web stack, deploy on a HostMyCode VPS.

If you’d rather hand off OS and security maintenance, managed VPS hosting is the cleaner operational choice.