Operations

How to back up a VPS before an upgrade

The upgrade is the easy part. The rollback is where most people find out they skipped a step. If you run a production service on a VPS and you are about to move from Ubuntu 22.04 to 24.04, or bump PHP from 8.1 to 8.3, or even apply a major kernel update, the first thing you do is back up the VPS before the upgrade. Not after you see the first error. This guide walks through the full backup routine: a provider-level snapshot, a database dump, a copy of every config file, and a verification step that proves the backup actually restores.

Prerequisites

  • A Linux VPS, this guide uses Ubuntu 24.04 LTS but the commands work on Debian 12, AlmaLinux 9 and Rocky Linux 9 with minor package-name changes.
  • Root access or a user with sudo privileges.
  • Enough free disk space to hold the backup, usually 1.5x the size of the data you are dumping.
  • Access to your VPS provider control panel for snapshots, if you rent a VPS from a provider that offers them.
  • SSH access from your workstation to copy files off the server.

Why backing up before an upgrade matters

Every major upgrade changes system libraries, package versions, and configuration formats. Nginx 1.24 configs load fine on 1.26, but a MariaDB major version bump can change the data directory format. PHP 8.3 removed deprecated functions that your application still calls. A kernel update can break a third-party module you compiled by hand. When that happens, you want a known-good state to return to, not a half-finished migration that you have to untangle at 2 AM.

A snapshot gives you that state at the disk level. It captures the entire filesystem, the bootloader, the package database, everything. If the upgrade breaks, you revert the snapshot in the control panel and the server is exactly where it was before you started. This is the single most important safety net. Database dumps and config backups are the second layer, they protect you in cases where a snapshot is not available, such as a single-volume server with no provider snapshot support, or when you only need to restore one service, not the whole machine.

Step 1: Take a provider-level snapshot

If your VPS provider offers snapshots, use them. A snapshot is a full copy of the virtual disk, taken while the server is running or after a clean shutdown. Most providers, including thueVPS, let you create one from the control panel in a few clicks. The process is identical across providers: go to the VPS management page, find the snapshot or backup section, name the snapshot, and click create.

Before you take the snapshot, flush the filesystem so the on-disk state matches what is in memory:

sync
sudo fsfreeze -f /var/lib/mysql

The sync command forces pending writes to disk. fsfreeze works on the filesystem level and is useful if you run a database like MySQL or PostgreSQL. You can skip fsfreeze if you are about to shut the server down anyway. A clean shutdown is actually the safest path:

sudo shutdown -h now

With the server off, take the snapshot from the control panel, then boot the server again. This guarantees a consistent disk state, no partially written transactions, no half-updated package files. The downtime is a few minutes, which is acceptable before a maintenance window.

Verify the snapshot exists and note its ID:

# Check from the control panel, or via the provider API
curl -s -H "Authorization: Bearer $API_TOKEN" \
  https://api.yourprovider.com/v1/snapshots | jq .

Expected output: a list that includes the snapshot you just created, with a timestamp and a status of "available" or "completed". If you do not have API access, the control panel displays the same information. Write down the snapshot ID and the date. You will need it if the upgrade fails.

Step 2: Dump your databases

Snapshots protect the whole disk, but a database dump is the format you can actually use to restore a single table or move data to a new server. If you run MySQL or MariaDB:

mysqldump --single-transaction --quick --all-databases \
  --result-file=/root/backup/all-databases-$(date +%F).sql

--single-transaction gives a consistent snapshot without locking tables, which matters on a live server. --quick streams the output row by row instead of buffering it all in memory. The result file lands in /root/backup/. For PostgreSQL:

sudo -u postgres pg_dumpall > /root/backup/postgres-all-$(date +%F).sql

Compress both dumps. Raw SQL files are bulky and the compression is cheap:

gzip /root/backup/all-databases-*.sql
gzip /root/backup/postgres-all-*.sql

Verify the dump is valid before you trust it. Try restoring into a scratch database, or at least inspect the file:

gzip -dc /root/backup/all-databases-*.sql.gz | head -n 20
# Should show CREATE TABLE statements and INSERT rows, not error messages

A quick integrity check for MySQL dumps:

gzip -dc /root/backup/all-databases-*.sql.gz | mysql --no-defaults --force

This applies the dump to your running server, which you do not want to do right before an upgrade. Instead, restore into a temporary database name, or just check that the file ends with Dump completed:

gzip -dc /root/backup/all-databases-*.sql.gz | tail -n 5

Step 3: Back up configuration files

Configuration files are small, but they are the part people forget. After a failed upgrade, you can reinstall a package, but you cannot guess what values you had in /etc/nginx/nginx.conf or /etc/php/8.3/fpm/pool.d/www.conf. Copy the entire /etc directory, or at least the parts that matter:

sudo tar czf /root/backup/etc-$(date +%F).tar.gz \
  /etc/nginx /etc/apache2 /etc/php /etc/mysql \
  /etc/postgresql /etc/redis /etc/systemd/system \
  /etc/ssh /etc/ssl /etc/letsencrypt

This covers web servers, PHP, databases, Redis, your custom systemd units, SSH config, and SSL certificates. Adjust the path list to match what your server actually runs. If you self-host n8n or GitLab, add their directories too:

sudo tar czf /root/backup/app-config-$(date +%F).tar.gz \
  /etc/nginx /etc/letsencrypt \
  ~/.n8n /var/opt/gitlab

List the archive contents to confirm nothing is missing:

tar tzf /root/backup/etc-$(date +%F).tar.gz | grep nginx

Expected output: the full path of every nginx file that was included. If the grep returns nothing, you missed the path in the tar command.

Step 4: Copy backups off the server

A backup on the same disk as the server is not a backup. If the disk fails during the upgrade, or you accidentally wipe the partition, everything is gone. Copy the backup directory to another machine. From your workstation:

