Skip to content

Getting Started Linux

OneSeventyFour edited this page Jun 19, 2026 · 4 revisions

Getting Started — Linux

Tested on Ubuntu 22.04 / 24.04, Debian 12, and Raspberry Pi OS Bookworm. Other distros work but you'll need to translate the package names.

Running on a Raspberry Pi? Use host/run/pi/install.sh instead of this manual guide. The script installs Docker, the Backyard Hero stack, the WiFi AP, NAT, mDNS, the dongle udev rule, and the systemd auto-start unit — all in one command.

Use this page when you want a manual install on a generic Linux box (x86_64 server, NAS, dev laptop, etc.) where the install script isn't the right shape — e.g. you don't want it touching your network config.

If you already have Docker + Python 3 installed, jump to Step 3.


Step 1 — Install prerequisites

Docker Engine + Compose plugin

sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo $ID)/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# (For Ubuntu/Debian. For Raspberry Pi OS, use https://docs.docker.com/engine/install/debian/.)
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/$(. /etc/os-release; echo $ID) \
$(. /etc/os-release; echo $VERSION_CODENAME) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Add yourself to the docker group so you don't need sudo every time:
sudo usermod -aG docker $USER
newgrp docker

docker run --rm hello-world

Python 3, git, and serial group access

sudo apt install -y python3 python3-venv python3-pip git
sudo usermod -aG dialout $USER     # required to talk to /dev/ttyACM* without sudo
newgrp dialout

Log out and back in once if groups doesn't show dialout and docker.

(Only if you'll flash your own firmware) arduino-cli

curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
sudo mv bin/arduino-cli /usr/local/bin/
arduino-cli core update-index
arduino-cli config init
arduino-cli config set board_manager.additional_urls https://espressif.github.io/arduino-esp32/package_esp32_index.json
arduino-cli core update-index
arduino-cli core install esp32:esp32

Step 2 — Decide between production and development

See Production vs Development mode. Production = pull the prebuilt image. Development = build from source.


Step 3 — Get the source (or the launcher)

git clone https://github.com/os4-ivmb/backyardhero_pyro.git ~/byh
cd ~/byh/host

(Production mode could in principle skip the byh_app/, pythings/, and devices/ folders, but on Linux you usually want everything.)


Step 4 — Plug in the dongle and find its serial port

ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# Typical output: /dev/ttyACM0
dmesg | tail -20    # confirms the USB enumeration line

On Raspberry Pi 4/5 the dongle usually shows up as /dev/ttyACM0. On x86 Linux, same.

Edit host/config/systemcfg.json and set the dongle_port field:

{
  "host_version": 0.08,
  "system": {
    "dongle_port": "/dev/ttyACM0",
    "dongle_baud": 115200,
    "dongle_protocol": "BKYD_TS_HYBRID"
  }
}

Tip: if you have multiple USB-CDC devices and the order shifts on reboot, give the dongle a stable name with a udev rule. Example /etc/udev/rules.d/99-byh-dongle.rules:

SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="80??", \
  SYMLINK+="ttyBYHDongle"

(Replace the IDs with what lsusb shows for your dongle.) Then reload with sudo udevadm control --reload && sudo udevadm trigger, and set dongle_port to /dev/ttyBYHDongle.


Step 5 — Flash and provision your receivers

devices/utils/build_receiver.sh                       # one-time
devices/utils/flash_receiver.py --full --node 146     # provision RX146

See Flashing a Receiver for details on --full, --set-id, OTA, etc.


Step 6 — Start everything

Pick the launcher for your install path. On a Pi using the install script, this is automatic via the byh-host systemd unit and you can skip this step entirely. On a generic Linux box:

Production

cd ~/byh
# Pi:     host/run/pi/start.sh
# Other:  the launchers live under host/run/<platform>/. Linux servers
#         that aren't a Pi can use the pi/ folder's start.sh (it doesn't
#         touch wlan0 if hostapd isn't installed) or build their own:
./host/run/pi/start.sh

Development

cd ~/byh
./host/run/pi/start-dev.sh

Both scripts:

  1. Start the host-native TCP-to-serial bridge (Python venv at host/tcp_serial_bridge/.venv).
  2. Pull (prod) or build (dev) the docker image.
  3. docker compose up the stack.

To stop cleanly: Ctrl-C.

Linux: passing the serial device through Docker (optional)

On Linux, the daemon container could in principle talk to the serial device directly via a --device mapping. The default Backyard Hero stack instead uses the host-native TCP-to-serial bridge so the same architecture works on macOS and Windows (where Docker Desktop runs in a VM and direct device passthrough isn't easy). You can keep the bridge — there's no functional downside — or modify docker-compose.yml to add devices: - /dev/ttyACM0 and bypass it. The protocol handler accepts both paths.


Step 7 — Open the UI and add your receivers

Browse to http://<your-host-ip>:1776 (or http://localhost:1776 if you're sitting at the machine).

Add your receivers from the Receivers tab. Same flow as macOS — see Getting Started — macOS, Step 7.


Step 8 — Run a test fire

End-to-end show example walks you through a full show.


Headless / Raspberry Pi notes

  • Use the install script. On a Pi, host/run/pi/install.sh handles auto-start (byh-host.service), the WiFi AP, NAT, mDNS, and the dongle udev rule. It's the right answer to almost every headless-Pi question.
  • Pi 4 / 5 are both fast enough. A Pi 3B+ will technically run it but feels sluggish in the UI; not recommended.
  • Browser on a different machine: Pi at 192.168.1.50? Open http://192.168.1.50:1776 from your laptop or tablet (or http://backyardhero/ if you're on the Pi's AP). The UI is responsive enough for phone use.

Common problems on Linux

  • /dev/ttyACM0: Permission denied — you're not in the dialout group. Re-check groups after logging out/in.
  • Docker container can't reach host.docker.internal — older Docker engines on Linux don't auto-add this hostname. Either upgrade to a current Docker (it's added by default since 20.10), or add extra_hosts: - "host.docker.internal:host-gateway" to the firework-system service in your compose file.
  • Bridge says "auto-reconnect attempt N failed" — try sudo dmesg | tail to see if the dongle keeps re-enumerating (bad cable / power issue), or whether it's just not appearing at all (try a different USB port).
  • OTA flashes hang on Pi — the SD card is too slow. Either upgrade to a USB-attached SSD or run OTA at the lower --rate 1 (1 Mbps) instead of 2 Mbps; see OTA flashing.

Clone this wiki locally