Complete guide to available services and creating custom ones.
Purpose: Essential system configuration for all images
Packages:
raspberrypi-kernel- RaspiOS kernel with RP1 driversraspberrypi-bootloader- Boot firmwarefirmware-brcm80211- WiFi/Bluetooth firmwareNetworkManager- Network managementopenssh-server- SSH access- Essential utilities
Configuration:
- RaspiOS APT repository + pinning
- Network bridges (br-wan, br-lan if dual NIC)
- SSH enabled
- MOTD with IP addresses
First-boot actions:
- Partition resize to fill SD card
- Network interface name persistence
- Bridge configuration based on detected NICs
Purpose: Incus container/VM platform with KVM acceleration
Dependencies: None
Packages:
qemu-kvm- KVM virtualizationincus- Container/VM managerincus-tools- Management utilities
Configuration:
- Incus initialization with default profile
- Network bridges: br-wan (WAN), br-lan (LAN if dual NIC)
- Storage pool: default (dir backend)
First-boot actions:
- Create br-lan and br-wan bridges (if not exist)
- Configure Incus network integration
- Enable IP forwarding and NAT
Use cases:
- Run VMs (Home Assistant, OpenWrt)
- Create containers for isolated services
- Development environments
Purpose: Docker Engine with Portainer and Watchtower
Dependencies: None
Packages:
docker-ce- Docker Enginedocker-ce-cli- Docker CLIcontainerd.io- Container runtime
Configuration:
- Docker installed from official repository
- User
piadded todockergroup
First-boot actions:
- Deploy Portainer (web UI for Docker)
- Deploy Watchtower (automatic container updates)
- Configure bridge networking
Services deployed:
- Portainer:
https://raspberry-ip:9443 - Watchtower: Automatic updates for containers
Use cases:
- Run containerized applications
- Manage containers via web UI
- Auto-update containers
Purpose: Home Assistant OS in an Incus VM
Dependencies: qemu (Incus required)
Packages: None (VM image downloaded at first boot)
First-boot actions:
- Download Home Assistant OS image (latest stable)
- Create Incus VM named
haos - Allocate resources (2 vCPUs, 4GB RAM, 24GB disk)
- Configure network bridge (br-lan or br-wan)
- Detect and pass through USB Zigbee coordinators
- Start VM
Zigbee auto-detection:
- Scans
/dev/ttyUSB*and/dev/ttyACM* - Detects ConBee, CC2652, Sonoff, Silicon Labs dongles
- Passes through via USB vendor/product ID
Access:
- Home Assistant:
http://raspberry-ip:8123 - First boot setup takes 5-10 minutes
Use cases:
- Home automation platform
- Zigbee/Z-Wave integration
- IoT device management
Purpose: OpenWrt router in an Incus container
Dependencies: qemu (Incus required)
Packages: None (container image downloaded at first boot)
First-boot actions:
- Download OpenWrt rootfs image
- Create Incus container named
openwrt - Allocate resources (1 vCPUs, 1GB RAM, 24GB disk)
- Configure network: eth0 → br-wan, eth1 → br-lan
- Set static IP:
192.168.10.1/24 - Start container
Network configuration:
- WAN: br-wan (DHCP client)
- LAN: br-lan (192.168.10.1, DHCP server)
Access:
- LuCI web UI:
http://192.168.10.1 - SSH:
ssh root@192.168.10.1
Use cases:
- Advanced routing and firewall
- VPN server/client
- QoS and traffic shaping
- Network monitoring
Purpose: WiFi access point (2.4GHz/5GHz)
Dependencies: None
Packages:
hostapd- WiFi access point daemon
Configuration files:
hostapd-5ghz.conf- 5GHz AP confighostapd-2.4ghz.conf- 2.4GHz AP config
First-boot actions:
- Detect WiFi interfaces (wlan0, wlan1)
- Configure hostapd based on detected adapters:
- Dual WiFi: 2.4GHz (wlan0) + 5GHz (wlan1)
- Single WiFi: 5GHz (wlan0)
- Attach to br-lan (if exists) or br-wan
- Disable NetworkManager management of WiFi
- Start hostapd services
Default credentials:
- SSID:
RaspberryPi-WIFI - Password:
raspberry
Use cases:
- WiFi access for IoT devices
- Guest network
- Extend network coverage
./bin/autobuild --image debian- Base Debian with RaspiOS kernel
- SSH access
- Network bridges
./bin/autobuild --image debian/docker- Docker Engine
- Portainer web UI
- Watchtower auto-updates
./bin/autobuild --image debian/qemu- Incus containers/VMs
- KVM acceleration
./bin/autobuild --image debian/qemu+haos- Home Assistant OS VM
- Zigbee dongle auto-detection
- Web UI on port 8123
./bin/autobuild --image debian/qemu+openwrt+hotspot- OpenWrt routing
- Dual-band WiFi hotspot
- Advanced firewall/QoS
./bin/autobuild --image debian/qemu+docker+openwrt+hotspot+haos- All services combined
- Ideal for Raspberry Pi 5 with 8GB RAM
images/debian/services/myservice/
├── setup.sh # Required: package installation (runs in QEMU)
├── first-boot/
│ └── init.sh # Optional: runtime config (runs on first boot)
├── setupfiles/ # Optional: static files → /etc/setupfiles/
│ ├── config.conf
│ └── script.sh
├── depends.sh # Optional: dependencies
└── motd.sh # Optional: MOTD content
Executed in QEMU ARM64 during build.
Template:
#!/bin/bash
set -e
# Install packages
apt update
apt install -y package1 package2
# Configure system
systemctl enable my-service
# Copy files
cp /etc/setupfiles/config.conf /etc/my-service/Best practices:
- Use
set -eto exit on errors - Install packages from Debian repositories when possible
- Add custom repositories if needed
- Enable systemd services that should start at boot
- Don't start services (no network in QEMU)
Executed on first boot on Raspberry Pi.
Template:
#!/bin/bash
set -e
# Detect hardware
if ip link show eth1 >/dev/null 2>&1; then
BRIDGE="br-lan"
else
BRIDGE="br-wan"
fi
# Download resources
wget https://example.com/resource.tar.gz -O /tmp/resource.tar.gz
# Create containers/VMs
incus launch images:alpine mycontainer
# Configure services
systemctl start my-serviceBest practices:
- Detect hardware and adapt configuration
- Download large files here (not in setup.sh)
- Create containers/VMs
- Start services
- Use
/etc/setupfiles/for configuration files
Declare dependencies on other services.
Example:
# myservice depends on qemu
DEPENDS_ON="qemu"Dependency resolution:
- Dependencies are automatically included
- Build order is adjusted to satisfy dependencies
Display service information on login.
Example:
cat <<'EOF'
My Service UI: https://raspberry-ip:8080
Username: admin
Password: (set on first access)
EOFStatic configuration files copied to /etc/setupfiles/.
Access in scripts:
# In setup.sh or first-boot/init.sh
cp /etc/setupfiles/myconfig.conf /etc/my-service/mkdir -p images/debian/services/myservice/first-boot
mkdir -p images/debian/services/myservice/setupfilescat > images/debian/services/myservice/setup.sh <<'EOF'
#!/bin/bash
set -e
apt update
apt install -y nginx
systemctl enable nginx
EOF
chmod +x images/debian/services/myservice/setup.shcat > images/debian/services/myservice/first-boot/init.sh <<'EOF'
#!/bin/bash
set -e
# Configure nginx with custom config
cp /etc/setupfiles/nginx.conf /etc/nginx/sites-available/default
systemctl restart nginx
EOF
chmod +x images/debian/services/myservice/first-boot/init.shcat > images/debian/services/myservice/setupfiles/nginx.conf <<'EOF'
server {
listen 80;
root /var/www/html;
index index.html;
}
EOFcat > images/debian/services/myservice/motd.sh <<'EOF'
cat <<'MOTD'
Nginx: http://raspberry-ip/
MOTD
EOF
chmod +x images/debian/services/myservice/motd.sh# Build image with your service
./bin/autobuild --image debian/myservice
# Flash and boot
sudo dd if=debian-myservice.img of=/dev/sdX bs=4M status=progress
# Check logs on first boot
sudo journalctl -u services-first-bootQEMU stage issues:
# Check QEMU logs
cat images/debian-myservice/qemu-*.log
# Manually test in QEMU
./bin/autobuild --image debian/myservice --skip-compressFirst-boot stage issues:
# On Raspberry Pi, check logs
sudo journalctl -u services-first-boot -f
# Check service status
sudo systemctl status myservice- Install in
setup.sh, notfirst-boot/init.sh - Use official Debian repositories when possible
- Pin package versions if stability critical
- Download large files in
first-boot/init.sh - Don't download in
setup.sh(slows QEMU) - Cache downloads in
/var/cache/if appropriate
- Always detect hardware in
first-boot/init.sh - Adapt configuration based on detection
- Fail gracefully if hardware missing
- Use
set -eto exit on errors - Log errors to journald
- Provide helpful error messages
- Use existing bridges (br-wan, br-lan)
- Don't create new bridges unless necessary
- Check bridge existence before use
- Don't hardcode passwords in scripts
- Use strong default passwords (prompt user to change)
- Enable firewall if service exposed