gled 2.31.0

gled is an application for creating animations and effects on artnet or dmx installations
# Raspberry Pi 5 server

gled can run without a window on a Raspberry Pi 5 as `gled-server`. It drives
the Art-Net and DMX output and serves the gled interface to browsers on the
same network. Several laptops, tablets or phones can be connected at once.

## What you need

- A Raspberry Pi 5 and an SD card of at least 4 GB.
- A network shared with the computers that should control it. On its first
  start gled clones the asset repository, which needs internet access once.
  After that the Pi works offline.
- A browser with WebGPU: current Chrome or Edge, Safari 26, or Firefox. The
  page tells you when the browser lacks it.

## Flashing

Download `gled-pi5-<version>.img.xz` and its `.sha256` file from the release,
check it and write it to the card:

```sh
sha256sum -c gled-pi5-2.30.0.img.xz.sha256
xz -dc gled-pi5-2.30.0.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
```

Raspberry Pi Imager works as well: choose "Use custom" and select the
`.img.xz` file. Its customisation settings may stay on.

## Before the first boot

The card has a small FAT partition called `bootfs`. Three files on it are
yours to edit:

- **`network-config`** sets the network. Wired with DHCP needs no change. The
  file has commented examples for Wi-Fi and for a fixed address on an isolated
  Art-Net network such as `2.0.0.10/8`.
- **`user-data`** sets the host name, `gled` by default, and an SSH login. No
  one can log in until you add a key there.
- **`gled-ssh-key`** is optional. A private key placed in a file of this name is
  moved to the data partition on the first boot and used for the asset
  repository. Use a deploy key without a passphrase.

## The first boot

The first boot takes a few minutes and must not lose power. It installs the
Vulkan driver and gled from the card, checks that the GPU works for the gled
user, makes the system read-only and reboots. Afterwards `bootfs` holds
`gled-setup.log` and either `gled-setup.OK` or `gled-setup.FAILED`, so a failed
setup can be read on any computer.

From then on the Pi may be unplugged at any time. Everything that has to
survive, the asset repository, the configuration and the TLS certificate, is on
a separate journaled partition. The rest of the system is read-only.

## Connecting

Open `https://gled.local` in a browser. `http://gled.local` redirects there.

The server uses a self-signed certificate, so the browser warns on the first
visit. The server logs the certificate's SHA-256 fingerprint at start-up.
Compare it with the one the browser shows, then accept the certificate. HTTPS
is required because browsers only offer WebGPU on secure pages.

The browser page is a first version of the interface. It shows the LED
preview and controls the show: blackout, tap tempo, main dimmer, and each
scene's activation and opacity. Keys
held in the browser count for the project's key inputs, as on the desktop. The
full interface with previews and the editors follows. The engine runs on the Pi
either way: it loads the last project, renders on the GPU and sends Art-Net and
DMX.

## Checking from another computer

The repository has a small command-line client that connects like a browser
would, prints what the engine reports for five seconds and can toggle the
blackout:

```sh
cargo run -p gled-server --example client -- \
    wss://gled.local/ws <fingerprint> [--blackout]
```

`<fingerprint>` is the certificate fingerprint from the server's log. The
client refuses any other certificate.

## Checking a running Pi

With an SSH login configured:

```sh
systemctl status gled-server
journalctl -u gled-server -b
runuser -u gled -- vulkaninfo --summary   # must list the V3D GPU
mount | grep -E ' / |/boot/firmware|/data'  # overlay, read-only, read-write
```

To change the system itself, use `sudo overlayroot-chroot`. Changes made
anywhere else are lost on the next boot.

## Building the image yourself

Building needs podman with qemu-user-static for arm64, mtools, e2fsprogs,
util-linux, jq and xz. On Fedora:

```sh
sudo dnf install podman qemu-user-static-aarch64 mtools e2fsprogs util-linux jq xz file binutils
RUST_VERSION=$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml)
podman build --platform linux/arm64 -f .cd/Containerfile.aarch64 \
    --build-arg RUST_VERSION="$RUST_VERSION" \
    -t "localhost/gled-aarch64-builder:rust$RUST_VERSION-trixie" .cd
.cd/build_web.sh
AARCH64_IMAGE="localhost/gled-aarch64-builder:rust$RUST_VERSION-trixie" \
    GLED_UI_DIST=crates/gled-web/dist .cd/build_aarch64.sh
image/build-image.sh --binary dist/gled-server --version dev --out dist
```

The binary is compiled natively for arm64 inside a Debian trixie container,
which matches Raspberry Pi OS exactly. Under emulation the release build takes
a long time. The image build downloads the Raspberry Pi OS Lite image once,
about 500 MB, and resolves the extra packages against that image.