Moving a site to a BLACKBOX server
A migration plan from another provider: copying the files and the database, testing, and switching DNS without downtime.
On this page
This guide describes how to move a site from another provider to a BLACKBOX server with the shortest possible interruption for visitors: taking inventory, copying the files and the database, testing on your computer, and switching DNS. You run the server commands over SSH; a few checks you do on your own computer. You'll find the new server's address in the app.blackbox.md panel, on the “My Servers” page (app.blackbox.md/my-servers, sidebar → “Infrastructure” → “My Servers”), in the “IP” field.
Available to: anyone with root SSH access to a BLACKBOX server who can change the domain's DNS. Migration done by the BLACKBOX team: on request, through support (see the last section).
The blackbox.md website is available in Romanian and Russian; this article quotes the Romanian labels with their English meaning.
The plan at a glance
| Stage | When |
|---|---|
| 1. Inventory of the site | before you order the server |
| 2. DNS TTL lowered to 300 | at least 48 hours before the switch |
| 3–5. The new server, the files, the database | after the server is activated |
| 6. Test through the hosts file | before the switch |
| 7. Final sync and DNS change | on the day of the switch |
| 8. Checks, with the old server still running | for a few days after the switch |
Until stage 7, visitors use the old server. The only downtime is the final sync, while the old site is in maintenance mode.
Step 1. Take inventory
| What to note | How to find it and why it matters |
|---|---|
| The site's files | the directory (for example public_html) and its size: choose a plan with enough disk space |
| Databases | the type (MySQL/MariaDB or PostgreSQL), name, user, size |
| PHP or Node.js versions | php -v, php -m (the modules), node -v: install the same versions |
| Web server | nginx or Apache; nginx does not read .htaccess, so the rules in it must be rewritten in the nginx configuration |
| Configuration files | wp-config.php, .env, config.php: the database host, passwords, paths |
| Cron jobs | crontab -l or the cron section in the old hosting's control panel |
| where the mailboxes are and what the MX record points to (see the “Email” section) | |
| SSL certificate | Let's Encrypt or commercial; you copy a commercial certificate over, together with its private key |
| DNS | who manages it: that is where you change the TTL and the address |
On the old server, if you have SSH access (OLD_PATH is the site's directory):
du -sh OLD_PATH
php -v
php -m
crontab -lOn shared hosting, the site's PHP version may differ from the one php -v shows: check it in the hosting control panel as well.
On your computer, find out who manages the DNS (NS) and where email is delivered (MX). Linux or macOS:
dig +short NS DOMAIN
dig +short MX DOMAINWindows:
nslookup -type=NS DOMAIN
nslookup -type=MX DOMAINThen choose the plan and the operating system (VPS plans: how to choose, Available operating systems). The disk must also have room for the export files. The PHP version in the standard repositories:
| System | PHP |
|---|---|
| Ubuntu 24.04 LTS / 22.04 LTS / 20.04 LTS | 8.3 / 8.1 / 7.4 |
| Debian 12 / Debian 11 | 8.2 / 7.4 |
| AlmaLinux 9, CentOS Stream 9 | 8.0; newer versions as modules (dnf module list php) |
Step 2. Lower the TTL 48 hours in advance
The TTL tells DNS servers around the world how long to keep an answer in their cache. At least 48 hours before the switch, set the TTL of the A records (and of the AAAA or CNAME records, if there are any) for DOMAIN and www to 300 seconds. Do not change the IP address yet. Check the result at the domain's name server (NS_SERVER is one of the names returned by the NS command above); the number after the name is the TTL:
dig +noall +answer DOMAIN A @NS_SERVEROn Windows, look for the ttl = line in the output:
nslookup -debug -type=A DOMAIN NS_SERVER- If you have connected your Cloudflare or GoDaddy account on the panel's “DNS” page, click the pencil (“Edit”) on the record's row, choose the TTL from the list and click “Save”: on Cloudflare, 300; on GoDaddy, the lowest value in the list is 600 (10 minutes). See Managing DNS records from the panel. With another DNS provider, change the TTL in that provider's control panel.
- On Cloudflare, “Proxied” records (the “Proxied” checkbox in the panel) have an automatic TTL, and an IP address change takes effect almost immediately. With the “Full (strict)” SSL mode, the new server needs a valid certificate from the moment of the switch: the simplest option is to set the records to “DNS only” for the duration of the move and turn the proxy back on once HTTPS works.
Important If you skip this step, some visitors may keep reaching the old server long after the switch: for as long as the old TTL, sometimes 86400 seconds (one day). After 48 hours, DNS servers have picked up the TTL of 300, and the new address reaches visitors in about 5 minutes (10 minutes with a TTL of 600).
Step 3. Prepare the new server
- Order the server and connect to it: Connecting to your server over SSH (Windows, macOS, Linux).
- Install the web server and the language your application runs on: Web server with HTTPS: nginx or Apache and Let's Encrypt, WordPress on LEMP (nginx, MariaDB, PHP), Node.js, Python and other services: nginx as a reverse proxy or Installing Docker and Docker Compose.
- Install the database server and create the database and the user: Databases: MariaDB/MySQL and PostgreSQL. If you use the same names and passwords as on the old server, you have less to change.
- Create the web server configuration for
DOMAINandwww.DOMAIN. You get the Let's Encrypt certificate in step 7.
The network filtering managed by BLACKBOX allows SSH (22), HTTP (80), HTTPS (443) and ping by default. Keep the database on the same server as the site; for other ports, write to support (Firewall: network filtering and ufw/firewalld on the server).
Step 4. Copy the files
Directly from the old server (recommended)
The new server pulls the files from the old one. Connect to the new server and start a tmux session, so the copy keeps running even if your connection drops:
tmux new -s migrareIn the session, run the copy; you'll be asked for the old server's password (on the first connection, confirm with yes first):
mkdir -p /var/www/DOMAIN
rsync -avzP root@OLD_SERVER_IP:OLD_PATH/ /var/www/DOMAIN/The trailing slash in
OLD_PATH/copies the contents of the directory, not the directory itself.If you are not
rootat the old provider, use the user that provider gave you.If the old provider's SSH uses a port other than 22 (
PORT), add it with-e. Do the same for thersynccommands in step 5.rsync -avzP -e "ssh -p PORT" root@OLD_SERVER_IP:OLD_PATH/ /var/www/DOMAIN/If you log in there with a key from your computer, load the key into
ssh-agent(Generating an SSH key (Windows, macOS, Linux)) and connect to the new server with-A, so thatrsyncuses the key without your having to copy it to the server:ssh -A root@SERVER_IPLeave the session with Ctrl + B, then D; return to it with
tmux attach -t migrare. Iftmuxorrsyncis missing, install them as shown in Transferring files to the server (scp, rsync, SFTP).
Through your computer
If the old provider offers only FTP or a file manager, download the files (or an archive from the hosting control panel) to your computer and upload them to the new server with rsync, scp or an SFTP client, as described in Transferring files to the server (scp, rsync, SFTP).
Finally, give ownership of the files to the web server user. On Ubuntu and Debian:
chown -R www-data:www-data /var/www/DOMAINOn AlmaLinux and CentOS Stream, the user is nginx or apache, and SELinux requires the correct labels: the details are in the same article on transferring files.
Step 5. Move the database
MySQL or MariaDB
On the old server (--single-transaction makes a consistent copy without stopping the site; if you only have phpMyAdmin, use its export in SQL format):
mysqldump --single-transaction --routines --triggers -u DATABASE_USER -p DATABASE_NAME | gzip > DATABASE_NAME.sql.gzOn the new server, after you have created the database and the user, fetch the file from the old user's home directory and import it:
rsync -avP root@OLD_SERVER_IP:DATABASE_NAME.sql.gz /root/
gunzip < /root/DATABASE_NAME.sql.gz | mysql DATABASE_NAMEPostgreSQL
On the old server:
pg_dump -Fc -h localhost -U DATABASE_USER DATABASE_NAME > DATABASE_NAME.dumpOn the new server, the database must be owned by the application's user. If you haven't created them yet (the first command asks for the new user's password):
sudo -u postgres createuser --pwprompt DATABASE_USER
sudo -u postgres createdb -O DATABASE_USER DATABASE_NAMEFetch the export and restore it; with --role, the tables belong to the application's user:
rsync -avP root@OLD_SERVER_IP:DATABASE_NAME.dump /tmp/
sudo -u postgres pg_restore --no-owner --no-acl --role=DATABASE_USER -d DATABASE_NAME /tmp/DATABASE_NAME.dumpAfter the final sync (step 7), delete the export files from both servers.
Update the application's configuration
| Application | File | What to check |
|---|---|---|
| WordPress | wp-config.php |
DB_NAME, DB_USER, DB_PASSWORD, DB_HOST |
Laravel and other applications with .env |
.env |
DB_HOST, DB_DATABASE, DB_USERNAME, DB_PASSWORD |
| Others | their configuration file | the database host, name and password, absolute paths |
The database host usually becomes localhost (on shared hosting it was often a different server). To find old paths left in the files, use the command below. Then clear the application's cache, if it has one.
grep -rl "OLD_PATH" /var/www/DOMAINStep 6. Test through the hosts file
The hosts file points the domain to the new server only on your computer; other visitors still see the old site. Add this line at the end of the file:
SERVER_IP DOMAIN www.DOMAINWindows
In the Start menu, type “Notepad”, right-click the app and choose “Run as administrator”.
Open
C:\Windows\System32\drivers\etc\hosts(in the Open dialog, choose to show all files,*.*), add the line and save.In PowerShell, clear the DNS cache and check: the
pingoutput must showSERVER_IP.ipconfig /flushdns ping -n 1 DOMAIN
macOS and Linux
Open the file, add the line, save with Ctrl + O, Enter, and exit with Ctrl + X:
sudo nano /etc/hostsOn macOS, clear the DNS cache:
sudo dscacheutil -flushcache sudo killall -HUP mDNSResponderCheck: the output must show
SERVER_IP.ping -c 1 DOMAIN
What to test
Reopen your browser and check everything visitors use: the main pages, the admin area, forms, image uploads, search, the cart and checkout. The new server does not have a certificate for the domain yet, so at https:// the browser shows an error or a security warning: during this test, that is normal. If the site switches to https:// on its own and the browser won't let you continue, install the current certificate from the old server on the new server (step 7, item 6). Do not start the cron jobs on the new server yet, so that it doesn't send emails or process orders in parallel with the old server.
After the test, delete the line from the hosts file and clear the DNS cache again.
Step 7. Final sync and switchover
Stop changes on the old site (the application's maintenance mode or a temporary page), so that no new orders or comments are lost.
Run the
rsynccommand from step 4 again: it copies only the files that have changed.Export and import the database again, as in step 5. An export made with
mysqldumpreplaces the existing tables on import; when you export from phpMyAdmin, enable the option to addDROP TABLEstatements. For PostgreSQL, add--clean --if-existstopg_restore.At your DNS provider, change the value of the A records for
DOMAINandwwwtoSERVER_IP(a CNAMEwww→DOMAINcan stay as it is). Delete the old hosting's AAAA records. Do not change the MX and TXT records (the exceptions are in the “Email” section). The steps: How to point your domain to the server.After about 5 minutes (10 minutes with a TTL of 600), check that the answer is
SERVER_IP. Linux or macOS:dig +short DOMAIN A @1.1.1.1Windows:
nslookup DOMAIN 1.1.1.1Get the Let's Encrypt certificate right away (with Apache, use
--apacheinstead of--nginx; to install certbot, see Web server with HTTPS: nginx or Apache and Let's Encrypt):certbot --nginx -d DOMAIN -d www.DOMAINUntil then, visitors who already reach the new server over HTTPS see a warning. To avoid this gap, install the current certificate and its key, copied from the old server, on the new server before the switch. A commercial certificate is moved this way in any case.
Start the cron jobs on the new server and stop them on the old one.
Watch the web server logs (with Apache:
/var/log/apache2/on Ubuntu and Debian,/var/log/httpd/on AlmaLinux and CentOS Stream) and the application's logs:tail -f /var/log/nginx/access.log /var/log/nginx/error.log
Step 8. After the switch
- Watch the old server's access log: when visitors stop arriving and you see only the occasional bot, everyone is using the new server.
- Keep the old hosting active for a few days and check the forms, payments, the emails the site sends, and the cron jobs.
- Set the TTL of the records back to 3600.
- Set up backups: BLACKBOX does not make automatic backups of your server. See Backup strategy for your server.
Irreversible Canceling the old hosting usually deletes the files, databases and mailboxes there permanently. Cancel it only after everything works on the new server, your email has been moved (if it was hosted there too) and you have a final copy of the old site.
Email does not move together with the site. The MX record you found in step 1 tells you what to do:
| Situation | What to do |
|---|---|
| Email is with a separate provider (for example Google Workspace or Microsoft 365) | Do not change the MX and TXT records. Change only the A records for DOMAIN and www. |
Email is at the old hosting, and MX points to a separate name with its own A record (for example mail.DOMAIN) |
Change neither the MX record nor that name's A record. Email keeps working as long as the old hosting is active. |
MX points to DOMAIN itself or to a name that is a CNAME to DOMAIN |
Changing the A record would also move email delivery. Ask the old provider for the name of its mail server and point MX to it before the switch, so that your email stays with that provider. |
| You want to move the mailboxes too | A mail server on a VPS needs ports (25, 465, 587, 993) that are not open by default in the network filtering: ask support first. The BLACKBOX team can also move the mailboxes, on request. |
If the site sends emails (forms, notifications), configure it to send them through your email provider's SMTP server, with a username and password, not directly from the new server.
Warning If your email is hosted elsewhere, do not change the MX records: new messages would be sent to a server that has no mailboxes and would no longer reach you.
Migration by the BLACKBOX team
The page “Migrare gratuită de la alți furnizori” (Free migration from other providers), at blackbox.md/solutions/migration (the “Soluții” (Solutions) menu → “Migrarea proiectelor” (Project migration)), describes the on-request migration service: files, databases, control panels, email and the DNS switch. For new customers with a paid VPS or hosting plan, migrating a single VPS, hosting account or control panel to a new BLACKBOX service is advertised as free; complex projects get a separate quote. The team confirms the exact terms during the assessment.
Click “Cere o evaluare gratuită” (Request a free assessment) on that page or write to us directly with the site's address, the old provider and what needs to be moved: Professional services on request: administration, DevOps, migration, How to contact BLACKBOX support.
Frequently asked questions
The MySQL import stops with the error Unknown collation: 'utf8mb4_0900_ai_ci'.
The export comes from MySQL 8, and the new server runs MariaDB, which doesn't know this collation. Replace it in the file and import again:
gunzip /root/DATABASE_NAME.sql.gz
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' /root/DATABASE_NAME.sql
mysql DATABASE_NAME < /root/DATABASE_NAME.sqlOn the new server, only the home page opens; the other pages return 404.
The rules in .htaccess don't work with nginx. For WordPress and most PHP applications, the nginx configuration needs try_files $uri $uri/ /index.php?$args;: see WordPress on LEMP (nginx, MariaDB, PHP).
Can I keep the IP address from my old provider? No. The BLACKBOX server has its own IPv4 address; that is why the DNS records change. You don't need to change the domain's name servers (NS).
I ordered a “VPS hosting” plan with a control panel. Does this guide apply? The stages (inventory, TTL, test, switch) are the same, but the site is created through the installed panel. Ask support which panel your server has and how to import the site: “VPS hosting” plans with a control panel.