Moving a site to another hosting

Choose the new hosting

A move is a copy, a test and a DNS switch, not a race. Start with a plan that can hold the site as it is now: the same or a newer PHP version, the same extensions, enough disk for the files plus room for backups, and SSH access. Without SSH you are limited to the panel file manager and FTP, which is slower and easier to break halfway. Tools used here: wget for the status checks on the new server.

What to compare before you pay: the yearly price, the disk quota, the number of databases, the PHP versions offered and whether they can be switched per site, SSH, cron, backups, and whether mail is included. How to weigh the options: Which hosting to choose and, for a server of your own, VPS hosting.

Measure what you are moving first. From the folder that holds the site:

find . -type f | wc -l

du -sh .

Write both numbers down. They are the baseline for the copy: a smaller file count on the new server means files were skipped, and the usual reason is a hidden folder or a permission problem.

Copy the files

There are three ways, and they can be mixed. The panel file manager is the fallback: pack the site into one archive, upload it, unpack it on the server. An archive keeps permissions, empty folders and hidden files, and one upload is much faster than a thousand small ones.

tar czf site-backup.tar.gz site

ls -lh site-backup.tar.gz

-rw-rw-r-- 1 user user 274 Nov 6 18:45 site-backup.tar.gz

tar prints nothing by itself; the ls line is what tells you the archive exists and how big it is. Look inside before you upload it:

tar tzf site-backup.tar.gz

site/
site/index.php
site/web/
site/web/page.html
site/.htaccess

The name and the size are yours; the point is a single file, and the list shows that the hidden .htaccess is inside it. Upload the archive through the panel, then unpack it inside the new document root:

tar xzf site-backup.tar.gz --strip-components=1

--strip-components=1 drops the top folder of the archive, so site/index.php lands as index.php in the current directory. Without it the site ends up one level too deep and the home page returns 404. More about archives: Archives in Linux.

With SSH, copy over SFTP or SCP using an SSH key: make an ed25519 key, put its public half in the panel, then upload. In an interactive session, the lines starting with sftp> are the ones you type:

sftp user@new-host.example

sftp> cd /home/user/site/public_html

sftp> put -r web

sftp> put index.php

SSH access also gives you rsync, which is the safest way to sync a folder: it transfers only what differs and can show the plan first. Here between two local folders, so you can try it:

rsync -avn site/ public_html/

sending incremental file list
.htaccess
index.php
web/
web/page.html

sent 171 bytes received 29 bytes 400.00 bytes/sec
total size is 48 speedup is 0.24 (DRY RUN)

The same command to the new server:

rsync -avn -e ssh site/ user@new-host.example:/home/user/site/public_html/

-n is the dry run: read the list, then repeat the command without -n. The trailing slash on the source matters: site/ copies the contents, site creates a folder named site inside the target. Hidden files such as .htaccess travel with both tools; check them after the copy:

ls -la /home/user/site/public_html

Do not forget what is not in the archive: uploaded files, logs, caches and anything the site writes at runtime. Those folders need their own copy and the right permissions: folders 755, files 644, and 775 only where PHP must write.

Move a database

A static site has no database; skip this section. A CMS such as WordPress, a shop or a forum does. Export on the old server, create an empty database and a user with the same charset on the new one, then import.

mysqldump --single-transaction --routines --triggers -u old_user -p old_db > old_db.sql

mysql -u new_user -p new_db < old_db.sql

MySQL asks for the password after each command, so the password never lands in the shell history. Without SSH, phpMyAdmin does the same job: choose the database, Export, format SQL, save the file; then on the new server Import the file into the new database.

After the import, the CMS configuration must point at the new database (name, user, password, host) and at the new site address. In WordPress the address sits in the database, so change it with the tool, not with a text editor:

wp search-replace 'https://old.example.com' 'https://www.example.com' --dry-run

Run it again without --dry-run when the dry run lists only the expected tables. A blind replace in the SQL file breaks serialized values.

