Introduction: How to BackUp and Shrink Your Raspberry Pi Image
Foreword
So why all the hullabaloo you may ask?
Surely all I need to do is use Win32DiskImager and take a read of my Raspbian Image and zip it right?
Job Done!
Well, unfortunately that's not the whole story. Read on...
- Have you ever noticed the size of your Rasbian image is that of the card you took the copy from and does not reflect the size actually being used?
- This happens when you re-size your image (via raspi-config) to make use of the full uSD card even if you end up not using much of the card space, the saved image will still be the same size as the uSD card.
- Have you ever found Win32DiskImager fails to write a backup Raspbian image even when you are writing to a 'like for like' uSD card of the same stated size, just a different make?
- This is because not all card sizes are the same ie. a 16GB uSD card from one manufacturer may not be exactly the same size as from another. This will cause Win32DiskImager to fail.
- Did you want to downsize your Raspbian image from one card to another but can't?
- If you use the Win32DiskImager read method you can only write to the exact same or bigger card size.
The following text details how you can make more efficient backups of your images.
Introduction
As mentioned above this Instructable documents how to efficiently make backups of your critical Raspberry Pi images, compress them such that they occupy the least possible space and can potentially be transferred to a uSD card of smaller size.
The Instructable will cover the following topics;
- How to install prerequisite software on Raspberry Pi to allow image resizing.
- How to read and store an Image from a uSD card (via Linux command line and with Win32DiskImager),
- How to create your compressed backup image,
- How to write your backup image to a uSD card (via Linux command line only. it assumes you know how to use Win32DiskImager to write an image. If not go here https://www.raspberrypi.org/documentation/installa...),
- Summary,
- References used.
What parts do I need?
To set the system up such that you can successfully carry out the instructions you will need the following;
- Raspberry Pi 3 + Jessie Image installed (in this case I used : 2016-03-18-raspbian-jessie.img) with monitor, mouse and keyboard etc.,
- uSD USB card reader for your uSD card to be backed up,
- External USB HDD for Raspberry Pi (big enough to hold your backed up images, in this instance mine is labeled '1TBFREECOM' and oddly enough is 1TB in size, which is more than ample for the needs of this Instructable),
- Target uSD card to read the uncompressed Image for backup,
- Target uSD card to write the compressed Image to (could be the same as 4.).
.
What skills do I need?
Do I require any specialist skills?
No, only the following;
- Some knowledge of Linux is always useful,
- A little patience as the writing process may take a while,
- The ability to accurately and blindly follow written instruction.
.
Note
- This method is only good for Raspbian images having two partitions, so won't work with NOOBS, RetroPi etc.
- It is assumed that all Linux commands are carried out directly on the Raspberry Pi (not via a PuTTY SSH connection etc.).
- Linux commands are entered via a Terminal instance. Terminal is the 'black monitor' icon on the start bar. Alternatively, it can be found via; Menu -> Accessories -> Terminal.
- Although uSD (micro SD) is used throughout, this method applies equally to SD cards.
- This was written to complement my series on home automation https://www.instructables.com/id/IoT-Intranet-of-Th...
.
Disclaimer
As always, you use these instructions at your own risk.
Step 1: Initial Raspberry Pi Software Install
Before we can begin we must install the following items of software. This is a 'one off' activity and won't take long.
Enter the following Linux commands, answering 'y' to any questions;
.
- sudo apt-get update
- sudo apt-get install dcfldd
- sudo apt-get install gparted
.
Once complete you have now installed the software necessary to write an image and change the partition of an image.
Step 2: Reading Your Raspberry Pi Image
Via Win32DiskImager
As in picture one above;
- Insert your uSD card into your PC USB reader and note which drive it is mapped to. In the example above it is drive 'G:\',
- Enter the directory where you want the Image to be written and give it a name. Here : 'c:\temp\RaspberryPi\BackUpServerUncompressed.img',
- Click the read button. Circled in red,
- Let the software complete,
- The Image file located in 'c:\temp\RaspberryPi\' can now be moved to the 1TB FREECOM External HDD for transfer to the Raspberry Pi.
.
That's it you're done.
.
or Via the Linux command line
This is a little bit more involved.
Insert the Raspberry Pi Image to be copied into your USB uSD card reader of your Raspberry Pi.
Insert your USB External HDD into your Raspberry Pi.
Open a Terminal instance and enter the following Linux command;
- df -h
This is to determine how your uSD card has been mounted (connected/mapped).
See Pic 2 above for the result. In general you will find external devices have a path something like '/media/pi/...'
In this case;
- For the External HDD (named '1TBFREECOM') it is '/media/pi/1TBFREECOM'
- For the Raspberry Pi Image there will be two entries under '/media/pi/...'
- One named 'boot'
- The second will have a long number, here 'e6e7f776-...-c44ecdbfcf90'
For these two Raspberry Pi entries note the mount details. Ringed in red, here; '/dev/sdb1' and '/dev/sdb2'
.
Next we 'unmount', the Raspberry Pi uSD card with the following Linux command (see pic 3).
- sudo umount /dev/sdb1 /dev/sdb2
Now we make a backup copy of the Raspberry Pi image to our external HDD, named '1TBFREECOM'
- sudo dcfldd if=/dev/sdb of=/media/pi/1TBFREECOM/MyImage.img
Pic 4 shows the backup activity in action and Pic 5 shows what it looks like when it's complete.
Next we use the sync command to force a synchronise of any outstanding input or output (see pic 6).
- sudo sync
Finally we finish off by taking a look at the backed up image file on the 1TBFREECOM HDD to check to see that user name and group are 'pi'.(see pic 7 above. User and Group are circled in red).
- ls -l /media/pi/1TBFREECOM
If not, then enter the following command (see pic 8);
- sudo chown pi:pi /media/pi/1TBFREECOM/MyImage.img
.
And that's all there is to it!
Ok, so I admit it's a little on the tortuous side.
.
.
Gotchas
In case your image is sizable, you have to format your USB-FDD/-stick as NTFS (example: image of 16 GB on a 32 GB stick). Linux/Jessie distros have a NTFS-driver, which is read-only. Therefore you need to install the newer driver NTFS-3G, which is read & write capable. sudo apt-get install ntfs-3g and reboot.
Thanks to gorgonops for spotting this. See in line comments below for thread.
Step 3: Resizing Your Image
Ok, we'll begin by getting the start point of the second partition on the uSD card. A Raspberry Pi image has two partitions, 1 Boot, 2 Where everything else is stored. To determine the start of the second partition enter the command below;
- sudo fdisk -l /media/pi/1TBFREECOM/MyImage.img
Take note of the 'Start' of the second partition '.img2', we'll need it later. Here : 131072 (see pic 1 above, red circle).
Now we mount this partition using the following command (see pic 2 above);
- sudo losetup /dev/loop0 /media/pi/1TBFREECOM/MyImage.img -o $((START*512))
Where START is the start of MyImage.img2 the second partition. ie. 131072. So in this case it will be;
- sudo losetup /dev/loop0 /media/pi/1TBFREECOM/MyImage.img -o $((131072*512))
Note : Don't worry if you get a busy message, just enter the following and retry the above;
- sudo losetup -d /dev/loop0
Now we resize the partition with 'GParted'. From a terminal window enter the following command (see pic 3 above);
- sudo gparted /dev/loop0
This will launch the 'GParted' application (see pic 4 above).
From GParted do the following;
- Select /dev/loop0 partition (pic 5 above),
- Select Partition menu -> Resize/Move (pic 6 above),
- Resize the partition by either dragging the slider left as indicated, or entering a value into the box marked 'New size (MiB)' (again as shown in pic 6). I found this to be a little trial and error and generally started with +500M and moved up in increments. ie Change the value of "New size (MiB)" to approx 500MB above "Minimum Size". In this case 2942 + 500MB = 3442MB etc.,
- Click 'Resize/Move' to finish,
- GParted will now indicate there is '1 operation pending' (as in pic 7 above),
- Click Edit menu -> Apply All Operations,
- Click 'Apply' to warning box (pic 8 above),
- GParted will now process the request to resize (see pic 9),
- If the resize is successful you will get a message: 'All operations successfully completed' (as in pic 10),
- Now expand the 'Applying pending operations' dialogue shown in pic 10 until you locate the line in pic 11, marked 'resize2fs -p /dev/loop0 ...' and take a note of the value. Here : '3506176K'. This is important, so, take your time to get it right.
Note : If you get an error message at step 9 (as in pic 12), then click Ok, Close, and repeat from step 1 above, only this time add 500MB to your last resize. Repeat this until the size is accepted.
It is now safe to exit GParted. Press Ctrl+Q (^Q), or menu GParted -> Quit.
We will now remove the loopback device for the second partition and create a new loopback device for the whole image. Enter the following commands (see pic 13);
- sudo losetup -d /dev/loop0
- sudo losetup /dev/loop0 /media/pi/1TBFREECOM/MyImage.img
Next we need to edit the partition table to reflect the new smaller size. Begin by entering the following command;
- sudo fdisk /dev/loop0
For the record 'fdisk' can be tricky to use, but in a 'nutshell' we are going to do the following (pressing the return/enter key after each character entry);
- Enter 'd' then '2' to delete the table entry for the second partition,
- Enter 'n' then 'p' then '2' to create a new second partition entry,
- Enter the START sector number that you used earlier, as the start sector. In my example it was '131072',
- Enter +NEWSIZE as the new size. Don't forget the '+' sign at the start. This is the new size that you noted down before exiting GParted. Here '3506176K',
- Enter 'w' to write the new partition table and exit.
Don't worry about 'Re-reading the partition table ...' error message.
Picture 14 above details what needs to be entered (the important parts are ringed in red).
Once the partition table has been written we will read the partition table to determine the end point of the second partition by issuing the following command (see pic 15 above, the end point is ringed in red);
- sudo fdisk -l /dev/loop0
Pay attention to end point of the second partition.
Here it is labeled as '/dev/loop0p2' and has a value of '7143423'
Next we remove the loopback device with the following command (see pic 15 above);
- sudo losetup -d /dev/loop0
Finally, we trim any empty space with the truncate command the template for which is shown below, where END is the value obtained above. Namely : 7143423
truncate -s $(((END+1)*512)) /media/pi/1TBFREECOM/MyImage.img
Consequently to execute the full command enter the following (see pic 16 above);
- truncate -s $(((7143423+1)*512)) /media/pi/1TBFREECOM/MyImage.img
.
And that's it. Your HDD will now contain an image file named 'MyImage.img' which has been successfully resized and can by written back onto a uSD card to restore your original image should the need arise.
You can further reduce the image size by 'zipping' it, as you will get some more compression. Handy for disk storage.
Step 4: Writing Your Raspberry Pi Image
This is a similar to the read operation.
Insert the target USB uSD card into your reader
Insert your USB External HDD into your Raspberry Pi
Open an Terminal instance and enter the following Linux command;
- df -h
Take note of the card mount point. '/dev/sd?'
I used a card which already had an image on it so it had two entries shown in pic 1 above and ringed in red, here; '/dev/sdb1' and '/dev/sdb2'. If you use a blank/empty or new card card it may only have one.
Now unmount your uSD card with the following command (pic 2 above);
- sudo umount /dev/sdb1 /dev/sdb2
Finally write your Raspberry Pi image from the HDD '1TBFREECOM' to the uSD card with the following command (Pic 3 above).
- sudo dcfldd of=/dev/sdb if=/media/pi/1TBFREECOM/MyImage.img
Follow this with a sync command, as in the case of the read (again pic 3 above).
- sudo sync
That's it.
Step 5: Summary
So the steps in brief are as follows;
- Set up your Raspberry Pi the way you want it, shut down the Pi and remove the uSD card,
- Make a copy of the Raspberry Pi Image of the uSD to your backup HDD drive,
- Resize the image,
- Edit the partition table to suit the new size,
- Trim the image to its new size,
- Write your new image from backup HDD to a uSD card.
Step 6: References Used
I used the following sources to put this Instructable together;
37 Comments
Question 2 years ago on Step 4
At the stage of,
sudo fdisk /dev/loop0
d <enter>
2 <enter>
n <enter>
p <enter>
2 <enter>
But then I got a message
<quote>
Partition #2 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o:
</quote>
What should I choose?
Answer 2 years ago
do not remove the signature, it worked fine for me after that
Tip 3 years ago
Doing this by copy the image to an USB Stick and issue
also worked for me :-)sudo apt-get install quemu-utils
cd wheretheimageis
and
http://content.untony.org/?p=730
3 years ago
there's a *much* simpler way. write out your image to an SD card, e.g. 32GB. use DiskGenius (version 5.2.0.884 x64) to resize the partitions. i resized the linux partition to 6GB and moved it out 0.75GB. then i extended the FAT32 partition (originally 256MB) to fill up the space released, making it 1GB. works perfectly and fits on an 8GB SD card.
Reply 3 years ago
Hi, I would be very interested in how you did this exactly.
I installed DiskGenius but do not find the right buttons I think
Reply 3 years ago
here are some of the instructions i wrote up. Text is written in markdown (.md). the images may not be order of execution. hope this is helpful.
Shrink the partition
--------------------
1. **Backup** the SD Card. We've used [win32diskimager] successfully to backup & retore, after which [Disk Genius] has been used to shrink the linux partition. *Do not* use Paragon backup (resized and even full images don't boot properly). *Do not* use Easeus Partition Master (has no option to resize the second partition).
2. **A full backup** should be made, i.e. leave `Read Only Allocated Partitions` blank (**test** whether we can check this and things still work; it would make the backup faster), enter the path & filename where you want it saved, then press "Read". After the read is done, safely remove the original SD Card.

