pi-gen: Stage Specification

In the GitHub page for pi-gen, there is a section on Stage Specification. However the example there is a little misleading. I wanted to run until stage3 and export an image from that stage, but because the example showed only touching the SKIP files, I did not realised that the EXPORT_IMAGE file is what the export script was looking for (until I read the export script….).

So basically in a nutshell:

  • SKIP files will only instruct pi-gen which stages to skip, nothing to do with any image export
  • EXPORT_IMAGE is required in the folder for which the stage you want an image to be exported.

The image suffix can be configured, just put a one-line IMG_SUFFIX="-my-own-image" in the EXPORT_IMAGE file at the appropriate stage folder.

pi-gen: Enabling ssh by default

There are some system services that you can enable or disable by default. ssh is disabled by default, which I presume is due to security reasons, but for my purpose it is easier to manage the RPi’s if I have ssh access. For a start, I want my RPi’s to listen to ssh, will be putting in the security measures gradually.

To enable ssh by default, change stage2/01-sys-tweaks/01-run.sh:

-systemctl disable ssh
+systemctl enable ssh

There are other services in this page that you can choose to enable or disable

pi-gen: Timezone and Locales

The tweaks here are minor, Just documenting so that I will not forget. The changes relevant to me are:

In stage0/01-locale/00-debconf

-tzdata	tzdata/Areas	select	Etc
+tzdata	tzdata/Areas	select	Asia


-tzdata	tzdata/Zones/Etc	select	UTC
+tzdata	tzdata/Zones/Etc	select	GMT+8

In stage2/01-sys-tweaks/00-debconf

-keyboard-configuration	keyboard-configuration/xkb-keymap	select	gb
+keyboard-configuration	keyboard-configuration/xkb-keymap	select	us

One thing to note that it is through this that I know that the “|” character is not on the default GB keyboard layout, have to change it to the US Keyboard.

pi-gen: Setting default WiFi settings

In Raspbian, the WiFi settings are found in /etc/wpa_supplicant/wpa_supplicant.conf. In my use case, all my RPis are in the same WiFi network, and it is easier for me to write that setting in the image.

Before writing the settings, we also need to get the pre-shared-key (psk) in hashed mode instead of storing it in the clear in the .conf file. To get the hashed psk, do the following at the command line:

wpa_passphrase [SSID] [wifi password]

for example:

wpa_passphrase MarvelWorld SpideyIsHome2017

which will return


put this into stage2/02-net-tweaks/files/wpa_supplicant.conf:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


Note that I changed the country to SG. You should change it to where you are using the RPi.

pi-gen: Changing the Mirror Site URL

There are two ways to run pi-gen, one is to run it within a host that calls the build.sh script to build the image, and the other is to run it within a docker image which in turns calls the same build.sh script. Both works and both take an awful amount of time.

Sometimes this is made worse by the mirror site not responding in time, or somehow serving the wrong headers or the files with the wrong Hash number.

[To do, add the actual error messages]

One way to work around this is to manually put in a different mirror site URL. I got the idea from https://www.reddit.com/r/raspberry_pi/comments/4bl4ia/mirrordirectorraspbianorg_not_working/ which suggested using http://mirror.leaseweb.com, which will automatically give you a site that is geographically close to your site. However, this is what the original mirrordirector.raspbian.org would already have done, and it sometimes still fails.

What I have done was to refer to https://www.raspbian.org/RaspbianMirrors, and choose the site that I feel is closest to me or fastest to load. This might not be very scientific, but it is good enough. If you want to get one more step more scientific, you can install the Page load time Chrome extension from https://github.com/alex-vv/chrome-load-timer which will tell you the time a page is loaded. Click on the http links in the RaspbianMirrors page and determine a site that is fast enough for yourself. I found a few with load time of 0.33 seconds or there about.

Once I find a mirror site I want to use (in my case http://mirror.premi.st, I don’t know why but for some reason a South Korea site is fast for me in Singapore), I can change the following files in pi-gen:


#!/bin/bash -e
if [ ! -d ${ROOTFS_DIR} ]; then
bootstrap jessie ${ROOTFS_DIR} http://mirror.premi.st/raspbian/raspbian


#deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi
deb http://mirror.premi.st/raspbian/raspbian/ jessie main contrib non-free rpi

Building your own Raspbian Image for Raspberry Pi: pi-gen

My recent project requires the use of the Raspberry Pi (RPi for short). I bought one early in June and has been playing with it for about 2 months. Quite an interesting adventure. As I needed to deploy a number of RPi’s, I had to do something to make the configuration management more sane for myself. I started with trying to build a standard image for all my RPi’s, and (my current planned approach) use Ansible to configure the parts that are different.

Good that that Raspbian provides an open source repository for the project they use to generate the Raspbian image at https://github.com/RPi-Distro/pi-gen.

I spent quite some time on this and here are some learning points I have:

There are two ways to run pi-gen, one is to run it within a host that calls the build.sh script to build the image, and the other is to run it within a docker image which in turns calls the same build.sh script.

Once you have completed the modifications above, you can start to run pi-gen using one of these two methods.