scp -r root@your-server-ip:/root/backup ./vps-backup-$(date +%F)

Or use rsync over SSH, which resumes interrupted transfers and verifies checksums:

rsync -avz --progress \
  root@your-server-ip:/root/backup/ \
  ~/vps-backup-$(date +%F)/

For an object-storage target, install the CLI and push the files:

rclone copy /root/backup remote:backup-vps --progress

Verify the remote copy by listing it and checking file sizes match:

ls -lh ~/vps-backup-$(date +%F)/
# Compare with the sizes shown on the server
ssh root@your-server-ip "ls -lh /root/backup/"

File sizes and modification times should line up. If they do not, the transfer was incomplete and you need to rerun it.

Step 5: Record the current package state

Sometimes the fastest rollback is not a snapshot, but reinstalling the exact package versions you had before. On Debian and Ubuntu, dump the installed package list:

dpkg --get-selections > /root/backup/packages-$(date +%F).txt
apt-mark showmanual >> /root/backup/packages-$(date +%F).txt

On AlmaLinux and Rocky:

dnf list installed > /root/backup/packages-$(date +%F).txt

This file tells you what was installed and which packages were manually selected, as opposed to pulled in as dependencies. If you decide to rebuild instead of restoring a snapshot, this list is your map.

Step 6: Test the restore procedure

A backup you have never restored is a hope, not a plan. At minimum, verify the snapshot can boot. Most providers let you create a new VPS from a snapshot. Spin up a throwaway instance from the snapshot, log in, and check that your application starts:

systemctl status nginx
curl -I http://localhost

For the database dumps, restore into a temporary database on the test instance:

mysql -e "CREATE DATABASE restore_test;"
gzip -dc /root/backup/all-databases-*.sql.gz | \
  mysql restore_test

Then confirm the row count in a key table:

mysql -e "SELECT COUNT(*) FROM restore_test.users;"

If the count matches what you see on production, the dump is trustworthy. Delete the test instance when you are done. This whole test takes fifteen minutes and saves you from discovering, during the actual outage, that your backup was corrupt.

Step 7: Run the upgrade with a rollback plan

You have a snapshot, database dumps, config archives, and a tested restore path. Now you can upgrade. Run the package update, then the distribution upgrade:

sudo apt update
sudo apt full-upgrade
sudo apt dist-upgrade

Watch the output for prompts about config file changes. When apt asks whether to keep or replace a modified config file, the safe answer is usually N, keep the current version, then review the diff later. After the upgrade completes, reboot:

sudo reboot

Verify the system comes back healthy:

uptime
systemctl --failed
ss -tlnp | grep -E ':80|:443'

Expected output: a fresh uptime (a few minutes, not days), no failed services, and your web ports listening. If any service failed, check its logs:

journalctl -u nginx -n 50 --no-pager

If the upgrade broke something you cannot fix in a reasonable time, roll back. Delete the upgraded VPS and restore from the snapshot in the control panel. That is the entire point of the backup work. Do not spend hours fighting a broken upgrade when a known-good image is one click away.

Troubleshooting common backup problems

mysqldump fails with "Permission denied"

The mysql user needs read access to the data directory. Run the dump as root or with sudo:

sudo mysqldump --single-transaction --all-databases > /root/backup/dump.sql

Snapshot taken while server was running is inconsistent

If you could not shut down the server, use fsfreeze to flush databases, or run mysqldump with --single-transaction first. An inconsistent snapshot can have a corrupted database that only shows up on restore.

scp or rsync times out on large backups

Large database dumps can exceed the default SSH timeout. Use rsync with the --partial flag to resume, or run the transfer inside a tmux session so it survives a dropped connection.

tmux new -s backup-transfer
rsync -avz --partial root@your-server:/root/backup/ ~/vps-backup/

FAQ

Can I rely on a snapshot alone without database dumps?

For a full rollback, yes, a snapshot restores the entire disk. But dumps are still worth taking. They let you restore a single table, move data to a fresh install, and verify the data is intact before you trust the snapshot. Snapshots and dumps cover different failure modes.

How long does a VPS snapshot take?

Most providers complete a snapshot in under a minute per 10 GB of disk, but it depends on the provider and the storage backend. NVMe-based infrastructure, like thueVPS uses, is faster than spinning disks. Plan for 2 to 5 minutes for a typical 20 to 50 GB VPS.

Should I stop the server before taking a snapshot?

If you can afford a few minutes of downtime, yes. A clean shutdown guarantees a consistent disk state. If you cannot stop the server, flush the filesystem with sync and use fsfreeze on database directories before taking the live snapshot.

How many backups should I keep before an upgrade?

Keep at least two: one snapshot taken immediately before the upgrade, and the previous one if it exists. After the upgrade runs for a week without issues, you can delete the older snapshot. Keep the database dumps for a month as a safety net.

What if my provider has no snapshot feature?

Back up the entire disk with dd or rsync to another server:

rsync -aAXv --exclude=/dev --exclude=/proc \
  --exclude=/sys --exclude=/tmp / root@backup-server:/backup/

This gives you a bootable copy in most cases, but test it on a separate instance before you rely on it.

Related articles

VPS 升级前备份要点

升级 VPS 前必须先做快照和数据库备份。快照恢复整个磁盘状态,数据库转储用于恢复单个表或迁移数据。配置文件备份让你能快速重建服务。备份必须复制到远程机器,并测试恢复流程。这些操作适用于 Ubuntu 24.04、Debian 12 等主流系统,也适用于越南 VPS 服务商提供的 NVMe 存储实例。

Note: This guide is for general reference. Every system and infrastructure has its own specifics, so test each step in a safe environment and consult a qualified engineer before applying it in production.