Fix SSL Certificate Not Trusted Error After Website Migration

Yesterday I spent four hours staring at a browser warning because of a dumb SSL certificate not trusted error after migrating a website to a new VPS. The migration went fine, the database connected, and the files were all there, but every browser threw a massive privacy alert.

If you just moved your site and everything broke, you’re probably dealing with a broken certificate chain or a cached IP mismatch.

It’s an incredibly annoying issue, especially when your hosting dashboard swears everything is completely fine. Let’s get it fixed.

Why the SSL Breakage Happens After a Migration

When you move a site, you aren’t just moving files; you’re changing IPs, web servers (maybe Apache to Nginx), and how your server talks to the Certificate Authority (CA). Here’s what usually goes sideways during a migration.

1. The Missing Intermediate Certificate (The Chain Link)

This is the most common culprit. Your server needs your main SSL certificate and the intermediate certificates provided by your CA. If you just copied the main ssl.crt file and forgot the bundle file (ca-bundle or chain.crt), modern browsers will reject it.

2. DNS Propagation Lag and Old CAA Records

Your domain nameservers point to the new host, but local DNS caches or CDN nodes still look at the old server. If your new server tries to auto-renew a Let’s Encrypt cert while DNS is in limbo, the validation fails. Also, if you have a Certificate Authority Authorization (CAA) record in your DNS that specifies a different provider, the new server can’t issue a cert.

3. Web Server Config Overwrites

If you moved from an Apache setup to Nginx, your old .htaccess redirect rules don’t work anymore. Or worse, the default virtual host file on the new server is overriding your specific SSL block, serving a self-signed localhost certificate instead of yours.

Quick Diagnostics: What Actually Is Wrong?

Error Message / SymptomMost Likely CauseQuick Fix
NET::ERR_CERT_AUTHORITY_INVALIDMissing intermediate CA bundle or self-signed fallback cert.Combine your main cert and bundle into a single file.
ERR_CERT_COMMON_NAME_INVALIDHostname mismatch or old server IP cached.Check your Nginx/Apache server name configuration.
Works on desktop, fails on mobileMissing intermediate chain.Mobile devices don’t cache intermediate certs like desktops do.

Step-by-Step Fixes

Step 1: Rebuild the Certificate Chain (Nginx or Apache)

If your SSL works on your laptop but gives an SSL certificate not trusted error after migrating a website on your phone, your intermediate bundle is missing.

For Nginx, you can’t just list the bundle separately; you have to concatenate them into a single file.

Bash

cat your_domain.crt your_bundle.ca-bundle > ssl-bundle.crt

Open your Nginx configuration file (usually in /etc/nginx/sites-available/) and update the paths:

Nginx

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /etc/ssl/certs/ssl-bundle.crt;
    ssl_certificate_key /etc/ssl/private/your_private_key.key;
}

Restart Nginx: sudo systemctl restart nginx.

If you use Apache, you keep them separate using the SSLCertificateChainFile directive inside your VirtualHost block.

Step 2: Clear the Local DNS and CDN Cache

If you use Cloudflare or another CDN, it’s likely trying to fetch the SSL info from your dead origin server. Log into Cloudflare, go to the SSL/TLS tab, and toggle the encryption mode from “Full” to “Flexible” and back to “Full (Strict)” to force a refresh.

On your local machine, flush your DNS:

  • Windows: ipconfig /flushdns in CMD.
  • Mac: sudo killall -HUP mDNSResponder in Terminal.

What Actually Worked For Me

Well, sort of—it’s actually more like what I accidentally stumbled upon after wasting a ton of time.

I initially assumed Let’s Encrypt was just bugging out on the new Ubuntu box. I spent an hour deleting certs, running certbot --nginx, and force-renewing over and over. Every time, Certbot said success, but my browser kept screaming that the connection wasn’t trusted.

That’s not entirely accurate, let me explain: Certbot was succeeding, but Nginx wasn’t actually loading the new paths.

The real issue was an old default configuration file (/etc/nginx/sites-enabled/default) that I forgot to delete. It was listening on port 443 with a generic self-signed snakeoil certificate. Because it loaded alphabetically before my actual site config, Nginx served the self-signed cert to anyone trying to connect.

Once I removed that default file and reloaded Nginx, the error vanished instantly.

From what I’ve seen, people online always tell you to reinstall Certbot or rewrite your .htaccess rules. But honestly, those rarely solve the issue if the underlying web server config is conflicted.

Advanced Fixes and Edge Cases

Look for Conflicting Listen Directives with grep

If your site still serves the wrong cert, someone else is hogging port 443. Run this command to see every file trying to configure SSL:

Bash

sudo grep -r "listen 443" /etc/nginx/

(Or /etc/httpd/ or /etc/apache2/ if you’re running Apache).

If you see files you didn’t create or a default-ssl.conf file active, disable them. They will intercept traffic before your actual domain configuration gets a chance to look at it.

Fix Permissions on Private Keys

Sometimes the migration tool copies files over but changes ownership to root. If your web server runs under the www-data or nginx user, it might not even be able to read your private key file. It falls back to a broken state without telling you clearly in the standard browser log.

Fix it by setting correct permissions:

Bash

sudo chmod 600 /etc/ssl/private/your_private_key.key
sudo chown root:root /etc/ssl/private/your_private_key.key

Check your error logs (/var/log/nginx/error.log or /var/log/apache2/error.log) right after restarting the service to see if it complains about permission denied.

Prevention Tips

  • Don’t lower your DNS TTL during the move: People say to lower it to 300 seconds, but some cheap routers ignore low TTLs entirely, causing weird split-routing SSL errors. Keep it normal and just wait out the change.
  • Back up the raw files, not just dashboard settings: Always copy the actual /etc/letsencrypt/ directory or raw .crt text strings manually before shutting down the old host.
  • Turn off DNS proxying initially: If using Cloudflare, turn the cloud icon to “Grey Box” (DNS only) during the migration. Once the SSL works directly on the server IP, turn the proxy back on.

FAQ

Why does my SSL error only show up on Android and iPhone?

Because desktop browsers like Chrome store old intermediate certificates in their local cache. Mobile browsers don’t do this. If your server is missing the intermediate bundle link, desktop users won’t notice, but mobile users will get a trusted error immediately.

Can I just copy my Let’s Encrypt folder to the new server?

Yes, you can tarball /etc/letsencrypt/ and move it. But you need to make sure the symlinks inside live directories don’t break during compression. If they turn into flat text files, Certbot will crash next time it updates.

How long does it take for SSL to fix itself after migration?

It doesn’t fix itself. If it’s a DNS issue, it takes up to 24 hours to clear up globally. If it’s a configuration error on your server, it will stay broken until you change the config files.

Editor’s Opinion

Man, SSL is easily the most annoying part of server admin work. The tools are supposed to automate everything now, but when they break, they give you zero helpful feedback. You just get a scary red screen in Chrome. Half the time the issue isn’t even the cert itself, it’s just some hidden default config file messing with your ports. Don’t overthink it—check your server blocks first, make sure your chain isn’t split, and look at the actual logs instead of guessing.

Leave a Comment