HTTPS site migration involves two additional steps compared to HTTP: installing the certificate on the new server and ensuring redirection rules cover HTTPS paths. Missing the former causes certificate warnings post-migration, while missing the latter directs HTTPS traffic to the wrong location.
Pre-Migration Preparation: Certificate Files
# ① Verify the currently active certificate (not local files)
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null
| openssl x509 -noout -dates -subject -ext subjectAltName
# ② Locate certificate and private key files on the old server
grep -E 'ssl_certificate|ssl_certificate_key' /etc/nginx/conf.d/*.conf
# ③ Package them up (including intermediate certificates)
tar -czf ssl-backup.tar.gz /etc/nginx/ssl/example.com/
You must transfer both the fullchain and the private key. If you only copy the certificate without the private key, Nginx will fail to start on the new server.
# Verify file usability before migration (check if cert and key match)
openssl x509 -noout -modulus -in fullchain.pem | openssl md5
openssl rsa -noout -modulus -in privkey.pem | openssl md5
# The two MD5 hashes must be identical
Installing Certificates on the New Server
mkdir -p /etc/nginx/ssl/example.com
cp fullchain.pem /etc/nginx/ssl/example.com/
cp privkey.pem /etc/nginx/ssl/example.com/
chmod 600 /etc/nginx/ssl/example.com/privkey.pem
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
...
}
nginx -t && nginx -s reload
Redirection: Cover Both HTTP and HTTPS
This is the most commonly overlooked step. A common SEO migration requirement is to 301 redirect old domains/paths to new addresses, but many people only configure rules for port 80.
# ❌ Only configured for HTTP; HTTPS access to the old domain won't redirect
server {
listen 80;
server_name old.com;
return 301 https://new.com$request_uri;
}
# ✅ Required for both ports
server {
listen 80;
listen 443 ssl;
server_name old.com;
ssl_certificate /etc/nginx/ssl/old.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/old.com/privkey.pem;
return 301 https://new.com$request_uri;
}
Key Point: The server block handling HTTPS redirects must also have the certificate configured. Otherwise, the TLS handshake fails before reaching return 301—users see a certificate error instead of being redirected.
# Verify that the old HTTPS domain redirects correctly
curl -I https://old.com/ | head -3
# Should show 301 and Location: https://new.com/...
301 Redirects Must Preserve Paths
# ✅ Preserves the full path
return 301 https://new.com$request_uri;
# ❌ Redirects everything to the homepage (loses weight and user intent for all pages)
return 301 https://new.com/;
# Verify path-preserving redirects
curl -I https://old.com/about/ | grep -i location
# Should be https://new.com/about/
Handling HSTS
If the old site had HSTS enabled, browsers will force HTTPS access to the old domain. This means the redirect block on port 443 mentioned above must work correctly; otherwise, users will get stuck.
# Check if the old site sent HSTS headers
curl -I https://old.com/ | grep -i strict
Recommendations during migration:
- Shorten the HSTS max-age before migrating to allow room for rollback
- After confirming everything works post-migration, restore the long max-age
Post-Switch Verification
# ① Verify certificate is active (on the new server)
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null
| openssl x509 -noout -dates
# ② Verify chain completeness
openssl s_client -connect example.com:443 -servername example.com
-verify_return_error </dev/null 2>/dev/null | grep -i 'verify return'
# ③ HTTP → HTTPS redirect
curl -I http://example.com/ | grep -i location
# ④ Old domain redirects (test both ports)
curl -I http://old.com/ | head -3
curl -I https://old.com/ | head -3
# ⑤ Check for mixed content (common after domain changes)
curl -s https://new.com/ | grep -oE 'http://[^"]+' | sort -u
Old Domains in the Database
# WordPress: Replace old domain (use WP-CLI, do not use direct SQL REPLACE)
wp search-replace 'https://old.com' 'https://new.com' --all-tables --dry-run
wp search-replace 'https://old.com' 'https://new.com' --all-tables
Replacing only home and siteurl is insufficient. Absolute links within post content must also be replaced, or mixed content issues will persist.
Decision Tree
HTTPS Site Migration
├─ Pre-Migration
│ ├─ Export fullchain + private key (verify they match)
│ ├─ Shorten HSTS max-age if rollback might be needed
│ └─ Backup old configuration
├─ New Server
│ ├─ Install certificate (fullchain, private key chmod 600)
│ └─ Run nginx -t before reloading
├─ Redirection
│ ├─ Configure redirect blocks for both 80 and 443
│ ├─ The 443 redirect block must also include the certificate ← Most easily missed
│ └─ 301 redirects must preserve $request_uri
└─ Post-Switch
├─ Certificate active + chain complete
├─ Redirects correct on both ports
└─ No mixed content (database must also be updated)
Scenario Walkthrough: Certificate Error When Accessing Old Domain After HTTPS Migration
Symptom: After migrating an encrypted site to a new server, accessing it via the old domain results in certificate-related errors; accessing via the new domain works normally.
- Identify the stage where the error occurs → If the error happens during the handshake phase before the page loads, it indicates a certificate issue, not a program or redirection problem.
- Confirm if the certificate is installed on the new server → It is installed, ruling out “forgot to install” as the cause.
- Check which domains the certificate covers → It only covers the new domain; the old domain is not listed. This is why the new domain works but the old domain reports an error.
- Verify where the redirect rule is placed → The redirect rule is inside the encrypted virtual host, meaning the handshake must succeed first before the redirect can trigger—a logical contradiction.
- Move the redirect to the unencrypted layer → Allow plain text access from the old domain to redirect first, avoiding the handshake phase entirely.
- Verify all four access scenarios individually → Old/New domain, with/without www, plain/encrypted. Test all combinations.
# Confirm covered domains: this is the core check
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null
| openssl x509 -noout -ext subjectAltName
# Verify all four scenarios individually
for u in http://old.com/p http://www.old.com/p https://old.com/p https://new.com/p; do
printf '%-30s ' "$u"
curl -sS -o /dev/null -w '%{http_code} -> %{redirect_url}n' "$u"
done
# Check for redirect loops
curl -sSL -o /dev/null -w 'Redirected %{num_redirects} timesn' http://old.com/p
# Handle plain text layer separately (Key: Put redirects on port 80, NOT inside 443)
# server { listen 80; server_name old.com; return 301 https://new.com$request_uri; }
Root Cause: The new server’s certificate does not cover the old domain, and the redirect rule is placed inside the encrypted virtual host. Since the handshake occurs before the redirect, users always see the certificate error first.
Two Key Takeaways:
- Redirects for the old domain must be written in the plain text layer. If written in the encrypted virtual host, the handshake fails first, and the redirect never executes.
- Post-migration verification must test all four access scenarios. Testing only the new domain misses old entry points—which are precisely the ones with the most external links and search engine indexing.
Applicability of Redirection Syntax
| Scenario | Key Syntax | Common Mistakes |
|---|---|---|
| HTTP → HTTPS (entire site) | A separate port 80 server block for redirection | Placing it inside the 443 block causes redirect loops |
| Old Domain → New Domain | return 301 $scheme://new$request_uri; |
Omitting $request_uri, causing all requests to go to the homepage |
| With WWW ↔ Without WWW | Unify to a single primary domain | Redirecting both ways creates a loop |
| Directory-Level Changes | Individual rewrite rules or map | Using wildcard redirects catches valid paths unintentionally |
The second row in the table above represents the most costly error in migration: redirections that do not preserve paths. This causes all old pages to 301 to the homepage. Search engines may treat these 301s as soft 404s, causing the accumulated indexing and backlink value of deep pages to disappear. The difference in syntax is just one variable: $request_uri.
# Four mandatory checks after switching
# 1. Is the certificate chain complete? (Return code must be 0)
echo | openssl s_client -connect new.com:443 -servername new.com -verify_return_error 2>&1 | grep -E 'Verify return code'
# 2. Do all scenarios redirect to the same target?
for u in http://old.com/a/b http://www.old.com/a/b https://old.com/a/b; do
curl -sS -o /dev/null -w "%{http_code} %{redirect_url} $un" "$u"
done
# 3. Are there redirect loops? (Be wary if more than 3 redirects occur)
curl -sSL -o /dev/null -w '%{num_redirects} redirectsn' http://old.com/a/b
# 4. Residual old domains in the database
wp search-replace '//old.com' '//new.com' --dry-run --report-changed-only
8 Common Pitfalls
- Copied certificate but not private key: New server fails to start.
- Used cert instead of fullchain: Incomplete chain.
- Configured only port 80 redirects: HTTPS access to old domain doesn’t redirect.
- 443 redirect block lacks certificate: Handshake fails immediately.
- 301 redirects to homepage: Loses path structure and SEO weight.
- Did not replace old domains in the database: Leaves mixed content.
- Migrated without shortening HSTS: Makes rollback difficult.
- Did not verify the chain post-migration: Certificate issues remain hidden until external access.
Real Customer Feedback (From Cloud Market Reviews and Consultations for Similar Products)
The following excerpts are taken from real buyer reviews and consultations for similar operations services on Alibaba Cloud / Tencent Cloud / Huawei Cloud Cloud Markets (service providers include our store and competitors, provided here for reference only, not fictional tickets from our site):
45***76 2021-04-14 5.0 Delivered on time. Excellent.
10***02 2024-07-31 5.0 Secure and reliable | Comprehensive features | Affordable price. Prompt handling, migration successful. 10***31 2022-06-22 5.0 Affordable price | Skilled technical support | Complete after-sales service. Good job, helped me migrate my years-old site to a new server.
10***31 2022-11-17 5.0 Delivered on time | Prompt response | Affordable price. System migration successful. 10***31 2022-11-17 5.0 Skilled technical support | Secure and reliable | Affordable price. Migration successful.