Raspberry Pi – Full Backup with `dd`

Raspberry Pi-4 Model-B

If you’re running a Raspberry Pi with a somewhat important service in your network, like a DNS-Level Adblocker, Nextcloud, a proxy web server and so on, you’ll probably like to back it up on a regular basis.

One way could be to unplug the MicroSD card – or any other kind of storage you use – from it, plug it into your workstation and make a copy of it. While this definitely works, it will leave your Raspberry Pi offline for that time, which in return would interrupt the service it provides.

So, a better way would be to run the backup while the Raspberry Pi is up and running. And let me tell you, this is pretty simple to do with the dd command.

Some Assumptions

You have some sort of storage somewhere (like a NAS for example) that can be mounted via cifs or nfs, whatever flavour you like. I’ll be using cifs in this example.

The backup storage is mounted to /mnt/Backup/, but you can mount it anywhere you like in your file system.

Mount the Storage

Your CIFS is hopefully requiring a username and password. So you’ll need to create a credentials file first. This file is used to pass your credentials – username and password – to cifs during the mount process.

For simplicities sake, we’ll have this file as /home/pi/.mount-credentials/backup-storage with the following content:


To make sure this file cannot be changed by accident, secure it:

chmod 600 /home/pi/.mount-credentials/backup-storage

Now, that this is done, it’s time to tell the system where we want to mount the backup storage.

First, the mount point needs to be created. This is simply a directory where the backup storage is mounted to.

sudo mkdir -p /mnt/Backup

Now it’s time to mount the backup storage to its new location. Again for simplicities sake, we use the /etc/fstab file here. This way it’ll be mounted every time the Raspberry Pi is booting.

To do so, add the following line to your /etc/fstab file:

//my_server.lan/backup/raspberry-pi    /mnt/Backup    cifs    credentials=/home/pi/.mount-credentials/backup-storage,vers=3.0,uid=pi,gid=pi,iocharset=utf8,dir_mode=0770,file_mode=0655,noperm    0 0


//my_server.lan/backup/raspberry-pi is the directory on your backup storage where the backup files will be written to. Change this accordingly.

/mnt/Backup is where the backup storage is mounted and can be accessed.

cifs is the network filesystem we use.

And the long line of options are options that are passed down to cifs, like our credentials, which user should be used, directory and file permissions, charset and so on.

Save the file and run the following command to mount the backup storage:

sudo mount -a

The Backup Script

Now that we have taken care of the backup location, it’s time to write our little backup script. Nothing too fancy, just some lines of shell/bash script that will check if the backup storage is mounted and try to mount it if needed and create the backup file.

But before we do so, we need to figure out which device our drive is. Luckily that’s a rather simple task, just run lsblk in your console and you should see something like this:

pi@raspberry_pi ~ $
» lsblk
sda      8:0    0 119.2G  0 disk
├─sda1   8:1    0   256M  0 part /boot
└─sda2   8:2    0   119G  0 part /

/dev/sda is the device in my case. This could vary in your setup. Make sure to change it accordingly in the backup script.

File: /home/pi/raspi-backup

#!/usr/bin/env bash

isMounted () {
    findmnt "$1" > /dev/null;

run_backup () {
    # Set some variables
    DATE=`/bin/date '+%Y-%m-%d'`
    TIMESTAMP="$(date +%s)"



    # Mount the backup directory if necessary
    if ! isMounted "${BACKUP_DIR}";
            sudo mount ${BACKUP_DIR}

    # Check again to see if the mount was successful.
    # If not, stop right here, something went horribly wrong
    if ! isMounted "${BACKUP_DIR}";
            echo "Backup directory could not be mounted. Exiting here!"

            exit 1;

    # Now go forth and run the backup
    echo "Backing up ${DEVICE_TO_BACKUP} to ${BACKUP_DIR} as ${BACKUP_FILE_NAME} ..."
    time sudo dd if=${DEVICE_TO_BACKUP} of=${BACKUP_DIR}${BACKUP_FILE_NAME} bs=1M status=progress

    # Check for PiShrink (https://github.com/Drewsif/PiShrink)
    if command -v pishrink.sh > /dev/null
            # Shrinking the image
            sudo pishrink.sh -rv ${BACKUP_DIR}${BACKUP_FILE_NAME}


Make sure the file is executable with:

chmod +x /home/pi/raspi-backup

Run the Backup

The backup script is ready to be tested. To run a backup simply execute the following command in your console:


With this command, your backup file will be created under /mnt/Backup/raspi-your_hostname-date-timestamp.img. Keep in mind, we are using a network connection to the backup storage, so this might take a while, depending on the size of your MicroSD card or other storage on your Raspberry Pi.

For my AdGuardHome Pi the output looks like this:

pi@adguard ~ $
» ./raspi-backup
Backing up /dev/sda to /mnt/Backup/ as raspi-adguard-2022-10-21-1666324418.img ...
127969263616 bytes (128 GB, 119 GiB) copied, 1155 s, 111 MB/s
122104+1 records in
122104+1 records out
128035676160 bytes (128 GB, 119 GiB) copied, 1161.04 s, 110 MB/s

real    19m21.064s
user    0m1.766s
sys     7m48.681s

Restore a Backup

To restore a backup you can use any tool that can write ISO images to a device, like the Raspberry Pi Imager for example, or Balena Etcher. The only thing you have to make sure of is that the device is large enough. You can even use the same MicroSD card again, and since you have to restore a previous version, something went wrong with the live system, so the data on this particular MicroSD is probably damaged or in any other way no longer viable anyways.

Last Words

Now, you only have to make sure to always have a somewhat recent backup!

This method is of course not limited to Raspberry Pi systems, you can apply this method to any Linux system you want. I used the Raspberry Pi here as an example to showcase how easy it is to create backups of a running system.

Leave a Reply

Your email address will not be published. Required fields are marked *