Skip to content

How to build Raspberry PI image

We need to make a Raspberry aarch64 image that contains all the configurations, printer drivers and binaries ready to auto start.

There are currently two ways on the internet to build a custom image from config files:

rpi-image-gen uses pi-gen internally.

Both tools currently do not support qemu emulation, meaning that in order to build an image you need a real Raspberry PI and run these tools there, which doesn’t make sense.

I was able to run these tools in a docker container with qemu emulation but they just compile everything from source and take hours to build, which does not save any time.

So I came up with a solution that just works.

First, we have to create an image manually and then I created an image-patcher that will apply the updates to the image without having to write the image to Raspberry Pi and build it again.

This solution can work for just config files and binaries but if you need to install any packages then you have to build the image from scratch.

NOTE: You also need to get tmate config from 1password and put it in repository/config/.tmate.conf.

Download the RPI image writer for your OS and then run it.

Inside, choose model as no filter and image as Raspberry Pi OS Lite (64-bit) and choose your location.

You MUST apply the following config before writing to the image:

hostname: raspberrypi
username: pantryclub
password: batman
configure_wifi: optional
set locale settings
timezone: Africa/Johannesburg
keyboard layout: English (US)
enable ssh: yes
use_password: yes

Make sure to apply these settings and then write the image.

Plug the SD card into the Raspberry Pi and boot it up.

You can then connect via SSH with ssh pantryclub@raspberrypi.local, enter the password and you will be in.

  1. Update the system
sudo apt update
sudo apt upgrade
  1. Install the needed packages
sudo apt install usbutils cups cups-client cups-bsd cups-filters foomatic-db-compressed-ppds printer-driver-all openprinting-ppds hpijs-ppds hp-ppd hplip smbclient printer-driver-cups-pdf printer-driver-splix cups-browsed tmate
  1. Set up the image
  • Create work directory sudo mkdir -p /opt/rpi-printer/master
  • Move the aarch64 binaries from repository/zig-out/bin to /opt/rpi-printer/master
  • Copy the tmate config from repository/config/.tmate.conf to /opt/rpi-printer
  • Overwrite cupsd.conf at /etc/cups/cupsd.conf with the one from repository/config/cupsd.conf
  • Overwrite sudoers at /etc/sudoers with the one from repository/config/sudoers with SAME PERMISSIONS
  • Copy systemd service file from repository/config/rpi-printer.service to /etc/systemd/system/rpi-printer.service
  • Enable the service sudo systemctl enable rpi-printer
  • Disable cups service sudo systemctl disable cups cups-browsed
  • Check tmate works with tmate -f /opt/rpi-printer/.tmate.conf
  • Reboot and check binaries are auto starting
  • Debug if anything goes wrong

Take out the SD card and plug it into the computer and you can use DD to create an image from the SD card. Or if you are using Linux Gnome then you can use Disks app to create an image.

You will then have a pantryclub.img file.

It will create a complete image of your SD card so if you have a 32GB card then the image will be 32GB.

You can shrink it with the pi-shrink tool.

That will shrink the image to 3.8GB or so.

You can always compress this file with any compression tool. I suggest XZ that will compress it to 700-800MB.

You can distribute this image or release it on GitHub, which is explained in the release section.

I created an image-patcher.sh script that will apply the updates to the image without having to write the image to Raspberry Pi and build it again.

It assumes that you already have a working image either built manually or downloaded from the GitHub release. That image must work.

This is very helpful when you just want to change the config files or binaries in the image without creating an image from scratch.

Just download the previous image from GitHub and move it to the repository/images with the name of pantryclub.img. Remember the image file must be an image file and not any compressed file.

Then run the patcher, start the docker container and run the script:

Terminal window
docker compose run --rm builder bash

Move to the rpi-printer-service directory and run the script:

Terminal window
./image-patcher.sh

This will apply all the updates from repository/config to the image and move the repository/zig-out/bin binaries to /opt/rpi-printer/master.

You will have a new image as pantryclub-DD-MM-YYYY.img which you can directly write to the SD card and it will work.

The image-patcher is only for updating the file content in the image. If you want to install any kind of package or want to run any command, then you have to write the image to the SD card and run it in the Raspberry Pi. After applying your changes, create the image again with your card and add it to the next GitHub release.