-
-
Notifications
You must be signed in to change notification settings - Fork 0
Pi Image Setup Guide
This page describes how I create the image file used on the Raspberry Pi. Regular users don't need this, but I've put this here for reference and because others might find this useful.
All steps are performed on a Linux machine with the Raspberry Pi SD card mounted via a card reader. The root partition is assumed to be mounted at /media/$USER/rootfs and the boot partition at /media/$USER/bootfs.
Requirements: This guide targets Raspberry Pi OS Trixie Lite. Both 32-bit and 64-bit are supported. Use the 32-bit image for the Pi Zero W, and the 64-bit image for the Pi Zero 2W, Pi 3, Pi 4, or Pi 5.
Did you find this tool useful? Feel free to support my open source tools - especially when using them commercially:
Trixie includes cloud-init, which handles first-boot configuration via two files on the boot partition:
-
user-data- creates the user, sets the hostname, installs Python dependencies, and starts our bridge service -
network-config- configures WiFi
Users only need to edit network-config to enter their WiFi credentials before first boot. Both files live on the FAT32 boot partition, so they are editable on Windows, Mac, and Linux without needing root.
lsblkIdentify the device (e.g. /dev/sda) and note where the partitions are mounted, for example:
-
Root partition ->
/media/$USER/rootfs -
Boot partition ->
/media/$USER/bootfs
If the partitions are not mounted yet:
sudo mkdir -p /media/$USER/rootfs /media/$USER/bootfs
sudo mount /dev/sda2 /media/$USER/rootfs
sudo mount /dev/sda1 /media/$USER/bootfsThese two files replace the wifi-setup service, user creation, and first-boot service from the old approach. They go on the boot partition and are processed automatically on first boot by cloud-init.
This is the file end users edit to connect to their WiFi network. Replace the existing network-config on the boot partition:
cat > /media/$USER/bootfs/network-config << 'EOF'
network:
version: 2
wifis:
wlan0:
dhcp4: true
# Change this to your country code (ISO 3166-1 alpha-2)
regulatory-domain: "NL"
access-points:
"YourNetworkName":
password: "YourPassword"
optional: false
EOFThis creates the bridge user, sets the hostname, installs Python dependencies on first boot, enables the bridge service, and disables cloud-init after it has run. Replace the existing user-data on the boot partition:
(generate the hashed password using: echo 'littleprinterlives' | openssl passwd -6 -stdin)
cat > /media/$USER/bootfs/user-data << 'EOF'
#cloud-config
hostname: little-printer-zigbee-bridge
manage_etc_hosts: true
timezone: Europe/Amsterdam
# 1. Create bridge user
users:
- name: bridge
groups: users,adm,dialout,audio,netdev,video,plugdev,cdrom,games,input,gpio,spi,i2c,render,sudo
shell: /bin/bash
lock_passwd: false
passwd: "$6$boqkDuR6gaVxXbFA$glw/miVRIqHulbFK0Bebyyov0NKQ3z7tlyUS7RYkXGjDozcEiSG.jSw2IDSI/ghItMpaJx/92Zajr.v6ebqmU1"
# Uncomment to start ssh
# runcmd:
# - systemctl enable ssh
# - systemctl start ssh
enable_ssh: false
rpi:
i2c: true
spi: true
# 2. Update system packages
package_update: true
packages:
- libopenjp2-7
- python3-pip
- git
- libfreetype-dev
# 3. Create service file
write_files:
- path: /etc/systemd/system/little-printer-zigbee-bridge.service
permissions: '0644'
owner: root:root
content: |
[Unit]
Description=Little Printer Zigbee Bridge Script
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=bridge
WorkingDirectory=/opt/little-printer-zigbee-bridge
ExecStartPre=/bin/sh -c 'until ping -c1 1.1.1.1 > /dev/null 2>&1; do sleep 2; done'
ExecStart=/usr/bin/env python3 -m bridge.main --sirius
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
runcmd:
# Block execution until network is online
- until ping -c1 1.1.1.1 > /dev/null 2>&1; do sleep 2; done
# 4. Clone the repository into /opt
- git clone https://github.com /opt/little-printer-zigbee-bridge
# 5. Transfer folder ownership to the bridge user so it can generate config.json
- chown -R bridge:bridge /opt/little-printer-zigbee-bridge
# 6. Install python requirements globally (system-level matching your service's python execution)
- cd /opt/little-printer-zigbee-bridge && pip3 install -r bridge/requirements.txt --break-system-packages
# 7. Tell systemd to find the file created by write_files, then boot it up
- systemctl daemon-reload
- systemctl enable little-printer-zigbee-bridge.service
- systemctl start little-printer-zigbee-bridge.service
# 8. Disable cloud-init for subsequent boots
- touch /etc/cloud/cloud-init.disabled
EOFNot needed anymore: we now just clone the repo on the first start.
Copy the bridge project onto the image. Ownership will be fixed by cloud-init's runcmd on first boot.
sudo cp -r /path/to/little-printer-zigbee-bridge /media/$USER/rootfs/opt/little-printer-zigbee-bridge
Restore network-config to placeholder values - the same file from step 2a but with your actual credentials replaced:
cat > /media/$USER/bootfs/network-config << 'EOF'
network:
version: 2
renderer: NetworkManager
wifis:
wlan0:
dhcp4: true
# Change this to your country code (ISO 3166-1 alpha-2)
regulatory-domain: "NL"
access-points:
"YourNetworkName":
password: "YourPassword"
optional: false
EOFsudo rm -f /media/$USER/rootfs/root/.bash_history
sudo rm -f /media/$USER/rootfs/home/bridge/.bash_historysudo rm -f /media/$USER/rootfs/etc/machine-id
sudo rm -f /media/$USER/rootfs/var/lib/dbus/machine-id
sudo touch /media/$USER/rootfs/etc/machine-idAn empty /etc/machine-id triggers a fresh ID to be generated on first boot.
sudo rm -rf /media/$USER/rootfs/var/log/journal/*
sudo rm -rf /media/$USER/rootfs/var/log/*.log
sudo rm -rf /media/$USER/rootfs/tmp/*
sudo rm -rf /media/$USER/rootfs/var/tmp/*sudo umount /media/$USER/rootfs
sudo umount /media/$USER/bootfsReplace /dev/sda with your actual device from lsblk:
sudo dd if=/dev/sda of=~/little-printer-zigbee-bridge.img bs=4M status=progresswget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh
sudo ./pishrink.sh -z ~/little-printer-zigbee-bridge.imgThis creates little-printer-zigbee-bridge.img.gz, compressed and shrunk to the minimum size needed.
- Download
little-printer-zigbee-bridge.img.gzand flash it to an SD card using Raspberry Pi Imager or balenaEtcher - After flashing, open the boot partition of the SD card (visible on Windows, Mac, and Linux as a small FAT drive)
- Open
network-configand replaceYourNetworkNameandYourPasswordwith your WiFi credentials - Optionally update
regulatory-domainto your country code (e.g.GB,US,DE) - Save the file, eject the SD card, and insert it into the Raspberry Pi
- Power on - the Pi will configure WiFi, install Python dependencies, and start the bridge automatically on first boot. The first boot takes a little longer than usual while dependencies are installed.
Bridge does not start Check the cloud-init log to see if first-boot setup completed:
sudo cat /var/log/cloud-init-output.logWiFi never comes up Check NetworkManager and the network-config that was applied:
sudo systemctl status NetworkManager
sudo cat /var/log/cloud-init-output.log | grep -i networkScript starts before network is ready
The ExecStartPre ping loop should make the script wait until internet is reachable.
Check bridge service status
sudo systemctl status little-printer-zigbee-bridge.service
sudo journalctl -u little-printer-zigbee-bridge.service