Pre-Upgrade Backup Checklist
System upgrades carry some risk; thorough backups are a prerequisite for a safe upgrade. The following checklist helps you prepare fully before upgrading.
Backup Priority
| Priority | Content | Reason |
|---|---|---|
| Highest | User data and databases | Cannot be recreated |
| High | System configuration files | Manually customized configs |
| Medium | Package lists and service states | Helps rebuild the environment |
| Low | Full system snapshot | Quick rollback |
1. User Data Backup
Personal Files
# Back up the entire home directory
sudo rsync -avzP /home/ /backup/home/
# Or pack with tar
sudo tar czf /backup/home-backup-$(date +%Y%m%d).tar.gz /home/
# Back up a specific user only
sudo rsync -avzP /home/username/ /backup/home-username/Database Backup
# MySQL / MariaDB
mysqldump -u root -p --all-databases > /backup/mysql-all-$(date +%Y%m%d).sql
# Single database
mysqldump -u root -p mydb > /backup/mysql-mydb-$(date +%Y%m%d).sql
# PostgreSQL
sudo -u postgres pg_dumpall > /backup/postgres-all-$(date +%Y%m%d).sql
# Single database
sudo -u postgres pg_dump mydb > /backup/postgres-mydb-$(date +%Y%m%d).sql
# Redis
redis-cli BGSAVE
sudo cp /var/lib/redis/dump.rdb /backup/redis-$(date +%Y%m%d).rdb
# MongoDB
mongodump --out /backup/mongodb-$(date +%Y%m%d)/
# SQLite
cp /path/to/database.db /backup/sqlite-$(date +%Y%m%d).dbWebsite and Application Data
# Web root directory
sudo tar czf /backup/www-$(date +%Y%m%d).tar.gz /var/www/
# Docker data volumes
docker volume ls
for vol in $(docker volume ls -q); do
docker run --rm -v ${vol}:/data -v /backup:/backup ubuntu \
tar czf /backup/docker-vol-${vol}-$(date +%Y%m%d).tar.gz -C /data .
done
# Docker Compose projects
cd /path/to/project && docker compose down
tar czf /backup/docker-project-$(date +%Y%m%d).tar.gz /path/to/project/2. System Configuration Backup
Key Configuration Files
# Pack the entire /etc directory
sudo tar czf /backup/etc-$(date +%Y%m%d).tar.gz /etc/
# Back up key configurations individually
sudo cp -a /etc/ssh/ /backup/ssh-config/
sudo cp -a /etc/nginx/ /backup/nginx-config/
sudo cp -a /etc/apache2/ /backup/apache2-config/
sudo cp -a /etc/netplan/ /backup/netplan-config/
sudo cp -a /etc/samba/ /backup/samba-config/
sudo cp -a /etc/fstab /backup/fstab
sudo cp -a /etc/hosts /backup/hosts
sudo cp -a /etc/crontab /backup/crontabCron Jobs
# System cron
sudo cp -a /etc/cron.d/ /backup/cron.d/
sudo cp -a /etc/crontab /backup/crontab
# User cron
crontab -l > /backup/crontab-$(whoami)-$(date +%Y%m%d).txt
# All users' cron jobs
for user in $(cut -d: -f1 /etc/passwd); do
cron=$(sudo crontab -u $user -l 2>/dev/null)
if [ -n "$cron" ]; then
echo "=== $user ===" >> /backup/crontabs-all.txt
echo "$cron" >> /backup/crontabs-all.txt
fi
doneCustom systemd Services
# Back up custom systemd service files
sudo tar czf /backup/systemd-custom-$(date +%Y%m%d).tar.gz \
/etc/systemd/system/*.service \
/etc/systemd/system/*.timer \
/etc/systemd/system/*.mount \
2>/dev/nullFirewall Rules
# UFW rules
sudo ufw status numbered > /backup/ufw-rules.txt
sudo cp -a /etc/ufw/ /backup/ufw-config/
# iptables rules
sudo iptables-save > /backup/iptables-$(date +%Y%m%d).rules
sudo ip6tables-save > /backup/ip6tables-$(date +%Y%m%d).rules3. System State Recording
Installed Packages
# Full package list
dpkg --get-selections > /backup/packages-selections-$(date +%Y%m%d).txt
# Manually installed packages (excluding auto-dependencies)
apt-mark showmanual > /backup/packages-manual-$(date +%Y%m%d).txt
# With version numbers
dpkg -l > /backup/packages-versions-$(date +%Y%m%d).txt
# Snap packages
snap list > /backup/snap-packages-$(date +%Y%m%d).txt
# Flatpak packages (if applicable)
flatpak list > /backup/flatpak-packages-$(date +%Y%m%d).txt 2>/dev/null
# pip packages
pip3 list > /backup/pip-packages-$(date +%Y%m%d).txt 2>/dev/nullAPT Source Configuration
# DEB822 format sources
sudo cp -a /etc/apt/sources.list.d/ /backup/apt-sources.list.d/
# APT keys
sudo cp -a /etc/apt/keyrings/ /backup/apt-keyrings/ 2>/dev/null
sudo cp -a /usr/share/keyrings/ /backup/usr-keyrings/ 2>/dev/null
# APT preferences
sudo cp /etc/apt/preferences.d/* /backup/apt-preferences/ 2>/dev/nullNetwork Configuration
# Network state
ip addr > /backup/ip-addr-$(date +%Y%m%d).txt
ip route > /backup/ip-route-$(date +%Y%m%d).txt
cat /etc/resolv.conf > /backup/resolv-conf-$(date +%Y%m%d).txt
ss -tlnp > /backup/listening-ports-$(date +%Y%m%d).txtRunning Services
systemctl list-units --type=service --state=running > /backup/services-running-$(date +%Y%m%d).txt
systemctl list-unit-files --state=enabled > /backup/services-enabled-$(date +%Y%m%d).txtKernel and Boot Information
uname -a > /backup/kernel-$(date +%Y%m%d).txt
cat /proc/cmdline > /backup/cmdline-$(date +%Y%m%d).txt
dpkg --list | grep linux-image > /backup/kernel-packages-$(date +%Y%m%d).txt4. Full System Backup
Using Timeshift
# Install Timeshift
sudo apt install timeshift -y
# Create a system snapshot (RSYNC mode)
sudo timeshift --create --comments "Pre-upgrade backup $(date +%Y%m%d)" --tags D
# List snapshots
sudo timeshift --listFull Disk Backup with rsync
# Full disk backup to an external drive
sudo rsync -aAXv --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/backup/*"} / /mnt/backup/full-system/Disk Image with dd
# Create a full disk image (should be done from a Live USB)
sudo dd if=/dev/sda of=/mnt/external/disk-image-$(date +%Y%m%d).img bs=4M status=progress
# Compressed image
sudo dd if=/dev/sda bs=4M status=progress | gzip > /mnt/external/disk-image-$(date +%Y%m%d).img.gzLVM Snapshots
# If using LVM, create a logical volume snapshot
sudo lvcreate -L 10G -s -n root-snap /dev/vg0/root
# After a failed upgrade, you can restore from the snapshot
sudo lvconvert --merge /dev/vg0/root-snapVirtual Machine Snapshots
# KVM/libvirt VMs
virsh snapshot-create-as vm-name pre-upgrade-$(date +%Y%m%d)
# VirtualBox
VBoxManage snapshot "VM Name" take "pre-upgrade"
# Cloud servers
# Create a system disk snapshot in the cloud console5. One-Click Backup Script
Consolidate the above steps into a script:
#!/bin/bash
# pre-upgrade-backup.sh
set -euo pipefail
BACKUP_DIR="/backup/pre-upgrade-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
echo "=== Starting pre-upgrade backup ==="
echo "Backup directory: $BACKUP_DIR"
# System information
echo ">> Recording system state..."
lsb_release -a > "$BACKUP_DIR/lsb-release.txt" 2>&1
uname -a > "$BACKUP_DIR/kernel.txt"
dpkg --get-selections > "$BACKUP_DIR/packages-selections.txt"
apt-mark showmanual > "$BACKUP_DIR/packages-manual.txt"
systemctl list-units --type=service --state=running > "$BACKUP_DIR/services-running.txt"
ip addr > "$BACKUP_DIR/ip-addr.txt"
ss -tlnp > "$BACKUP_DIR/listening-ports.txt"
# Configuration files
echo ">> Backing up configuration files..."
sudo tar czf "$BACKUP_DIR/etc.tar.gz" /etc/ 2>/dev/null
# Cron
echo ">> Backing up cron jobs..."
crontab -l > "$BACKUP_DIR/crontab-user.txt" 2>/dev/null || true
# Firewall
echo ">> Backing up firewall rules..."
sudo ufw status numbered > "$BACKUP_DIR/ufw-rules.txt" 2>/dev/null || true
sudo iptables-save > "$BACKUP_DIR/iptables.rules" 2>/dev/null || true
# Package sources
echo ">> Backing up APT sources..."
cp -a /etc/apt/sources.list.d/ "$BACKUP_DIR/sources.list.d/" 2>/dev/null || true
echo "=== Backup complete ==="
echo "Backup file listing:"
ls -lh "$BACKUP_DIR/"
echo ""
echo "Please also manually back up:"
echo " - Databases (MySQL/PostgreSQL, etc.)"
echo " - User data (/home)"
echo " - Web data (/var/www)"
echo " - Docker data volumes"
du -sh "$BACKUP_DIR"# Use the script
chmod +x pre-upgrade-backup.sh
sudo ./pre-upgrade-backup.shBackup Verification
After completing backups, be sure to verify their integrity:
# Verify tar archive integrity
tar tzf /backup/etc-*.tar.gz > /dev/null && echo "etc backup is OK"
# Verify database backup
# WARNING: a full dump usually contains CREATE DATABASE / USE statements,
# so never SOURCE it directly into a production instance, or it will overwrite existing databases!
# Safe approach 1: only check the integrity of the dump file
gunzip -t /backup/mysql-all-*.sql.gz && echo "database backup archive is intact"
# For an uncompressed .sql, check whether it ends with the dump-completed marker
tail -n1 /backup/mysql-all-20260324.sql | grep -q "Dump completed" && echo "dump is complete"
# Safe approach 2: restore and verify in an isolated, throwaway instance (e.g. a separate container/port), never against the production database
# Verify file count
echo "Original file count: $(find /etc -type f | wc -l)"
echo "Backup file count: $(tar tzf /backup/etc-*.tar.gz | wc -l)"
# Confirm the backup disk has enough space
df -h /backup/Checklist Summary
- User home directory backed up
- All databases exported
- /etc configuration directory backed up
- Cron jobs recorded
- Firewall rules saved
- Installed package list exported
- APT source configuration backed up
- Network configuration recorded
- Service list recorded
- System snapshot created (if using LVM/Timeshift)
- Backup file integrity verified
- Backups stored on a different disk from the system
Last updated on