-
Notifications
You must be signed in to change notification settings - Fork 3
Production vs Development Mode
Backyard Hero ships two ways to run the host stack. Both produce an identical web UI on http://localhost:1776 (or, on a Pi, http://backyardhero/); the difference is where the container's contents come from.
| Property |
Production (start.sh / start.bat) |
Development (start-dev.sh) |
|---|---|---|
| Image | Pulls os4ivmb/backyardhero:latest from Docker Hub |
Builds from host/Dockerfile against the local source tree |
| First-run time | ~2 minutes (pull) | ~10–15 minutes (npm ci + next build + python deps) |
| Disk footprint | ~600 MB image, no source needed | Source tree + image + node_modules (~3 GB) |
| Hot reload | No — code lives inside the image | Yes — byh_app/, pythings/ mounted as volumes |
| Recommended for | Operators, field deployments, Pi installs | Active development, contributors, anyone tweaking firmware integration |
| Compose file | host/run/<platform>/docker-compose.yml |
host/run/<platform>/docker-compose-dev.yml |
Both modes' launchers and compose files live under host/run/<platform>/:
host/run/
├── pi/ # Raspberry Pi (controller; AP, NAT, systemd, install.sh)
├── osx/ # macOS development (Docker Desktop)
├── windows/ # Windows development (Docker Desktop)
└── README.md # platform-picker
Each folder is self-contained: its compose files reference Dockerfile from the repo root (build.context: ../..), but the launcher scripts, compose files, and any platform-specific extras don't share branches with the others. No platform conditionals anywhere — if you can read pi/start.sh you understand exactly what happens on a Pi, without grep-ping across switches.
See host/run/README.md in the repo for the rationale.
This is what you want unless you're modifying the codebase.
- Starts the TCP-to-serial bridge as a host-native Python process (talks to
/dev/byh_dongle,/dev/tty.usbmodem*, orCOMn). -
docker compose -f host/run/<platform>/docker-compose.yml pull— fetches the prebuilt image from Docker Hub. Tolerant of pull failure when offline (Pi installs that run AP-only can boot without internet using the cached image). -
docker compose ... up— starts the container.
The image embeds:
- The pre-built Next.js app (
next buildalready done at image build time). - The Python daemon, websocket server, and dependencies.
- supervisord wiring everything together.
The default tag is :latest. To pin to a specific build:
BYH_IMAGE=os4ivmb/backyardhero:v0.08 ./host/run/<platform>/start.shAvailable tags are listed at https://hub.docker.com/repository/docker/os4ivmb/backyardhero/general.
On a Pi, the right command is sudo host/run/pi/update.sh. It does git pull + docker compose pull + idempotent install.sh + systemctl restart byh-host, in one go.
On macOS / Windows, just stop the running launcher and re-run it. The script always does a docker compose pull before bringing the stack up, so you'll automatically get the newest :latest (or your pinned tag).
To roll back: pin a previous version with BYH_IMAGE=....
For when you're editing the UI, the daemon, or hooking in changed firmware behavior.
The dev compose file (host/run/<platform>/docker-compose-dev.yml) is identical to production except:
-
build: .instead ofimage: ...— the image is built locally fromhost/Dockerfile. -
../../pythings:/app/pythingsand../../byh_app/backyardhero:/app/byh_app/are bind-mounted into the container, so your local changes are visible immediately. -
supervisord.dev.confis used instead ofsupervisord.conf. The dev variant runsnpm run dev(Next.js dev server with HMR) instead ofnpm run start(production build). -
NODE_ENV=development.
On Pi specifically, the dev compose still binds port 80 (for the friendly URL) and still wires host.docker.internal:host-gateway so the in-container daemon can reach the host-side bridge. On macOS / Windows, dev compose binds only 1776 (no port 80) to avoid colliding with whatever else the dev has running.
The daemon (pythings/pc_daemon/pc_daemon.py) does not auto-reload. Restart the daemon process inside the container:
docker exec firework-system supervisorctl restart firework-daemon(The Next.js app under npm run dev does auto-reload — saved JSX changes show up in the browser within a second.)
Firmware (devices/os4_*/...) does not affect the Docker image at all. Build & flash separately:
devices/utils/build_receiver.sh # receivers
devices/utils/flash_receiver.py # routine app-only update
devices/utils/build_dongle.sh # dongle (auto-installs arduino-cli + core)
devices/utils/flash_dongle.py # routine app-only updateFor the dongle UI flash flow, see Flashing a Dongle.
If you've made changes you want to publish as the next :latest, use the platform-specific build-and-push script:
host/run/osx/build_and_push_docker.sh # multi-arch build + push :latest and :v<host_version>
host/run/osx/build_and_push_docker.sh --tag rc1 # add an extra :rc1 tag
host/run/osx/build_and_push_docker.sh --no-push # build locally only (single arch)
host/run/windows/build_and_push_docker.bat # equivalent on WindowsThe script reads host_version from host/config/systemcfg.json and auto-tags :v<version>. You must docker login to the Docker Hub account that owns os4ivmb/backyardhero first.
If you're SSH'd into a Pi and want to push local edits from your laptop instead of editing on the Pi directly, the recommended flow is:
# On your laptop, rsync your git-tracked-and-modified files:
cd /path/to/backyardhero_pyro
git ls-files -mo --exclude-standard \
| rsync -avz --files-from=- ./ pi-host:/opt/backyardhero/
# On the Pi (one-time after install): make sure /opt/backyardhero is owned
# by your SSH user, otherwise rsync hits permission errors.
sudo chown -R "$USER:$USER" /opt/backyardheroThen on the Pi, restart whatever you changed:
# Frontend (HMR picks JSX up automatically; restart just for safety):
sudo systemctl restart byh-host # prod
# OR (dev mode, foreground; Ctrl-C and rerun):
cd /opt/backyardhero/host/run/pi && ./start-dev.sh
# Python daemon:
docker exec firework-system supervisorctl restart firework-daemon
# Bridge (if you changed tcp_serial_bridge or flash_server):
sudo systemctl restart byh-hostSee Updating the Pi for the upstream-pull equivalent.
Just stop the running launcher and start the other one. The two compose files use the same container name (firework-system), so docker will refuse to bring up one stack while the other is running. docker compose down (or Ctrl-C the running launcher) first.
The on-disk state — host/data/backyardhero.db, host/config/systemcfg.json, host/data/state — is shared between modes. Receiver definitions, shows, and inventory carry over.
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