Skip to content
dartpilot
Esc
↑↓navigate↵open⌘Jpreview
On this page

Headless boards

Install, configure, update, and supervise a dartpilot board with no screen, on a Raspberry Pi, a small server, or a Mac.

A headless board runs the same camera and detection engine as the desktop app but has no window. It serves the Board Console over HTTP so you configure and calibrate it from any browser on the same network: a phone, a TV, or a laptop. This is the recommended setup for venues and for machines with no display attached: a Raspberry Pi, a small Linux server, or a Mac.

Install

curl -fsSL https://get.dartpilot.app/headless.sh | sh

This downloads the latest build for your platform to ~/.local/share/dartpilot and symlinks ~/.local/bin/dartpilot. It also installs a service that starts on boot and restarts on failure:

Platform Service
Linux systemd user unit dartpilot. Camera access is granted to the service automatically (SupplementaryGroups=video).
macOS LaunchAgent com.dartpilot.board in ~/Library/LaunchAgents. No sudo, and no camera-group setup.

If you are unsure whether the machine is a desktop or a board, run the installer with no flags; it detects a graphical session and asks if it cannot.

First start and pairing

On first start the board prints a sign-in code to its logs:

# Linux
journalctl --user -u dartpilot -f

# macOS
tail -f ~/Library/Logs/dartpilot/dartpilot.out.log

Enter the code at play.dartpilot.app/device to approve it. The board then stays connected. On macOS, allow camera access when macOS asks. Until you do, it cannot see the board.

The same log prints the Board Console URL:

Board Console: http://192.168.1.42:3000/#key=…

Open that URL (including the #key=… fragment) in a browser on the same network. The fragment key is exchanged for a cookie, so MJPEG and event streams authenticate too. The key lives at ~/.local/share/com.dartpilot.desktop/console_key on Linux and ~/Library/Application Support/com.dartpilot.desktop/console_key on macOS; delete it to rotate.

Board Console

From the console you can:

  • select cameras and resolution, and set the frame rate;
  • run calibration and watch the live camera feeds;
  • pair/re-pair the board and reset its identity;
  • start/stop detection and preview;
  • export a board image for the web scoreboard.

Configuration

Everything is set with CLI flags or environment variables. There is no config file to edit.

Flag Env var Default Purpose
--bind <ADDR> DARTPILOT_BIND_ADDR 0.0.0.0:3000 Address the local API/console listens on.
--log-level <LEVEL> DARTPILOT_LOG info trace/debug/info/warn/error.
--log-format <FMT> DARTPILOT_LOG_FORMAT text text or json (structured logs).
--check-update – – Print whether a newer release is available, then exit.
--update – – Download, verify, and install the latest release, then exit.
-V, --version – – Print the version and exit.
-h, --help – – Print usage and exit.

Updating

Update in place:

dartpilot --update

The board does not leave a stopped or broken build behind. --update stops the service, swaps in the new build, checks that it actually runs, and starts the service again, restoring the previous version if the check fails. It reads https://get.dartpilot.app/headless.json and verifies the archive SHA-256 first. If the restart fails it prints the command to run yourself:

systemctl --user restart dartpilot                       # Linux
launchctl kickstart -k gui/$(id -u)/com.dartpilot.board # macOS

A venue can roll a fleet by issuing the update command from the dashboard; the board updates and restarts itself.

Operations

# Linux
systemctl --user status dartpilot                        # service state
systemctl --user restart dartpilot                       # restart the board
journalctl --user -u dartpilot -f                        # follow logs
journalctl --user -u dartpilot | jq                      # parse JSON logs (--log-format json)

# macOS
launchctl print gui/$(id -u)/com.dartpilot.board         # service state
launchctl kickstart -k gui/$(id -u)/com.dartpilot.board  # restart the board
tail -f ~/Library/Logs/dartpilot/dartpilot.out.log       # follow logs

Readiness is exposed at GET http://<board>:3000/api/health (no key required) for the service manager and LAN dashboards. It reports ready, phase (starting/calibrating/ready/error), board_state, per-camera calibration, detection status, and the version. See the health contract for every field.

Recipes

Raspberry Pi with no display (venue rack)

  1. Flash Raspberry Pi OS, boot it, and join the venue network.
  2. Run the headless installer and approve the sign-in code.
  3. Open the printed Board Console URL on your phone with the board’s cameras mounted, select them, and calibrate.
  4. Point a TV or tablet at the scoreboard; the board itself needs no screen.

Small server / NUC

The same installer works on x86_64 Linux. Bind to a specific interface and use JSON logs if you ship them to a log collector:

DARTPILOT_BIND_ADDR=0.0.0.0:3000 DARTPILOT_LOG_FORMAT=json dartpilot

Mac

The installer works on Apple Silicon and Intel Macs. A LaunchAgent starts when the user logs in rather than at boot, so keep the board’s user logged in (enable automatic login if the Mac reboots unattended). Everything else is the same as Linux.

Troubleshooting

  • No cameras in the Console. Confirm they are UVC USB cameras. On Linux, check the service has the video group (systemctl --user show dartpilot -p SupplementaryGroups). On macOS, open System Settings → Privacy & Security → Camera and allow dartpilot. Then read the logs (see Operations).
  • Console asks for an access key. Open the full URL printed at boot, including the #key=… fragment. If you lost it, read the console_key file listed above.
  • ready: false in /api/health. Read phase and cameras.items[].calibration. The board stays up and explains the failure rather than exiting.

Was this page helpful?