Moving a site to a new server means the certificate has to come too, or be replaced. Which of those is easier depends entirely on how it was issued.
First: does it need moving at all?
If the certificate was issued automatically and renews automatically, issue a fresh one on the new server instead. It is faster, it avoids handling the private key, and the new server ends up with a renewal process that works.
The catch is that issuance usually requires the domain to point at the new server, which it does not yet. Two ways round it: use DNS-based validation, which works before any traffic moves, or issue the certificate immediately after the cutover and accept a short window.
Moving the existing files avoids that window entirely, which is the main argument for doing it. Planning a DNS cutover walks through the sequence around it.
The three files
The certificate. Public. Begins -----BEGIN CERTIFICATE-----.
The intermediates. Also public, often called a CA bundle. The server must send these alongside the certificate or non-browser clients fail. Fixing certificate errors in scripts explains that symptom.
The private key. Secret, irreplaceable, and the reason this operation deserves care. Begins -----BEGIN PRIVATE KEY-----.
All three must arrive. A certificate without its key is useless; a key without its certificate is a liability.
Confirm they belong together
openssl x509 -noout -modulus -in certificate.crt | openssl md5 openssl rsa -noout -modulus -in private.key | openssl md5
The two hashes must be identical. If they differ, the files are from different issuances and installing them produces a broken site rather than an error at install time.
This happens more often than it should, because renewals leave several similarly named files in the same directory. Ten seconds here saves an outage.
Generating a CSR and managing private keys explains keeping them straight in the first place.
Transfer the key properly
Over SSH, directly:
scp private.key certificate.crt ca-bundle.crt user@newserver:/tmp/
Not by email. Not through a chat application. Not in a ticket.
A private key that has travelled in the clear should be treated as disclosed, and the correct response to that is reissuing the certificate with a new key: not proceeding and hoping.
On arrival, set the permissions before anything else:
chmod 600 /path/to/private.key chown root:root /path/to/private.key
A key readable by the web user is readable by any code the web server runs, which includes anything an attacker manages to place there. Understanding file permissions goes over why that matters.
Installing
In cPanel, the SSL/TLS section takes all three in one form. There is more in installing an SSL certificate in cPanel.
On a server you administer, the three files are referenced in the site's configuration, and the certificate and bundle are frequently concatenated into one file. Order matters: your certificate first, then the intermediates.
Verify from outside
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | grep -E 'Verify return|subject='
Check the verification result and that the names on the certificate cover both the bare domain and www. Testing only from the server itself proves less than it appears to.
Delete the copies
Once it is working, remove the key from wherever it was staged, /tmp, your laptop's downloads folder, the archive you used for the migration.
Keys accumulate in exactly those places and are forgotten. A key sitting in a temporary directory on a shared server is a real exposure with no benefit at all.
Then fix the renewal
A moved certificate expires on its original date and the new server has no renewal process for it.
Set that up immediately rather than after the reminder, and check the expiry date now so you know how long you have. Renewing your certificate picks it up from there. A migration that ends with a working certificate and no renewal is a migration with a deadline nobody wrote down.
Test the new server before pointing anything at it
The certificate can be verified on the new machine while the domain still resolves to the old one.
curl -sI --resolve example.com:443:NEW-IP https://example.com/ | head -1 echo | openssl s_client -connect NEW-IP:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -dates
Resolving the name to the new address for a single request presents the hostname the certificate expects, which is what the certificate check depends on.
A certificate that verifies here will verify for visitors after the switch. Doing it in this order means a mistake is found while nothing depends on it, which is the difference between an adjustment and an outage.
Check every service, not only the website
The same certificate is usually presented by more than one service, and each reads it at startup.
for p in 443 993 465 587; do printf 'port %-5s %s\n' "$p" "$(echo | openssl s_client -connect NEW-IP:$p -servername example.com 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null || echo 'yanit yok')" done
Different dates across ports mean one service was restarted after the installation and another was not.
Mail is the one that gets missed, because the website is what people check. A customer whose mail client warns after a server move is usually seeing a mail service still holding the previous certificate.
Plan the renewal on the new machine
Moving a certificate moves the file. It does not move whatever was renewing it.
crontab -l | grep -iE 'certbot|acme|ssl' systemctl list-timers --all --no-pager 2>/dev/null | grep -i cert
Check on both machines. The old one frequently still has the renewal job, which will keep renewing a certificate for a domain it no longer serves and eventually fail in a way nobody investigates.
Set up renewal on the new machine and confirm it completes once, deliberately, rather than waiting for the automatic run to discover a problem near the expiry date. Renewing your SSL certificate covers the mechanism.
Keep a record of what is installed where
An estate with several certificates across several machines needs a list, because the alternative is discovering the arrangement during an expiry. Record, per certificate: which names it covers, which machine it is installed on, which services present it, who issued it and when it expires. Five fields, kept anywhere you will actually look. The value shows the first time somebody asks whether a particular subdomain is covered, which is a question that otherwise takes half an hour to answer.