+ **Restore** the image generated to a **different** SD card. Insert the new SD card and with Win32DiskImager, press "Write." A full restore is done.
+ **Verify bootup** by putting the new SD Card into the Raspberry Pi and booting it up, using the instructions up above. Also, a properly booting Pi will have the green light flicker for quite a while until it stabilizes whereas an incorrect copy will get to the stable green light much faster. Once the bootup is verified, shut it down as before.
+ **Reinsert** the SD card into the computer after removing from the Raspberry pi.
+ **Reduce the partition size** by using Use [Disk Genius][] (version 5.2.0.884 x64 tested).


+ **Verify** the partition sizes with `parted`:
```
pi@raspberrypi:~ $ sudo parted -l
Model: SD SD32G (sd/mmc)
Disk /dev/mmcblk0: 31.0GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 4194kB 273MB 268MB primary fat32 lba
2 273MB 8901MB 8629MB primary ext4
pi@raspberrypi:~ $
```
+ **Move** the big partition out by another 500MB (could probably be done in conjunction with the previous step).
+ **Resize the FAT32** partition to fill the newly unallocated area. The FAT32 partition is now big enough to hold large files or log files. This is useful to transfer data between Windows and linux. After resizing, remove safely from the computer.

+ **Test it works** by booting the Raspberry Pi with the new SD card.
+ **Check partition sizes** with `parted`:
```
pi@raspberrypi:~ $ sudo parted -l
Model: SD SD32G (sd/mmc)
Disk /dev/mmcblk0: 31.0GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 32.3kB 1423MB 1423MB primary fat32 lba
2 1423MB 10.1GB 8629MB primary ext4
pi@raspberrypi:~ $
```
+ **Check free space** using `df`.
```
pi@raspberrypi:~ $ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 8262464 1269528 6639488 17% /
devtmpfs 217212 0 217212 0% /dev
tmpfs 221540 0 221540 0% /dev/shm
tmpfs 221540 3132 218408 2% /run
tmpfs 5120 4 5116 1% /run/lock
tmpfs 221540 0 221540 0% /sys/fs/cgroup
/dev/mmcblk0p1 1368357 53034 1315323 4% /boot
tmpfs 44308 0 44308 0% /run/user/1000
pi@raspberrypi:~ $
```
+ **Shrink further** if you wish -- we'll try shrinking down to 5MB so that the entire linux SD can fit on an 8MB card if needed. Use steps above with [Disk Genius].
+ **Verify it works** by booting up.
+ **Check partition sizes** with `parted`:
```
pi@raspberrypi:~ $ sudo parted -l
Model: SD SD32G (sd/mmc)
Disk /dev/mmcblk0: 31.0GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 32.3kB 1423MB 1423MB primary fat32 lba
2 1423MB 7822MB 6399MB primary ext4
pi@raspberrypi:~ $
```
+ **Check free space** using `df`.
```
pi@raspberrypi:~ $ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 6118884 1269184 4583372 22% /
devtmpfs 217212 0 217212 0% /dev
tmpfs 221540 0 221540 0% /dev/shm
tmpfs 221540 3124 218416 2% /run
tmpfs 5120 4 5116 1% /run/lock
tmpfs 221540 0 221540 0% /sys/fs/cgroup
/dev/mmcblk0p1 1368357 53034 1315323 4% /boot
tmpfs 44308 0 44308 0% /run/user/1000
pi@raspberrypi:~ $
```
[Disk Genius]: http://www.diskgenius.com
[win32diskimager]: https://sourceforge.net/projects/win32diskimager/
Reply 3 years ago
Meanwhile I managed to find my own solution, which is even more simple, I think.
My goal was to get a small backup image to be shared with others and able to be written on sd cards of different size.
my tools:
my steps:
- create backup image of the microSD with Win32diskimager
- open DiskGenius and mount the image as disk (Menu: "Disk→Open Virtual Diskfile")
- resize rootfs partition and leave the free space unallocated
- calculate the position of the end of the rootfs partition in the img file. Take the "Starting Sector" of the unallocated free space, in my case 5251072, add 1 and multiply by 512. This is (5.251.072 + 1) * 512 = 2.688.549.376
- close the virtual diskfile in DiskGenius
- make shure, trunc.exe is located in the same folder as your img
- start command window in this folder and enter "trunc.exe FILENAME FILESIZE" of course replace FILENAME by the name of your img and replace FILESIZE by the sector you have calculated earlier (in my case 2688549376)
- my img has now less than 3GB and can be written on a microSD by using Win32diskimager
Reply 3 years ago
hi, it seems that your solution is basically a subset of mine, and riskier. in mine, i first copy to the new SD card and then shrink. this is the safer way as it leaves the original SD card *and* the backup on the computer read-only . also, your method of simply truncating a file may cause trouble because trunc doesn't seem to take into account that it is a file system. while things may work fine for a while, you might get into trouble when you fill up the, smaller, partition on your new SD. i would not do it this way for a production-oriented OS.
Reply 3 years ago
You've been a member since 2016, why not write your first instructable on this method?
Reply 3 years ago
because i'm rubbish at documenting when i'm doing all the work by myself, much to my own detriment. don't have the luxury of time as i have a startup, not a company with infrastructure to take the load off. i figure i'd rather get some info out there than do nothing.
Reply 3 years ago
Alas, your comment came across as firing bullets. At the time of writing, some 3.5 years ago, there was no 'easy method' available.
So I took the time to document the only sound process I could come up with, more as an aide memoire than anything else.
As I say, if there is a better way, then document it with pictures. It'll be a useful record to come back to, when you forget how to do it (speaking from personal experience).
I understand your pain though, I work some very extreme hours it's only in my spare time I do project work. It helps that I have insomnia.
Good luck with the start up.
Reply 3 years ago
thanks :-). i've found that while pictures are useful, they're really hard to parse a few months down the road if they're not labeled properly, kept in an orderly fashion and accompanied with text documentation. to this end, on windows, i'm using markdown (.md) with mdwiki.html rendering it, using the tiny http server miniweb by stanley huang. i simply couldn't find a decent documentation tool that wasn't also a memory hog. mdwiki.html is kinda glitchy at times but not too bad. i might just revert to html if i can't get things right. it's disappointing that after all these years, there's still not a solution that's better than that :-(.
Tip 4 years ago
This could be worth updating now that BUSTER is the default version of Raspbian... bearing in mind that many folk will have upgraded from Jessie or Stretch to Buster, which NOW has a much larger BOOT partition than it's predecessors.... there's a great copier/clone utility for RPI called RPI-clone but while it easily resizes the ROOT partition up and down making Win32DiskImager look old, it does not resize upgraded BOOT partitions and that took me to GPARTED which is mentioned here.Jusy in case anyone hits this, Buster wants BOOT partitions of maybe 120 MB. Here's where and how I eventually got around that one..https://tech.scargill.net/raspberry-pi-buster-issue/
5 years ago
i signed up just so i could thank you for this. i recently got a few 32gb sd cards and writing a 32gb image for maybe 4gb of data was annoying. i just went through and resized my first image, the only issues i ran into were fixed by reading the steps correctly. it took less time to shrink the image and write it to an sd than it did to write the 32gb image to an sd. you have my thanks!
Reply 5 years ago
Hi sploiz,
You're very welcome. I glad you found it useful
Regards
SteveQuinn
6 years ago
Hi
There is a typo at the end of Step 4. if= and of= need to be swapped around.
i.e. the text says:
Finally write your Raspberry Pi image from the HDD '1TBFREECOM' to the uSD card with the following command (Pic 3 above).
but that command should read:
sudo dcfldd if=/media/pi/1TBFREECOM/MyImage.img of=/dev/sdb
Hope that helps
Reply 6 years ago
Yep,
Typo on my part. You'll notice the screen shot is correct.
Regds
SQ
6 years ago
One thing missing from this tutorial is that you must have a desktop UI installed in order to run GPARTED or be proficient enough to setup X11 forwarding to a PC or Mac. Without UI you cannot run Gparted. But who is using Raspberry Pi without a UI? well for one RetroPi image does not come with a desktop interface. X11 forwarding is a bit more complex to setup vs installing Pixel Desktop Environment so I'd recommend you install the UI first, then you can follow the Backup and Shrink tutorial.
Instruction for installing Pixel Desktop can be found here: https://github.com/RetroPie/RetroPie-Setup/wiki/FAQ#where-did-the-desktop-go
Reply 6 years ago
Check,
What parts do I need? Step 1
Also Note 1.
Whilst I specifically mention NOOBs it clearly pertains to RetroPi also.
Instructable updated accordingly.
6 years ago
Hi SteveQuinn,
when gparted executes the job, it fails with the comment, that it needs root- or r/w-rights to work on the partition. How can I set this up?