Applies to: any Linux system with GNU dd; tested on Debian 13 (coreutils 9.7, util-linux 2.41.5, qemu-img 10.0.13) with image files; loop mounting from the util-linux manual

To create a disk image in Linux, copy the whole disk into a file with dd: sudo dd if=/dev/sdb of=/backup/sdb.img bs=4M status=progress conv=fsync. The file is an exact, sector-by-sector copy, including the partition table and boot loader. You can compress it, look inside it, and write it back to a disk later.

Before you start

  • Image a disk that isn’t in use. A copy of a mounted, running file system can be inconsistent. For the system disk of a server, boot a rescue or live system first (on a dedicated server, attach a live ISO through the IPMI console, as in installing a custom ISO).
  • Save the image somewhere else: another disk, a mounted backup volume or another server. Never on the disk you are copying.
  • Check if= and of= twice. if is what you read, of is what dd overwrites. Swapped, they destroy the disk.

Find the disk’s name with lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS: disks show as disk (such as sda, vda or nvme0n1) and their partitions as part.

1. Create the image

sudo dd if=/dev/sdb of=/backup/sdb.img bs=4M status=progress conv=fsync

bs=4M reads and writes 4 MiB at a time instead of dd’s default of 512 bytes; status=progress shows progress while it runs; conv=fsync makes sure everything is written before dd exits. In our test with a 256 MiB disk image it ended with:

64+0 records in
64+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 0.178011 s, 1.5 GB/s

The image is as big as the whole disk, even if the disk is mostly empty. Check it with sha256sum: the source and the image gave the same checksum in our test.

2. Compress it, or send it to another server

sudo dd if=/dev/sdb bs=4M status=progress | gzip -c > /backup/sdb.img.gz
sudo dd if=/dev/sdb bs=4M status=progress | zstd -o /backup/sdb.img.zst

Our mostly empty 256 MiB test disk shrank to 255 KB with gzip and 8.6 KB with zstd. Real disks compress less: space that once held deleted files still contains the old data. In our test, an empty 128 MiB file system compressed to 0.1 MiB, but after writing and deleting a 60 MiB file it still compressed to 60.1 MiB.

If the server has no room for the image, pipe it to another server over SSH instead:

sudo dd if=/dev/sdb bs=4M status=progress | gzip -c | ssh user@backup.example.com 'cat > /backup/sdb.img.gz'

3. Look inside the image

fdisk reads the partition table straight from the file:

$ fdisk -l sdb.img
Disk sdb.img: 256 MiB, 268435456 bytes, 524288 sectors
Units: sectors of 1 * 512 = 512 bytes
...
Disklabel type: gpt

Device      Start    End Sectors  Size Type
sdb.img1     2048 133119  131072   64M Linux filesystem
sdb.img2   133120 522239  389120  190M Linux filesystem

To open the files in it, attach the image as a loop device and mount a partition read-only (commands from the util-linux manual; they need root on a real system, so we didn’t run them in our container lab):

sudo losetup --find --show --partscan sdb.img     # prints e.g. /dev/loop0
sudo mount -o ro /dev/loop0p1 /mnt
# ... copy what you need ...
sudo umount /mnt
sudo losetup -d /dev/loop0

Or in one step, using the partition’s start sector from fdisk -l times 512 as the offset:

sudo mount -o loop,ro,offset=$((2048*512)) sdb.img /mnt

4. Restore the image

This overwrites the whole target disk:

sudo dd if=/backup/sdb.img of=/dev/sdb bs=4M status=progress conv=fsync
gunzip -c /backup/sdb.img.gz | sudo dd of=/dev/sdb bs=4M status=progress conv=fsync

The target must be at least as large as the original. In our test the restored copy had the same SHA-256 checksum as the original.

Variations

  • One partition only: use the partition as the source, if=/dev/sdb1. You can check an ext4 partition image without mounting it: e2fsck -fn part1.img.
  • Save space without compressing: conv=sparse skips writing blocks of zeros. Our 256 MiB image used 8 MB on disk this way (du -h), while ls -l still showed 256 MiB.
  • Use the image in a virtual machine: qemu-img convert -O qcow2 sdb.img sdb.qcow2 converts it for KVM; our qcow2 file used 388 KiB.
  • Copy disk to disk without a file in between: see clone a partition or hard drive in Linux.

A disk image is a full snapshot, but it is slow to restore single files. For regular backups, file-level tools are usually better, such as backups with rsync to a VPS. Our unmanaged dedicated servers include free IPMI KVM, so you can boot a live ISO from the console to image the system disk.

Official documentation: GNU dd, losetup(8) and mount(8).

Was this answer helpful? 0 Users Found This Useful (0 Votes)