Backup data between servers
This guide explains how to copy and back up data between Linux servers using rsync, as well as how to perform low-level disk cloning with dd.
Before you start
The commands in this guide are run on the source server — the server you are copying data from. The destination server must be accessible via SSH, and the user specified in the command must have read access to the source path and write access to the destination path.
To verify SSH access to the destination server before running a backup:
ssh user@destination_host
Replace user with the remote username and destination_host with the IP address or hostname of the destination server.
For automated or scheduled backups, configure SSH key-based authentication instead of using passwords.
Copy a directory to a remote server
Note that the trailing slash in the source path affects how rsync behaves: /source/ copies the contents of the directory, while /source copies the directory itself.
Always use --dry-run before running commands with --delete to avoid accidental data loss. To preview what will be transferred without making any changes:
rsync -a --delete --dry-run -e ssh /path/to/source/ user@destination_host:/path/to/backup/
Once you have confirmed the output, run the same command without --dry-run. Add -P to allow resuming an interrupted transfer and show progress:
rsync -a --delete -e ssh -P /path/to/source/ user@destination_host:/path/to/backup/
The -a flag preserves permissions, timestamps, and symlinks. The --delete flag ensures that the destination is an exact mirror of the source by removing any files that do not exist on the source. Add -v to see detailed output.
The --delete flag will remove files on the destination that are not present on the source. Do not use it if the destination contains files that should be kept independently.
Copy most of the system files
To copy the majority of the file system while excluding virtual and temporary directories:
rsync -aAXv --delete --one-file-system --numeric-ids \ --exclude={/dev/,/proc/,/sys/,/tmp/,/run/,/mnt/,/media/,/lost+found,/swapfi le} \ / user@destination_host:/path/to/backup/
The flags used here: -a preserves permissions, timestamps, symlinks, and recursive copy; -A preserves ACLs; -X preserves extended attributes; -v shows detailed output. The -H flag for hard links is intentionally omitted: system hard links do not need to be replicated in a remote backup and preserving them increases transfer time and complexity. The --one-file-system flag prevents rsync from crossing into other mounted filesystems. The --numeric-ids flag preserves UID and GID values without mapping them to usernames, which is important when source and destination servers have different user configurations.
Most excluded paths use a trailing slash to exclude the directory contents while keeping the directory itself. /lost+found has no trailing slash because the entire directory should be excluded, not just its contents. The same trailing slash rule applies to the source path: /source/ copies the contents of the directory, while /source copies the directory itself.
This method does not create a bootable system image and should not be used as a full system backup replacement. For consistent backups of active systems, consider stopping critical services or using filesystem snapshots such as LVM snapshots before running the command.
Full directory clone with rsync
To perform a full clone of a directory tree, preserving hard links, ACLs, and extended attributes:
rsync -aAHXv /source/dir/ user@destination_host:/destination/dir/
The flags used here: -a preserves permissions, timestamps, symlinks, and recursive copy; -A preserves ACLs; -H preserves hard links, which is important for an exact directory clone; -X preserves extended attributes; -v shows detailed output.
Clone a disk with dd
To clone an entire disk to another disk on the same server:
dd if=/dev/sdX of=/dev/sdY bs=1M conv=noerror,sync status=progress
Replace sdX with the source disk and sdY with the destination disk. The conv=noerror,sync flags allow the copy to continue past read errors by filling damaged blocks with zeros. If data integrity is critical, omit these flags so that dd stops on the first error instead of silently replacing bad blocks with zeros.
To clone a disk to a remote server over SSH:
dd if=/dev/sdX bs=1M status=progress | ssh user@destination_host 'dd of=/dev/sdY bs=1M'
The destination can also be a file path instead of a block device.
dd writes directly to the target device or file without confirmation. Double-check the source and destination before running the command. For live systems, unmount all partitions of the source disk if possible, or remount them read-only. For consistent backups of mounted filesystems, use LVM snapshots or boot from a rescue environment.
Verify the backup
After the transfer, connect to the destination server and check the backup size and basic structure:
ssh user@destination_host du -sh /path/to/backup/ ls /path/to/backup/
For a thorough integrity check, run rsync with --checksum and --dry-run. This compares file contents rather than timestamps and will report any differences:
rsync -av --checksum --dry-run /path/to/source/ user@destination_host:/path/to/backup/
Note that this may take significantly longer than a regular rsync run on large datasets.