-
Notifications
You must be signed in to change notification settings - Fork 3
Pi Install Script
host/run/pi/install.sh is a one-shot installer that turns a bare Raspberry Pi (or generic Ubuntu/Debian box) into a turnkey Backyard Hero appliance — a self-contained firework controller that broadcasts its own WiFi network, auto-starts at boot, and is reachable from any phone at http://backyardhero/.
This is the recommended way to set up a Raspberry Pi as a Backyard Hero controller. Start from a fresh Raspberry Pi OS (64-bit) install, run the script, and you're done.
What the installer is NOT. It is not interactive in the "guide me through each step" sense — it accepts flags, picks defaults for everything else, and runs to completion. Re-running it is safe; it's fully idempotent.
In order, from a fresh Pi OS / Ubuntu install:
-
Sanity-check the OS and architecture. Bails out cleanly on 32-bit Pi OS, since the Docker image is multi-arch but built for
arm64/amd64only. -
Install runtime dependencies via
apt:docker.io+docker-compose-v2,python3,python3-venv,hostapd,dnsmasq,iw,rfkill,iptables,git,curl,jq,avahi-daemon. -
Add the target user to the
dockeranddialoutgroups so they can talk to the dongle and run docker withoutsudo. -
Locate (or clone) the backyardhero repo. If you're already inside a checkout the installer reuses it in place. Otherwise it clones to
/opt/backyardhero. -
Drop a udev rule at
/etc/udev/rules.d/99-byh-dongle.rulesthat creates a stable/dev/byh_donglesymlink for any USB-CDC device with the Espressif vendor ID (0x303a). The dongle keeps the same name regardless of which/dev/ttyACM*slot it landed on after a reboot. -
Auto-detect the dongle right now (before reboot) and write the result into
host/config/systemcfg.json, preferring/dev/byh_dongleand falling back to whatever/dev/ttyACM*it sees. -
Pre-pull
os4ivmb/backyardhero:latestso the first boot doesn't need internet. -
Install the
byh-host.servicesystemd unit that wrapshost/run/pi/start.sh, plus path-watcher units for UI-driven AP configuration (byh-ap-apply.service+.path) and UI-driven system updates (byh-update.service+.path). -
Configure the Pi's on-board WiFi as an isolated WPA2 access point using
hostapd+dnsmasq. The AP runs on a separate/24(default192.168.42.0/24) and the web UI is reachable at the gateway IP and atbackyardhero.localvia mDNS. -
Install NAT so AP clients can reach the internet through the Pi's other uplink (typically
eth0). Setsnet.ipv4.ip_forward=1via/etc/sysctl.d/99-byh-ap-nat.confand adds aniptablesMASQUERADE rule wrapped inbyh-ap-nat.service. -
Hand
/opt/backyardheroownership to your user so you can rsync/edit code there withoutsudo.
Reboot once when the installer finishes. After that, the Pi is a self-contained controller.
On a fresh Pi OS Bookworm 64-bit (or Ubuntu Server 22.04+ / 24.04) install:
sudo apt update && sudo apt install -y git
git clone https://github.com/os4-ivmb/backyardhero_pyro.git ~/backyardhero
sudo ~/backyardhero/host/run/pi/install.shThat's it. After it finishes:
sudo rebootWhen the Pi comes back up:
- Connect a laptop or phone to the WiFi network it's broadcasting. The default SSID is
BackyardHero-<5-char-suffix>and the default password isbackyardhero. - Open http://backyardhero/ in a browser.
Plug the dongle into any USB port and the system is live.
If you don't override anything, the installer applies:
| Setting | Default |
|---|---|
| Repo URL | https://github.com/os4-ivmb/backyardhero_pyro.git |
| Repo dir | /opt/backyardhero |
| Branch | main |
| AP SSID |
BackyardHero-<5 chars of machine-id> (stable per Pi) |
| AP password | backyardhero |
| WiFi interface | wlan0 |
| AP gateway IP | 192.168.42.1 |
| AP subnet |
/24 (i.e. 192.168.42.0/24) |
| DHCP pool | 192.168.42.50 – 192.168.42.150 |
| WiFi channel |
6 (2.4 GHz) |
| Regulatory country | US |
| App port (in container) |
1776 (also bound on host port 80 for friendly URL) |
| systemd unit name | byh-host.service |
The default WPA2 password backyardhero is intentionally weak. Change it from the UI (Settings → Network → WiFi access point) or by passing --password '...' to the installer.
WiFi access point:
--ssid NAME AP SSID (default: BackyardHero-<hostsuffix>)
--password PASS WPA2 passphrase, 8+ chars (default: backyardhero)
--wifi-iface IFACE Wireless interface (default: wlan0)
--ap-ip IP Gateway IP for the AP (default: 192.168.42.1)
--ap-cidr N Netmask in CIDR bits (default: 24)
--ap-dhcp-start IP First DHCP lease (default: 192.168.42.50)
--ap-dhcp-end IP Last DHCP lease (default: 192.168.42.150)
--ap-channel N 2.4 GHz channel 1-13 (default: 6)
--country CC WiFi regulatory country (default: US)
--no-ap Skip all AP configuration.
--no-nat Skip the NAT step that routes AP clients out
via the Pi's other uplink (e.g. eth0).
Repo / service:
--repo-url URL Git clone URL (default: upstream)
--repo-dir DIR Where to clone (default: /opt/backyardhero)
--branch BRANCH Branch / tag to check out (default: main)
--user USER User to add to docker+dialout groups
(default: $SUDO_USER or first non-root login user)
--no-service Don't install the systemd auto-start unit.
--no-docker-pull Don't pre-pull the image (deferred to first boot).
General:
-y, --yes Non-interactive, accept every default.
--uninstall Remove services + AP config (keeps repo & image).
-h, --help Show this message.
A pure unattended install with sensible defaults:
sudo /opt/backyardhero/host/run/pi/install.sh -yCustom SSID and password (the only changes you'll typically want):
sudo /opt/backyardhero/host/run/pi/install.sh \
--ssid PyroPi-East \
--password 'longerthan8chars' \
--country GBInstall Backyard Hero but leave the Pi's WiFi alone (e.g. you want the Pi joined to your house WiFi instead, with no AP at all):
sudo /opt/backyardhero/host/run/pi/install.sh --no-apUse the Pi as a controller on a venue's WiFi but still broadcast an AP for phones (skip NAT so AP clients can't reach the internet through the Pi):
sudo /opt/backyardhero/host/run/pi/install.sh --no-natInstall from a non-default branch (e.g. testing a feature branch):
sudo /opt/backyardhero/host/run/pi/install.sh --branch experiment/fooAfter a successful install:
| Path | Purpose |
|---|---|
/opt/backyardhero/ |
The cloned repo. Owned by the target user. |
/etc/systemd/system/byh-host.service |
Auto-start unit. ExecStart = host/run/pi/start.sh. |
/etc/systemd/system/byh-ap-iface.service |
Configures wlan0 as the AP gateway at boot. |
/etc/systemd/system/byh-ap-apply.{service,path} |
UI-driven SSID/password apply pipeline (see WiFi Access Point). |
/etc/systemd/system/byh-ap-nat.service |
NAT MASQUERADE rules for AP-client internet. |
/etc/systemd/system/byh-update.{service,path} |
UI-driven system-update pipeline. |
/usr/local/sbin/byh-ap-apply.py |
Apply script invoked by the path-watcher. |
/usr/local/sbin/byh-ap-nat.sh |
NAT rule loader. |
/usr/local/sbin/byh-update.py |
Update apply script. |
/etc/udev/rules.d/99-byh-dongle.rules |
Stable dongle symlink rule. |
/etc/hostapd/hostapd.conf |
The AP's WPA2 config (SSID, password, channel). |
/etc/default/hostapd |
Points hostapd at the conf above. |
/etc/dnsmasq.d/backyardhero.conf |
DHCP + DNS for the AP, including the *.local hostname aliases. |
/etc/sysctl.d/99-byh-ap-nat.conf |
net.ipv4.ip_forward=1. |
/opt/backyardhero/host/data/byh_ap_current.json |
Seed file for the UI's "current AP config" view. |
/opt/backyardhero/host/data/backyardhero.db |
SQLite (created on first boot by the web app). |
Right after the reboot:
# 1. The host service should be active.
sudo systemctl status byh-host
# active (running) -- start.sh is up, the container is up.
# 2. The container should be running.
docker ps
# CONTAINER ID IMAGE ... NAMES
# abc123def456 os4ivmb/backyardhero:latest ... firework-system
# 3. hostapd and dnsmasq should be running.
systemctl status hostapd dnsmasq
# 4. NAT rules should be loaded.
sudo iptables -t nat -L POSTROUTING -n -v
# ... MASQUERADE all -- 192.168.42.0/24 anywhere
# 5. The dongle should have a stable name (if plugged in).
ls -l /dev/byh_dongle
# lrwxrwxrwx 1 root root 7 ... /dev/byh_dongle -> ttyACM0
# 6. The web UI should answer locally.
curl -sS -o /dev/null -w '%{http_code}\n' http://localhost/
# 200From a client device on the AP:
ping backyardhero.local
# 64 bytes from 192.168.42.1: ...Open http://backyardhero/ in a browser. The Console tab should load.
sudo systemctl status byh-host # is it running?
sudo systemctl restart byh-host # restart after config changes
sudo journalctl -u byh-host -f # tail the stack logs
sudo journalctl -u hostapd -u dnsmasq -f # tail the AP logs
sudo journalctl -u byh-ap-apply -f # tail UI-driven AP changes
# Update everything (source + image + system state + restart):
sudo /opt/backyardhero/host/run/pi/update.shFor more on updating, see Updating the Pi.
Every step is idempotent. Re-running is safe and is the recommended way to:
- Pick up new system-level changes after a
git pull(or useupdate.sh, which calls the installer for you). - Change AP defaults (pass new
--ssid/--passwordflags). The installer rewriteshostapd.confand reloadshostapd. - Reset the dongle udev rule after upgrading firmware or replacing hardware.
sudo /opt/backyardhero/host/run/pi/install.sh -yPass -y to accept every existing default and avoid prompts.
sudo /opt/backyardhero/host/run/pi/install.sh --uninstallRemoves:
- The
byh-host.service, the AP iface/apply units, the NAT unit, and the UI-driven update units (disable + delete). - The udev rule.
-
hostapd.conf, the dnsmasq drop-in, and the sysctl drop-in. - The seed
byh_ap_current.jsonfile.
Leaves behind:
- The cloned repo at
/opt/backyardhero(your data, config, and any local edits). - The Docker image (
os4ivmb/backyardhero:latest). - The apt-installed system packages.
If you want a truly clean slate, after --uninstall:
sudo rm -rf /opt/backyardhero
docker rmi os4ivmb/backyardhero:latest
sudo apt purge -y hostapd dnsmasq-
The Pi's regulatory domain is unset. On Pi OS Bookworm the WiFi country must be set before
hostapdwill broadcast. The installer callsraspi-config nonint do_wifi_country USwhenraspi-configis present; on plain Ubuntu Server you may need to edit/etc/wpa_supplicant/wpa_supplicant.confand reboot. Override the default with--country GB(or your code). -
rfkillhas WiFi soft-blocked. Runrfkill listandsudo rfkill unblock wlanif you seeSoft blocked: yes. The installer attempts this, but a manual override stays in effect across reboots. -
NetworkManager keeps reclaiming the interface. The installer drops a NetworkManager
unmanaged-devicesconfig so this shouldn't happen, but if you have a pre-existing aggressive setup, runsudo systemctl restart NetworkManagerafter the install to force a re-read.
The installer prints a warning and continues — the image will get pulled lazily on first start.sh. If the Pi is on an AP-only deployment with no upstream internet, run the pre-pull manually from a Pi that briefly has internet, before deployment.
Check journalctl -u byh-host. The most common causes:
-
/dev/byh_dongledoesn't exist (no dongle plugged in, or udev hasn't reloaded). The systemd unit retries automatically, but if it's tight-looping inspectstart.sh's log. - Container can't pull image and there's no cached one. Pre-pull or check upstream connectivity.
The host-side flash_server.py binds to 0.0.0.0:9001 so the daemon inside the container can reach it via host.docker.internal. If you get a connection refused, the bridge isn't running. Either:
- Restart the bridge through the host service:
sudo systemctl restart byh-host. - Or in dev mode, restart
host/run/pi/start-dev.sh.
See Flashing a Dongle for more.
The installer chowns the repo to the target user — but only on install. If you ran it as root originally without --user, run it again with --user <you> or sudo chown -R "$USER:$USER" /opt/backyardhero directly. After that, rsync from your dev box works without sudo.
- WiFi Access Point — how the AP, NAT, and friendly URLs work, and how to change them from the UI.
-
Updating the Pi —
update.shwalkthrough. - Flashing a Dongle — including the UI-driven dongle flash flow.
-
Connecting the dongle — the
/dev/byh_donglesymlink and serial-port discovery. -
Production vs Development Mode — the two
start*.shflavors.
Getting started
- Overview
- Desktop installers (macOS / Windows)
- macOS
- Linux
- Windows
- Production vs Development
- Connecting the dongle
- Flash a receiver
- Flash a dongle
- OTA flashing
Raspberry Pi
System overview
Subsystems
Hardware
- Receiver firmware
- Dongle firmware
- RF protocol
- Contributor Portal — BOMs, schematics, and board resources
UI walkthrough
Reference
Downloads
- Firmware
- Installers
Module Build & User Guides
- Cue
- Receiver
- Dongle