Managed Hosting Cutover on Debian Without Downtime

What this cutover solves
Use this guide when you need to move a customer site, reseller account, or managed server service from one Debian 12/13 VPS to another with the least possible interruption. The goal is not just to copy files. You will prepare DNS, create a non-root administrator, sync content safely, validate the new host, and keep a rollback path open until the cutover is confirmed.
This is a practical fit for agency workflows, regional hosting moves, and support-led migrations on Hostperl VPS where you need clean handover, predictable maintenance windows, and a fast recovery path if something does not behave as expected.
Before you start
This procedure assumes:
- Debian 12 or Debian 13 on both servers.
- Root SSH access on the old and new servers.
- A domain name already pointing to the old server.
- Enough disk space on the new server for a full sync.
- rsync installed on both ends.
If your current service is managed through a panel, review WHM account operations that keep hosting moves clean and cPanel WHM license recovery for hosting moves if the move also includes licensing or control-panel changes. The file-sync and DNS principles here still apply.
1) Connect to the source server and identify the OS
On your local computer, open your first SSH session to the source server. Replace 203.0.113.10 with the real public IP assigned by your provider.
ssh root@203.0.113.10Keep this root session open. You will use it as your safety net while you prepare the new server.
On the VPS as root, confirm the operating system before you touch packages or firewall rules.
cat /etc/os-releaseYou should see Debian 12 or Debian 13 in the output. If you are not on Debian, stop here and follow a distribution-specific migration path instead.
2) Create a non-root admin on the new server
On your local computer, open a second terminal and connect to the new server.
ssh root@203.0.113.10Again, replace the documentation IP with the actual new server IP. Now set up your admin account before you make any access changes.
On the VPS as root, create the account, grant sudo access, and prepare SSH keys. Use the same account name Hostperl support teams often use in handovers: deploy.
adduser deployFollow the prompts to set a password for the new account. Then add it to the sudo group.
usermod -aG sudo deployCreate the SSH directory and lock down ownership and permissions.
install -d -m 700 -o deploy -g deploy /home/deploy/.sshCopy your public key into place. Replace the sample key text with your real key.
cat > /home/deploy/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyExampleKeyReplaceWithYourOwnKey comment
EOFSet restrictive permissions so SSH accepts the file.
chown deploy:deploy /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keysConfirm the account is ready.
ls -ld /home/deploy /home/deploy/.ssh
ls -l /home/deploy/.ssh/authorized_keysYou should see deploy as the owner and tight permissions on the SSH directory and key file.
3) Update packages and time sync
On the VPS as root, refresh package metadata and apply current security updates before the migration work begins.
apt update
apt -y upgradeInstall the tools you need for the move.
apt -y install rsync curl chronyEnable time sync so file timestamps and TLS validation behave properly during cutover.
systemctl enable --now chronyCheck that the service is active.
systemctl status chrony --no-pagerYou should see active (running). If the service fails, inspect the journal before proceeding.
journalctl -u chrony -n 50 --no-pager4) Prepare the destination layout
On the VPS as root, create the target directory structure. This example uses /opt/myapp as a generic application path because you may be moving a web app, customer portal, or support tool.
mkdir -p /opt/myapp/{current,backup,shared}
chown -R deploy:deploy /opt/myappCheck that the directories are present and owned by the admin user.
ls -ld /opt/myapp /opt/myapp/*If your service is static or proxied, a clean directory layout makes rollback much simpler.
5) Sync the live data with rsync
On the VPS as root, copy the current live data from the old server to the new one. Replace the source path with the real application or site path on the source host.
rsync -aHAX --numeric-ids --delete --info=progress2 root@203.0.113.10:/var/www/example/ /opt/myapp/current/This command preserves permissions, ACLs, extended attributes, and ownership. It also removes files on the new server that no longer exist on the source. That keeps the destination consistent with production.
Run a dry check after the first sync to catch obvious mismatches.
rsync -aHAX --numeric-ids --delete --dry-run root@203.0.113.10:/var/www/example/ /opt/myapp/current/If the dry run shows large unexpected deletes or missing directories, stop and inspect the source path before continuing.
6) Add a firewall before exposing the new server
On the VPS as root, install and enable UFW on Debian if it is not already present.
apt -y install ufw
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enableThis opens SSH, HTTP, and HTTPS before you point live traffic at the new host. Do not remove the old server from service until you can confirm the new one answers correctly.
Verify the firewall state.
ufw status verboseYou should see the three allowed services and an active firewall.
7) Set up Nginx as the new front end
For a managed hosting cutover, Nginx is often the cleanest front end because it can serve static files, reverse proxy app traffic, and give you clear logs for support. If your existing stack uses Apache, keep that unchanged unless the migration specifically includes a web server change. This tutorial stays focused on the cutover itself, not a web-server comparison.
On the VPS as root, install Nginx.
apt -y install nginxCreate a site configuration for the migrated service.
cat > /etc/nginx/sites-available/example.com <<'EOF'
server {
listen 80;
server_name example.com www.example.com;
root /opt/myapp/current/public;
index index.html index.php;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ /index.html;
}
}
EOFEnable the site and disable the default if you do not want it answering requests.
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
rm -f /etc/nginx/sites-enabled/defaultTest the configuration before any reload.
nginx -tA successful test ends with syntax is ok and test is successful. Then reload Nginx.
systemctl reload nginxCheck the service status.
systemctl status nginx --no-pagerIf Nginx refuses to start, inspect the syntax and logs first, not the firewall.
journalctl -u nginx -n 50 --no-pager8) Move SSL into place
Once the DNS cutover is ready, obtain a certificate with Let's Encrypt. You can do this before the final switch if the DNS record already points to the new host, or after you lower the TTL and are ready to flip traffic.
On the VPS as root, install Certbot and request a certificate for the live name.
apt -y install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.comCertbot will update the Nginx server block automatically. Re-test afterward.
nginx -t
systemctl reload nginxFor customers moving regional services, this is a useful point to review DNS and nameserver handling with the 2026 hosting buyer decision framework for real buyers and keep DNS changes predictable rather than rushed.
9) Lower DNS TTL before the cutover
On your DNS provider's control panel, reduce the A and AAAA record TTL for example.com and www.example.com to 300 seconds at least a few hours before the switch. This shortens propagation time and reduces the number of stale resolvers still pointing to the old server.
If you manage DNS through Hostperl services, the DNS and domain workflow usually becomes easier to coordinate during a migration. See Hostperl IP rental and DNS services if your move also involves a new address or region.
10) Do the final sync and freeze writes
On the source server, stop write-heavy services first. That may be your app worker, queue consumer, or database write path. The idea is to prevent a moving target during the last copy.
Then run a final rsync from the old host to the new host.
rsync -aHAX --numeric-ids --delete --info=progress2 root@203.0.113.10:/var/www/example/ /opt/myapp/current/If the app stores uploads or customer-generated files separately, copy those paths too. Keep the old server running until the new one answers correctly.
11) Check ownership, logs, and service health
On the VPS as root, confirm file ownership after the final sync.
find /opt/myapp/current -maxdepth 2 -printf '%u:%g %p
' | headThen review Nginx logs for a live request.
tail -n 20 /var/log/nginx/example.com.access.log
tail -n 20 /var/log/nginx/example.com.error.logIf your application needs a systemd service, enable and check it now. Replace myapp with your real service name.
systemctl enable myapp
systemctl status myapp --no-pagerFor app-service troubleshooting patterns, Nginx access logs for supportable app hosting is a useful companion reference.
12) Verify from the server and a client
On the VPS as root, check that Nginx is listening on the expected ports.
ss -tulpn | grep -E ':(80|443)\s'Then confirm the local HTTP response.
curl -I http://127.0.0.1You should see an HTTP 200, 301, or 302 depending on your redirect setup.
On your local computer, test the live domain once DNS begins to point to the new host.
curl -I https://example.comRun a functional smoke test too. For example, load the login page, submit a simple form, or open the customer dashboard. A green HTTP code alone is not enough for managed hosting work.
Rollback plan if the cutover fails
If the new server shows broken assets, login errors, or missing data, switch DNS back to the old server immediately. Because you lowered TTL earlier, the rollback should propagate faster than the original move.
On the old server, keep the source copy intact until the new host has run cleanly for at least one business cycle. If you must revert application data, reverse the rsync direction only after you confirm which side contains the correct writes.
rsync -aHAX --numeric-ids --delete --info=progress2 /var/www/example/ root@203.0.113.10:/var/www/example/Use this only when you are certain the source of truth is back on the old host. Reversing the wrong way can overwrite fresh customer data.
Troubleshooting the most common failures
SSH key rejected
Run this on the new server.
ls -ld /home/deploy /home/deploy/.ssh
ls -l /home/deploy/.ssh/authorized_keysIf permissions are too open or ownership is wrong, fix them with:
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keysNginx returns 403
Check whether the document root exists and whether the web user can read it.
ls -ld /opt/myapp/current /opt/myapp/current/public
namei -l /opt/myapp/current/publicCorrect the path or permissions if the web root is missing.
Certificate issuance fails
Check DNS resolution and port 80 access.
dig +short example.com
ufw status verbose
curl -I http://example.comIf port 80 is closed or the domain still points at the old server, fix DNS first, then rerun Certbot.
Old data still appears after the move
That usually means cached DNS, browser cache, or an upstream proxy. Confirm the target server is receiving traffic.
tail -f /var/log/nginx/example.com.access.logIf no requests appear, the client is still reaching the old host or a cache layer is in front of the new one.
Reboot persistence check
On the VPS as root, confirm that the services come back after reboot.
systemctl is-enabled nginx
systemctl is-enabled chrony
systemctl is-enabled myappIf all three show enabled, schedule a maintenance reboot only after the migration has been stable.
rebootAfter the server returns, reconnect and re-run:
systemctl status nginx chrony myapp --no-pager
ss -tulpn | grep -E ':(80|443)\s'That final check confirms the cutover survived a restart, which is what customers will experience later during routine maintenance.
If you need help moving a customer site, reseller account, or managed service without a rushed DNS window, Hostperl can help you plan the handoff and keep rollback options open. For migration-friendly infrastructure, start with Hostperl VPS hosting or a dedicated server hosting plan when the workload needs more predictable resources.
Our support team is used to real migration windows, not just green checkmarks. That matters when you are coordinating customers, email delivery, and live traffic at the same time.
FAQ
How long should I keep the old server online?
Keep it online until DNS has fully propagated and the new server has handled live traffic cleanly for at least 24 to 48 hours.
Should I switch DNS before or after the final rsync?
Do the final rsync first, then switch DNS. That reduces the chance of users landing on a partially synced destination.
Can I skip lowering TTL?
You can, but rollback becomes slower. Lowering TTL is a small step that saves time if the new server needs to be withdrawn.
What if my app uses a database?
Freeze writes, take a final database backup or dump, move the database separately, and verify the app connects before you point traffic at the new host.
Is this process suitable for agency clients?
Yes. It works well for agencies because it preserves a clear rollback path and keeps the client-facing cutover controlled.
