Ubuntu 26.04 Tutorial / Back Up Ubuntu Configuration, Package Inventories, and User Data

An Ubuntu backup needs a defined scope, storage independent of the source failure, and a tested restoration. A package list or VM snapshot alone is insufficient. This lesson plans the backup scope and demonstrates restoration to a separate directory without overwriting the source.

Decide what must be restored

Target What to retain and verify
Configuration Changed /etc files, reasons, and service versions; restrict certificate/private-key access
User files Actual home/share paths, UID/GID, and required modes, ACLs, and extended attributes
Application data Database dumps, volumes, uploads, application versions, and consistency procedure
Packages Manual APT list, full versions, Snap inventory, and repository information
Recovery access Installation media, console, unlock/decryption keys, and custody responsibility

A simple tar of a live database can mix data from different points in time. Use an application-supported dump or coordinated stop/freeze procedure, and identify stores that must be restored together. Separately test preservation and restoration of ACLs and extended attributes when required.

Record packages and configuration locations

These commands create a new inventory directory under the current user’s home without installing or removing packages. Restrict access because inventories may contain operational details. They do not contain the actual configuration or user-file contents.

(
set -eu
umask 077
inventory_dir=$(mktemp -d "$HOME/ubuntu-inventory.XXXXXX")
apt-mark showmanual > "$inventory_dir/apt-manual.txt"
dpkg-query -W -f='${binary:Package}\t${Version}\n' > "$inventory_dir/dpkg-versions.tsv"
if command -v snap >/dev/null 2>&1; then
    snap list > "$inventory_dir/snap-list.txt"
fi
cat /etc/os-release > "$inventory_dir/os-release.txt"
printf "%s\n" "$inventory_dir"
)

Before restoration, review which packages and repositories are supported and needed on the destination release instead of reinstalling the entire list blindly. Distinguish configuration backups from machine-specific identities such as machine-id, SSH host keys, and static addresses. Recovery of the same server differs from cloning another server.

Perform a small backup-and-restore round trip

Save the complete script as ~/backup-roundtrip-lab.sh and run bash ~/backup-roundtrip-lab.sh. It requires tar, sha256sum, and cmp, uses no sudo, and touches only new fixture files in a temporary directory. This same-disk exercise does not replace independent backup storage.

set -eu
umask 077
lab_dir=$(mktemp -d)
mkdir "$lab_dir/source" "$lab_dir/restored"
printf "original data\n" > "$lab_dir/source/note with spaces.txt"
tar -C "$lab_dir/source" -cpf "$lab_dir/data.tar" .
(
    cd "$lab_dir"
    sha256sum data.tar > data.tar.sha256
    sha256sum -c data.tar.sha256
)
tar -tf "$lab_dir/data.tar"
tar -C "$lab_dir/restored" -xpf "$lab_dir/data.tar"
cmp "$lab_dir/source/note with spaces.txt" "$lab_dir/restored/note with spaces.txt"
printf "Round trip passed: %s\n" "$lab_dir"

The checksum checks whether the archive matches the recorded bytes, and the tar listing checks member names. A successful cmp followed by Round trip passed verifies restoration of this example’s file content. It does not test encryption, access controls, or application startup. Do not extract unknown archives as administrator; begin real restoration in an isolated empty directory.

Back up real Nginx configuration and a user folder

Use /etc/nginx after the Nginx site-configuration lab and one ordinary-document folder inside your home. Identify the folder and pause editing, sync, and application writes for consistency. This does not replace database dumps or coordinated volume backups. Record the separate backup disk’s mountpoint/UUID from the persistent-mounting lesson and verify that it is independent of the source device.

Save the complete script as ~/backup-course-data.sh. It requires Bash, GNU tar, util-linux findmnt, and coreutils realpath/sha256sum. Pass the user-data folder, backup filesystem mountpoint, and actual UUID. Adapt bash ~/backup-course-data.sh "$HOME/Documents/course-data" /srv/backup ACTUAL_UUID to verified local values.

set -eu
umask 077
if [ "$#" -ne 3 ]; then
    printf 'Usage: bash backup-course-data.sh SOURCE_DIR BACKUP_MOUNT EXPECTED_UUID\n' >&2; exit 2
