Many embedded systems applications do not require a desktop environment or graphical interface on the screen (e.g. server), and you may want to only install the files you really need on the SD card either to reserve as much space as possible for data and/or your program or to reduce costs.

After searching for a minimal image based on Raspbian ARMHF distribution for the Raspberry, I could only find Linux Systems minimal image based on the Alpha version of the Raspbian Wheezy. Their compressed image is 109 MB in size, has a custom kernel, sshd and ntpd are enabled, but the wireless tools were deleted, and at the time the swap was located in another partition instead of a file inside the rootfs. The uncompress rootfs is about 414 MB (as reported by df -h when mounted as a loop device).

I decided to prepare a minimal image myself based on the first Raspbian Wheezy release, that supports about the same features of the image mentioned above, plus support for the wireless tools. I’ll describe how I proceeded below, but for those who are only interested in the image, and could not care less how it was done, here’s the download link (84 MB compressed image). The username / password are the same: pi /raspberry.

Upon the first boot you can change the time zone:



sudo dpkg-reconfigure tzdata 1 sudo dpkg - reconfigure tzdata



This image only support US keyboard layout and English locale, if you need to change those:



sudo apt-get install console-data locales sudo dpkg-reconfigure console-data sudo dpkg-reconfigure locales 1 2 3 sudo apt - get install console - data locales sudo dpkg - reconfigure console - data sudo dpkg - reconfigure locales



If you are mainly going to access your board via ssh, you probably don’t need those.

Instructions to Generate a Minimal Raspbian Image

I’ve downloaded the image via BiTorrent and copied it to the SD card using dd. During the first boot, I configured the keyboard to US layout, Bangkok timezone, enabled SSH and disabled X are started and did not resize the partition.

Now let’s have a look at the rootfs usage:



df -h Filesystem Size Used Avail Use% Mounted on rootfs 1.8G 1.4G 338M 80% / 1 2 3 df - h Filesystem Size Used Avail Use % Mounted on rootfs 1.8G 1.4G 338M 80 % /



We’ve got 1.4 GB used, so we’ll need to delete about 1 GB.

The steps below are not optimized, and I’ve just described the way I did it.

As I login to the Raspberry Pi as pi user, the first thing I see is a directory called python_games. Sorry kids, but:



rm -rf python_games 1 rm - rf python_games



Then I vaguely remember some things that are pre-installed in the image by default, so I removed those:



sudo apt-get remove x11-common midori lxde python3 python3-minimal 1 sudo apt - get remove x11 - common midori lxde python3 python3 - minimal



Those two steps only shoved around 100 MB, so it’s not such a good start, but it’s still progress. I miraculously remember a command to find large file in Linux:



sudo find / -type f -size +10000k -exec ls -lh {} \; | awk '{ print $NF ": " $5 }' /boot/kernel_emergency.img: 16M /var/cache/apt/srcpkgcache.bin: 17M /var/cache/apt/pkgcache.bin: 17M /var/swap: 100M /var/lib/apt/lists/mirrordirector.raspbian.org_raspbian_dists_wheezy_main_binary-armhf_Packages: 33M /usr/share/icons/gnome/icon-theme.cache: 60M /usr/share/icons/HighContrast/icon-theme.cache: 74M /usr/lib/arm-linux-gnueabihf/libicudata.so.48.1.1: 18M /usr/lib/arm-linux-gnueabihf/libicudata.a: 18M /opt/vc/src/hello_pi/hello_video/test.h264: 30M 1 2 3 4 5 6 7 8 9 10 11 sudo find / - type f - size + 10000k - exec ls - lh { } \ ; | awk '{ print $NF ": " $5 }' / boot / kernel_emergency .img : 16M / var / cache / apt / srcpkgcache .bin : 17M / var / cache / apt / pkgcache .bin : 17M / var / swap : 100M / var / lib / apt / lists / mirrordirector .raspbian .org_raspbian_dists_wheezy_main_binary - armhf_Packages : 33M / usr / share / icons / gnome / icon - theme .cache : 60M / usr / share / icons / HighContrast / icon - theme .cache : 74M / usr / lib / arm - linux - gnueabihf / libicudata .so . 48.1.1 : 18M / usr / lib / arm - linux - gnueabihf / libicudata .a : 18M / opt / vc / src / hello_pi / hello_video / test .h264 : 30M



Now that’s more interesting! The first 3 files are the apt caches and the swap, we’ll take care of those at the end. Some icon takes appear to take a lot of space, the .a file show there are some development libs installed and the last file reminded me there’s some Raspberry media sample code.

Let’s take care of those code samples:



sudo rm -rf opt 1 sudo rm - rf opt



Now I need to find a way to list development packages installed in the system. Luckily there is a command to list installed packages, which I can filter to list development packages:



sudo dpkg --get-selections | grep "\-dev" binutils-dev install dpkg-dev install libasound2-dev install ... 1 2 3 4 5 sudo dpkg -- get - selections | grep "\-dev" binutils - dev install dpkg - dev install libasound2 - dev install . . .



Good! Let’s remove those:



sudo apt-get remove `sudo dpkg --get-selections | grep "\-dev" | sed s/install//` 1 sudo apt - get remove ` sudo dpkg -- get - selections | grep "\-dev" | sed s / install // `



Let’s remove python and some other packages (LXDE, omxplayer…)that do not look necessary in a minimal image.

sudo apt-get remove sudo dpkg --get-selections | grep -v "deinstall" | grep python | sed s/install//

sudo apt-get remove lxde-common lxde-icon-theme omxplayer raspi-config

At this point I just discovered there were still some x11 packages, and realized this should have been the first thing I had removed since it would get rid of several hundred MB of data:

sudo apt-get remove sudo dpkg --get-selections | grep -v "deinstall" | grep x11 | sed s/install//

Let’s say we don’t need audio support either:

sudo apt-get remove sudo dpkg --get-selections | grep -v "deinstall" | grep sound | sed s/install//

As I mentioned above, we would still like to have ssh access, but we don’t need to use the default sshd, and we can replace it with the lightweight dropbear ssh server:

sudo apt-get remove sudo dpkg --get-selections | grep -v "deinstall" | grep ssh | sed s/install//

sudo apt-get install dropbear

We now have 550 MB used space in the rootfs, minus the 100 MB swap file, that’s still 450 MB which is well above the 414 MB for Linux Systems image. I can see gcc is still there, and we should not need to build anything directly on the device. let’s remove it!:

sudo apt-get remove sudo dpkg --get-selections | grep -v "deinstall" | grep gcc\- | sed s/install//

After this operation, 234 MB disk space will be freed.

You are about to do something potentially harmful.

To continue type in the phrase 'Yes, do as I say!'

?] no

OK, this was a bad idea, and I answered no. So instead, I decided to only keep gcc 4.7:



sudo apt-get remove gcc-4.4-base:armhf gcc-4.5-base:armhf gcc-4.6-base:armhf 1 sudo apt - get remove gcc - 4.4 - base : armhf gcc - 4.5 - base : armhf gcc - 4.6 - base : armhf



After some more time trying to find non-essentials packages, I removed a few others, and call autoremove to delete unused packages.

sudo apt-get remove ca-certificates libraspberrypi-doc xkb-data fonts-freefont-ttf locales manpages

sudo apt-get autoremove

Almost done. Since we won’t use apt-get anymore, let’s clean apt-get cache:



sudo apt-get clean 1 sudo apt - get clean



Let’s disable swappping, and fill the swap file with zeros:



sudo swapoff -a cd /var sudo dd if=/dev/zero of=swap bs=1M count=100 1 2 3 sudo swapoff - a cd / var sudo dd if =/ dev / zero of = swap bs = 1M count = 100



Delete the logs



cd /var/log/ sudo rm `find . -type f` 1 2 cd / var / log / sudo rm ` find . - type f `



Check the size:



df -h Filesystem Size Used Avail Use% Mounted on rootfs 1.8G 461M 1.2G 28% / 1 2 3 df - h Filesystem Size Used Avail Use % Mounted on rootfs 1.8G 461M 1.2G 28 % /



Yes! That 461 MB including swap file. Time to turn off the Pi:



sudo shutdown now 1 sudo shutdown now



Now, we can remove the SD card from the Raspberry Pi board, and access it from a Linux PC to create an image.



sudo dd if=/dev/sdb of=2012-07-15-wheezy-raspbian-minimal.img count=3788800 1 sudo dd if =/ dev / sdb of = 2012 - 07 - 15 - wheezy - raspbian - minimal .img count = 3788800



We can mount the root and use sfill to fill free space with zeros:



mkdir mnt sudo mount -o loop,offset=$((512*122880)) 2012-07-15-wheezy-raspian-minimal.img mnt sudo sfill -z -l -l -f mnt sudo umount mnt 1 2 3 4 mkdir mnt sudo mount - o loop , offset = $ ( ( 512 * 122880 ) ) 2012 - 07 - 15 - wheezy - raspian - minimal .img mnt sudo sfill - z - l - l - f mnt sudo umount mnt



and finally compress the image with 7z using ultra settings:

7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on 2012-07-15-wheezy-raspian-minimal.img.7z 2012-07-15-wheezy-raspian-minimal.img

Done. We now have a 84 MB minimal Raspbian image.

It’s certainly possible to even go slightly lower, as a basic debootstrap of Debian unstable comes out at 269MB uncompressed, and using Emdebian Grip might even allow a ~100 MB uncompressed rootfs with all the features we need, but I doubt this option is available with Raspbian mirrors (TBC).