Configuration and paths

Files that mention the old server are the usual reason a moved site shows a white page or a wrong link. Check these:

Change paths in configuration, not in page content. If a page contains the old domain, fix it in the CMS or with a search over the database, and leave the old domain reachable with a redirect for a while.

Test before DNS

The domain still points at the old server, so test the new one by address. The simplest way is the hosts file of your own machine, which overrides DNS for that name only. On Linux and macOS it is /etc/hosts, on Windows C:\Windows\System32\drivers\etc\hosts, and the editor must run as administrator. Add one line:

203.0.113.10 www.example.com example.com

How the file works: etc/hosts. Now a browser on this machine sees the new server while everyone else still sees the old one. Ask for the status line of each important page:

wget -qS --spider https://www.example.com/ 2>&1 | head -4

HTTP/1.1 200 OK
Date: Fri, 06 Nov 2026 16:22:03 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked

The output above is what a healthy answer looks like; yours will carry the date of your own request. Check the home page, an inner page, a page that must redirect, and a missing page (it should return the site 404 document, not the hosting default). A 500 usually means a path or a permission; a 403 means an index file is missing or the folder is closed; a redirect loop means the HTTPS or www rule fires twice.

Remove the hosts line when the test is over, or you will keep testing the new server and wonder why the old one never changes.

Switch DNS

DNS records are cached for their TTL, so lower the TTL first: a day before the switch set it to 300 seconds on the A (and AAAA) records of the domain and of www. Then change the address to the new server.

nslookup www.example.com

Server: 192.0.2.1
Address: 192.0.2.1:53

Non-authoritative answer:
Name: www.example.com
Address: <new-server-ip>

The block shows what the answer looks like: the two addresses at the top are the DNS server that answered, and the last line must be your new server's address in place of <new-server-ip>. Different resolvers cache for different times, so check from another network too, for example from a phone with mobile data. Keep the old server running until the checks in the last section pass: some visitors can still reach it for hours.

TLS and redirects

A certificate for the new server can only be issued once the name points at it, because the free automatic certificates check the domain over HTTP. So the order is: DNS first, certificate second, redirects last. After the certificate is in place, every address must end on one canonical form in one hop: http to https, and www to the bare domain, or the other way round.

Test each form with its own request and look at the first status line: one 301 to the final address is right, two hops or a stop on http is not. Panels often add their own redirect; do not keep two rules for the same case. Background: HTTPS and certificates in plain words.

Email on the domain

Mail and the website are separate services that only share the domain name. Changing the web server does not move the mailboxes. If the domain has mail, its MX records must keep pointing at the mail provider, and SPF, DKIM and DMARC must stay valid; otherwise mail stops arriving or starts landing in spam.

Only change an MX record when the mailboxes themselves move, and do that as its own small project: create the mailboxes on the new side, copy the old mail, test sending and receiving, and only then switch the record. Send a test message to a mailbox on the domain after the move; that is the check that catches a broken MX.

Check and close the old hosting

Keep the old account for one to two weeks. During that time compare the two servers and watch the new one:

CheckHow
Every page answersopen a sample from each section; all return 200
Redirects are one hopwget -qS --spider on a few old addresses
No new 404sthe access log of the new server, or the hosting 404 report
No PHP errorsthe error log of the new server
HTTPS and wwwboth forms open on the canonical address
Certificate renewalthe panel shows an automatic renewal date
Maila test message arrives at a mailbox on the domain
Backupsthe new hosting makes them, and one restore was tried

When all of it passes, take a last copy of the old logs and of anything that existed only there, and cancel the old plan. If the renewal date is close, cancel after it: most providers do not refund a partial period.

The short version: lower the TTL, copy the files and the database, fix the configuration, test through the hosts file, switch DNS, issue the certificate, check redirects and mail, wait a week, close the old account. The domain side of a move, with the registrar and the transfer code, is in Moving a website: domain and hosting.

Article author: Arthur Isaev