fi
source_dir=$(realpath -- "$1")
backup_mount=$(realpath -- "$2")
expected_uuid=$3
case "$source_dir" in
    "$HOME"/*) ;;
    *) printf 'Choose a specific ordinary-data folder inside your home.\n' >&2; exit 1 ;;
esac
test -d "$source_dir"
if [ -z "$expected_uuid" ] || [ "$expected_uuid" = REPLACE_WITH_VERIFIED_UUID ]; then
    printf 'Record the actual backup filesystem UUID first.\n' >&2; exit 1
fi
actual_uuid=$(findmnt -rn --mountpoint "$backup_mount" -o UUID || true)
if [ "$actual_uuid" != "$expected_uuid" ]; then
    printf 'Expected backup filesystem is not mounted; stop.\n' >&2; exit 1
fi
for original in "$source_dir" /etc/nginx; do
    original_uuid=$(findmnt -rn --target "$original" -o UUID)
    if [ -z "$original_uuid" ] || [ "$original_uuid" = "$actual_uuid" ]; then
        printf 'Use a separate verified backup filesystem.\n' >&2; exit 1
    fi
done
case "$backup_mount/" in
    "$source_dir/"*) printf 'Backup must be outside the source tree.\n' >&2; exit 1 ;;
esac
sudo test -d /etc/nginx
df -h "$source_dir" "$backup_mount"
set_dir=$(sudo mktemp -d "$backup_mount/ubuntu-course-backup.XXXXXX")
sudo chmod 0700 "$set_dir"
sudo tar --acls --xattrs --numeric-owner -C / -cpf "$set_dir/nginx.tar" etc/nginx
sudo tar --acls --xattrs --numeric-owner -C "$source_dir" -cpf "$set_dir/user-data.tar" .
sudo sh -c 'cd "$1" && sha256sum nginx.tar user-data.tar > SHA256SUMS && sha256sum -c SHA256SUMS' sh "$set_dir"
printf 'Backup set: %s\n' "$set_dir"

A missing or mismatched mount stops before archive creation. Success prints a set path and two checksum OK results. Restricting the potentially sensitive set to root-only 0700 is not encryption against disk loss. Plan storage/encryption separately and test ACL/xattr restoration on the actual filesystems.

Restore into an empty separate location and compare

Use only the trusted set just created. Save this as ~/restore-course-data.sh and run bash ~/restore-course-data.sh BACKUP_SET_DIRECTORY. It extracts only into a new /var/tmp directory, preserving live configuration and user originals. Check capacity and UID/GID mappings first.

set -eu
if [ "$#" -ne 1 ]; then
    printf 'Usage: bash restore-course-data.sh BACKUP_SET_DIRECTORY\n' >&2; exit 2
fi
set_dir=$(realpath -- "$1")
sudo test -f "$set_dir/SHA256SUMS"
sudo sh -c 'cd "$1" && sha256sum -c SHA256SUMS' sh "$set_dir"
restore_dir=$(sudo mktemp -d /var/tmp/ubuntu-course-restore.XXXXXX)
sudo chmod 0700 "$restore_dir"
sudo mkdir "$restore_dir/config" "$restore_dir/data"
sudo tar --acls --xattrs --same-owner -C "$restore_dir/config" -xpf "$set_dir/nginx.tar"
sudo tar --acls --xattrs --same-owner -C "$restore_dir/data" -xpf "$set_dir/user-data.tar"
sudo ls -ldn "$restore_dir/config/etc/nginx" "$restore_dir/data"
printf 'Isolated restore: %s\n' "$restore_dir"

Substitute the printed restore path and compare against an unchanged source. A silent diff with exit 0 means matching content; exit 1 reports differences. Post-backup source changes do not by themselves establish corruption. Investigate permissions and missing files for other errors.

restore_dir=/var/tmp/REPLACE_WITH_PRINTED_RESTORE_DIRECTORY
source_dir="$HOME/Documents/course-data"
sudo diff --no-dereference -r /etc/nginx "$restore_dir/config/etc/nginx"
sudo diff --no-dereference -r "$source_dir" "$restore_dir/data"

Compare important contents, numeric owners/modes from ls -ln, and required ACLs/xattrs with getfacl/getfattr; install acl/attr if needed. Extraction alone does not complete service recovery. Validate configuration and application behavior on a separate recovery server before real restoration. Clean up only the identified comparison directory when finished.

Prepare independent storage and failure detection

For an external disk or another host, an existing destination directory does not prove that storage is connected. Compare the target mount’s SOURCE/UUID from findmnt with the recorded identity and stop on mismatch. Writing to an unmounted directory can fill the system disk. Plan capacity, decryption access, and off-site or offline generations around the recovery need.

Ubuntu’s shell-backup guide includes tar examples and restoration to a different directory.

Automate after a manual restoration succeeds. Record exit status, last success, retained generations, and space failures, and test the notification route. A hash stored beside a writable archive is not by itself tamper protection; use independent verification records or immutable retention when required.

Judge recovery by data and service behavior

On the destination, verify file counts, important content, ownership, and permissions, then test application reads/writes and user login. Check DNS, certificates, shares, and resumed backups as applicable. Record recovery duration and lost updates; revise frequency or procedures if they exceed acceptable limits. Preserve the failed source until required evidence and data are secured.