How to Migrate VPS from Another Provider to Hostini with Zero Downtime
Technical guide to migrate VPS from Vultr, DigitalOcean or Contabo to Hostini using rsync, low DNS TTL and cutover with no maintenance window.
Migrating a VPS between providers looks risky when you have a production application running, but the operation is deterministic when it follows a runbook. The real risk is not in the commands — it’s in skipping validations or underestimating DNS TTL. This tutorial covers the full process to move your VPS from Vultr, DigitalOcean, Contabo, or similar providers to Hostini, with a downtime window measured in seconds.
The approach uses incremental rsync to synchronize files while the old application keeps serving traffic, reduces DNS TTL to speed up cutover propagation, and validates everything via local /etc/hosts before making the change public. Target persona: you run a Linux VPS (Ubuntu/Debian/Rocky) with a web application, database, and possibly a stack like Nginx + PHP-FPM, Node.js, or Docker.
Estimated time: 2-4 hours, with 30-45 minutes of active execution and the rest waiting for rsync and DNS propagation. The downtime perceived by end users typically stays under 2 minutes.
Prerequisites
SSH access with sudo on the source VPS (current provider) and on the destination Hostini VPS. Access to your DNS control panel (Cloudflare, Registro.br, etc) to adjust TTL and A records. A list of what is running: systemd services, open ports, data paths (web root, database, configs).
Before touching any server, document the current state. Run systemctl list-units --type=service --state=running on the source and save the output. Note down versions: nginx -v, php -v, mysql --version, node -v. List cron jobs with crontab -l and ls /etc/cron.d/. This inventory is what you will replicate.
60s 24h before 30s-2min incremental rsync Provision the destination VPS on Hostini
The new VPS should mirror the source operating system on the same major version. If the source runs Ubuntu 22.04, pick Ubuntu 22.04 — jumping OS versions in the middle of a migration adds incompatibility variables (libraries, config paths) you don’t need to carry.
On the Hostini panel, order the VPS with specs equal to or greater than the source. Same OS family (Ubuntu/Debian/Rocky) and same LTS version. Note the new public IP.
ssh root@NEW_HOSTINI_IPConfirm connectivity and switch to a non-root user for subsequent work.
Install the exact same packages from the source on the new VPS. On Ubuntu/Debian, use the list you documented:
sudo apt update
sudo apt install -y nginx mysql-server php8.3-fpm php8.3-cli redis-serverFor Rocky/AlmaLinux, adjust to dnf install. Make sure the PHP, Node, or any critical runtime version matches exactly — a minor version difference can break application dependencies.
Configure the firewall with the same ports as the source. If you use UFW:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableDon’t forget custom ports (e.g., 8080 for an app, 6379 for exposed Redis). Comparing against ss -tlnp on the source is the source of truth.
Reduce the DNS TTL
This step must be done 24 hours before the cutover. The current TTL of your A record determines how long DNS resolvers around the world will cache the old IP after you point to the new one. A default TTL of 3600s (1 hour) or 86400s (1 day) means downtime measured in hours for some visitors.
On your DNS provider (Cloudflare, Registro.br, Route53, etc), edit the A and AAAA records of the domain. Change the TTL to 60 seconds.
If you use Cloudflare with the orange proxy enabled, TTL is controlled by Cloudflare (not your value) — but adjust it to “Auto” anyway and disable the proxy temporarily on cutover day to observe real propagation.
Reducing TTL has no immediate effect — resolvers will only pick up the new value after the old TTL expires. If the record had a TTL of 3600s, wait at least 1 hour. For an old TTL of 86400s, wait 24h to be safe.
Sync data with rsync
rsync with the application running is safe for static files (web root, uploads, configs), but requires care with databases — sync database files via mysqldump/pg_dump, not via direct copy of the table files.
From the source VPS, transfer the web root and nginx configs to Hostini:
rsync -avz --progress \
/var/www/ \
root@NEW_HOSTINI_IP:/var/www/
rsync -avz --progress \
/etc/nginx/ \
root@NEW_HOSTINI_IP:/etc/nginx/The -a flag preserves permissions, owners, and timestamps. -v shows progress. -z compresses during transfer — useful for text files, neutral for already-compressed binaries.
For MySQL/MariaDB databases, use dump + restore (never copy /var/lib/mysql directly between different servers):
mysqldump --single-transaction --routines --triggers \
--all-databases > /tmp/backup.sql
rsync -avz /tmp/backup.sql root@NEW_HOSTINI_IP:/tmp/On the new VPS:
ssh root@NEW_HOSTINI_IP
mysql < /tmp/backup.sqlThe --single-transaction flag avoids table locks during the dump on transactional engines (InnoDB), letting the application keep serving requests.
Copy Let’s Encrypt TLS certificates preserving the original permissions:
rsync -avz --progress \
/etc/letsencrypt/ \
root@NEW_HOSTINI_IP:/etc/letsencrypt/The certificates remain valid on the new IP because they are bound to the domain, not the IP. After cutover, install certbot on Hostini and the renewal cron takes over normally.
Enable and start the services on the new VPS with the migrated configuration:
sudo systemctl enable --now nginx php8.3-fpm mysql
sudo systemctl status nginxCheck each service log with journalctl -u nginx --since "5 min ago" to confirm nothing exploded on boot.
Validate before the cutover
This is the step that separates a smooth migration from a chaotic one. You will test the new VPS as if it were already production, without touching the public DNS — only your local /etc/hosts.
On your computer (not the server), edit /etc/hosts adding a line that points your domain to the new IP:
sudo nano /etc/hostsAdd at the end:
NEW_HOSTINI_IP yourdomain.com www.yourdomain.comNow your browser will resolve yourdomain.com to the new IP just for you. Open the site in an incognito window, test login, navigation, forms. If something breaks, the old production server is still running intact.
Test in Chrome, Firefox, and Safari. Each one caches DNS differently. On mobile, configure /etc/hosts via apps like “Hosts Editor” on Android or a local SSH connection to validate the real UX.
Cutover: point DNS to the new IP
This is the transition moment. Before the switch, run a final rsync to capture any changes since the last sync. Ideally, put the application in maintenance mode for 30-60 seconds during this final rsync to guarantee consistency.
Final incremental rsync of files that may have changed:
rsync -avz --delete --progress \
/var/www/ \
root@NEW_HOSTINI_IP:/var/www/The --delete flag removes files at the destination that no longer exist at the source — useful if you cleared caches or logs.
Final database dump with the application in maintenance:
mysqldump --single-transaction --routines --triggers \
--all-databases > /tmp/final.sql
rsync -avz /tmp/final.sql root@NEW_HOSTINI_IP:/tmp/
ssh root@NEW_HOSTINI_IP "mysql < /tmp/final.sql"On the DNS panel, change the domain A record to point to the Hostini IP. Save. Remove the line from your local /etc/hosts that you added for testing — now you want to see real propagation.
Track propagation:
dig +short yourdomain.com @8.8.8.8
dig +short yourdomain.com @1.1.1.1When both return the new IP, most visitors are already landing on the Hostini VPS.
Post-cutover verification
Confirm everything is responding on the new infrastructure and nothing still depends on the old server.
curl -I https://yourdomain.com
The response should include Server: nginx (or whatever you configured), and the TCP socket IP should be the Hostini one. Verify with curl -v to inspect the TLS handshake and confirm the certificate is correct.
Monitor logs for a few hours:
sudo tail -f /var/log/nginx/access.log
Incoming traffic = cutover worked. If logs stay empty after 30 minutes, DNS propagation may be slow — some ISPs ignore TTL.
Troubleshooting
TLS certificate error after migration
Check that the certificate path in nginx still points to /etc/letsencrypt/live/yourdomain.com/. If you renamed directories during the migration, adjust ssl_certificate and ssl_certificate_key in the config. Test with sudo nginx -t before reloading.
Application can’t connect to the database
Confirm the database user exists on the new VPS with the same passwords. mysqldump exports data but doesn’t import mysql.user records by default — add --all-databases (already included in the commands above) or do a separate dump of mysql.user. Check /etc/mysql/my.cnf to make sure bind-address is correct.
Traffic keeps hitting the old VPS
Resolvers that ignore TTL can cache for hours. Keep the old VPS online for 48-72 hours after cutover as a safety net. Configure it to issue a 301 redirect to the new IP via Nginx — that way even visitors stuck on old cache end up where they should be.
Next steps
With the migration complete, focus on consolidating operations on the new infrastructure:
- Configure automatic backups on the new VPS — scheduled snapshots protect against operational errors
- Update monitoring (UptimeRobot, Better Stack) to point to the new endpoints
- Document the runbook you executed for the next migration — it evolves with each run
- After 7 stable days on Hostini, cancel the old VPS and remove the safety redirects
- Restore DNS TTL to a standard value (3600s or 86400s) — keeping it at 60s permanently puts extra load on resolvers
If you are putting production load on a VPS, a Hostini VPS offers NVMe SSD, native IPv6, and a network with volumetric attack protection — worth running comparative benchmarks during the parallel window between both servers to confirm a real performance gain.
Frequently asked questions
How much downtime should I expect from a well-executed migration?
With DNS TTL reduced to 60 seconds 24h before the cutover and services already replicated, real downtime falls between 30 seconds and 2 minutes. Most of it is DNS propagation across resolvers that honored the TTL — some ISPs ignore it and cache longer, but the window seen by most users is short.
rsync or full snapshot? Which method is safer?
rsync is safer for migrations between different providers because you sync files on the same operating system, without importing incompatible disk images. Snapshot/image only works well when both sides use the same format (raw/qcow2) and a compatible kernel version. For Vultr → Hostini or DigitalOcean → Hostini, rsync wins.
Do I need to stop the application during the initial rsync?
No. The first rsync copies the current state with the application running — it may catch inconsistent files (database, sessions), but its only job is to move the bulk of bytes. You then run incremental rsyncs that reconcile differences, and the final one (with the application stopped for 30-60s) guarantees final consistency.
How do I avoid the new IP being blocked due to bad reputation?
IPs of newly created VPSes sometimes inherit reputation from the previous owner. Before cutover, test against tools like MXToolbox and Spamhaus. If the IP is blacklisted, open a ticket asking for a replacement before migrating — it takes minutes and avoids post-migration email delivery problems.
Can I test the new VPS without touching DNS?
Yes. Add a line to your local /etc/hosts pointing the domain to the new Hostini IP. Your browser will resolve to that IP just for you, while the rest of the world keeps hitting the old server. This lets you validate TLS, application, and database before flipping the public switch.
How do I handle Let's Encrypt certificates during the transition?
Copy the entire /etc/letsencrypt/ directory via rsync — it includes private keys and active certificates. They remain valid until expiration and can be used on both servers in parallel. After cutover, install certbot on the new VPS and let automatic renewal take over the cycle.