Downtime during a move is almost never the copying. It is changing DNS before the new server is ready, and it is a TTL nobody lowered.

A week before: lower the TTL

TTL is how long the world caches your DNS. At 86400 it takes a day for a change to reach everyone; at 300 it takes five minutes. Lower it a day ahead - the old value has to expire before the new one is believed.

yourdomain.com.  300  IN  A  1.2.3.4

Build the new server while the old one serves

  1. Copy the files — rsync, twice: once for the bulk, once at cutover for what changed.
  2. Copy the database — A dump now, another at cutover.
  3. Point your own machine at the new server — Edit your hosts file. You see the new site; the world still sees the old one.
  4. Test everything — Log in, place an order, send a mail, upload a file. Every path that touches disk or mail.
# hosts file\n1.2.3.4  yourdomain.com www.yourdomain.com

Cutover

  1. Put the OLD site in read-only or maintenance — Minutes, not hours.
  2. Sync the last changes — rsync again, and a fresh database dump.
  3. Change the DNS record
  4. Watch both servers — The old one keeps answering while caches expire. Do not turn it off.
Leave the old server running for at least 48 hours. Some resolvers ignore a low TTL, and a visitor who lands on a switched-off server sees nothing at all.

The two that catch people

  • Mail. MX records are separate from the A record. Moving the site does not move the mail, and forgetting them loses messages silently.
  • Cron jobs. They do not travel with the files. A backup that stops running is not noticed until it is needed.
EGPHP migrates for you, free, with the checks above. If you are doing it yourself, write the cutover steps down first and follow the list - not your memory, at midnight.