After setting up the Raspberry Pi, it’s a good idea to make your own installation image from it. This mainly involves using the dd command to clone the SD card into a file. However, there are some extra steps that can be used to produce a smaller file, and to provide a helpful login message to anyone using the image.

Preparation on the running system

After setting up your Raspberry Pi - but before shutting it down - prepare the installed system for imaging.

Edit the login message to detail setup tasks required on logon:

echo -e "\e[47;30;1m
Please generate new host keys by using the following commands:
  rm /etc/ssh/ssh_host_*
  dpkg-reconfigure openssh-server

Set user and root passwords with 'sudo passwd $(logname) && sudo passwd'

You should also use 'sudo raspi-config' to change the hostname
and expand the filesystem to fill the SD card.

Use the following command to suppress this message in future:
  touch ~/.hushlogin
\e[0m" | sudo tee /etc/motd

# ensure the message is shown
rm -f /home/$(logname)/.hushlogin

Clean up the system by removing any unneeded files and private user data.

# login as root
sudo -s

# clean up downloaded packages, log, caches, etc.
apt-get clean
find /var/log -type f -delete
du -sch /var/cache/*
df -h /

# backup files from home directory before removal
cd /home/$(logname)
zip -FS -ry1 /media/KEY/pihome.zip .

# remove any other unneeded or private user data
nano /etc/network/interfaces
nano /etc/wpa_supplicant/wpa_supplicant.conf

# list of temp files to remove from home dir
tmpfiles=".*_history .lesshst *.log .cache/ .hushlogin"
# list of config files/dir to remove from home dir
dotfiles=".local/ .gem/ .npm/ .git__/  .ssh__/"
# remove transient and config files for root and user home
for u in /home/$(logname) /root; do echo &&
  cd $u && pwd && rm -rfv $tmpfiles $dotfiles
  ls -A
done

Zero fill the unused SD card space for better compression. This can instead be done with an image file1 if you’re concerned wearing out the card, or just want better speed.

# zero fill the swap file
swapoff -a
dd if=/dev/zero of=/var/swap bs=1M count=100
mkswap /var/swap

# zero fill the filesystem
for vol in /boot /; do
  dd if=/dev/zero bs=1M of=$vol
done

# shutdown and remove the card
poweroff

Here’s the basic command to copy an SD card into a file. The size is correct for the current Raspbian image at raspberrypi.org, and can be confirmed by viewing the size of the original uncompressed image: unzip -l raspbian.zip, or by using fdisk2.

# location and size of SD card
dev=/dev/rdisk2 size=1238

# image name variables
date=$(date +%Y%m%d) name=raspbian-minimal

# make uncompressed dd image
# sudo dd if=$dev of=$name.img count=$size bs=1m

# make compressed dd image on the fly using 7z
sudo dd if=$dev count=$size bs=1m | \
  7za a -mf- $date-$name.img.7z -si$name.img
  1. The easiest way I’ve found to mount the image as writable, is to first create loopback devices using gnome-disk-image-mounter -w. You can also calculate the partition offsets and use mount directly. 

  2. Use fdisk to view the partition table info of the SD card, then calculate the total amount to copy using bc:

    # confirm the above values
    sudo fdisk $dev  # append '-l' flag on linux
    
    # on OS X, add the last partition start to its size
    bc -l <<< '(122880+5662720)/2/1024'
    
    # on Linux, use the last partition block
    bc -l <<< '(5785599+1)/2/1024'