AWTRIX on Linux¶
AWTRIX on Linux is the same AWTRIX NG core that runs on the ESP32, built as an ordinary Linux
program called awtrix-linux. It uses the same engine, renderer, HTTP API, MQTT client, Berry
script engine and web UI. The program has two jobs:
- Headless development target. On a PC, or in WSL (Windows Subsystem for Linux), it runs without a clock attached. You see its pixels in the web UI. Use it to develop and test the API, scripts, rendering, MQTT and persistence.
- The runtime of the Ulanzi TC002. On the TC002,
awtrix-linux --board tc002drives the 52 × 16 panel, the keys, the knob and the speaker. A supervisor starts it and handles the hardware around it. That side is described in AWTRIX NG on the TC002.
The code lives in
src/platform/linux/;
the entry point is
main_linux.cpp,
the CMake target is defined in
cmake/Linux.cmake.
Pages in this section¶
Read them in this order:
- This page – build, run and test
awtrix-linuxon a development machine. - HTTPS administration – the
--hardenedmode: authenticated HTTPS and MQTT over verified TLS for a Linux host that is reachable from the network. - Running as a systemd service – the shipped systemd unit that runs the hardened mode as an isolated system service.
- Update packages – the
.awupupdate container, the verifier and the update state policy that the TC002 web update is built on. - ARM system build – the runner that builds a pinned ARM cross toolchain and userspace, and the evidence and reproduction tools around it.
- Buildroot configuration – what the Buildroot external tree contains, its pinned versions and its license evidence.
Build¶
Use Linux, or a Linux distribution inside WSL on Windows. The build needs a C++17 compiler, CMake 3.20 or newer, Python, PlatformIO and the OpenSSL development libraries. On Debian or Ubuntu, from the repository root:
sudo apt-get update
sudo apt-get install -y build-essential cmake libssl-dev liblzma-dev libjpeg-turbo8-dev python3-venv openssl mosquitto
python3 -m venv .pio/venv-linux
. .pio/venv-linux/bin/activate
python -m pip install platformio
pio pkg install -e native
cmake -S . -B .pio/linux -DCMAKE_BUILD_TYPE=Release
cmake --build .pio/linux --parallel 2
PlatformIO fetches the shared libraries. CMake builds awtrix-linux against the same core the
ESP32 firmware uses. The host CMake preset does the same into build/host:
cmake --preset host && cmake --build --preset host. The rest of this section uses .pio/linux,
as CI does.
Run locally¶
Choose a dedicated directory for application data, then start the program from the repository root:
.pio/linux/awtrix-linux \
--data "$HOME/.local/share/awtrix-ng-dev" \
--port 8080 \
--width 52 --height 16 \
--webui "$PWD/webui/index.html"
Open http://127.0.0.1:8080. By default the HTTP server listens on IPv4 loopback only and has
no login. Other local processes can call the API, so run it as an ordinary user and keep it
local. Browser requests must come from the service's own origin; foreign origins and unknown
Host headers are rejected. This is not authentication.
There are two other network modes:
--lanserves the device on the network like the ESP32 does, with the login configured in the web UI. It listens on all IPv4 addresses unless--listennames one, and allows ports 1 to- It accepts no other security option. The TC002 uses this mode.
--hardenedserves authenticated HTTPS. See HTTPS administration.
Command-line options¶
| Flag | Default | Meaning |
|---|---|---|
--data DIRECTORY |
required | Persistent application data, locked exclusively while running |
--port NUMBER |
8080 |
HTTP port, 1024 to 65535 (with --lan: 1 to 65535) |
--width NUMBER |
52 |
Display width, 8 to 128 pixels |
--height NUMBER |
16 |
Display height, 8 to 32 pixels |
--board NAME |
headless |
headless serves pixels to the web UI only; tc002 drives the TC002 panel and requires exactly 52 × 16 |
--webui FILE |
webui/index.html |
The web UI file; an absolute path avoids depending on the working directory. A name ending in .gz is served gzip-encoded |
--lan |
off | Network service with the web UI login, as on the ESP32 |
--listen IPv4_ADDRESS |
0.0.0.0 with --lan, 127.0.0.1 with --hardened |
Listen address; only allowed with --lan or --hardened |
--ca-file FILE |
– | PEM root certificates that every HTTPS client of the program verifies against, read once at start |
--boot-intro |
off | Show the power-on intro before the first app |
--performance-report FILE |
– | Write frame-timing statistics as private JSON to a new file at exit |
--help |
– | Print usage and exit |
The hardened-mode flags are listed in HTTPS administration. The TC002-only flags (input, supervisor and speaker descriptors, start reason, device ID, web update) are passed by the TC002 supervisor and documented in AWTRIX NG on the TC002.
The display size is fixed for the life of the process. In headless mode the device reports the
platform linux, that size, and no GPIO or panel wiring settings, so the web UI hides them. A
Berry or JSON drawing command at (51, 15) sets the bottom-right pixel of a 52 × 16 display.
State and shutdown¶
The data directory holds settings, device configuration, a persistent device ID, app order, radio stations, scripts and uploaded assets. Each instance needs its own directory and HTTP port. Pushed apps live in memory only and disappear when the process stops.
Stop the program with Ctrl+C or SIGTERM. It stops accepting work, joins its HTTP workers and writes pending script state and changed settings before it exits. A forced kill cannot do this final write.
Files are replaced atomically, with a shared data quota of 8 MiB. When a configuration write
fails, the latest value is kept for a retry. A system-configuration write can answer
507 insufficientStorage while the new configuration is already active in memory; the response
says that saving is pending. Unsaved writes at shutdown give exit code 1.
Linux owns the network, DNS and the clock. The program uses the host clock with its configured display timezone. On a PC it does not configure Wi-Fi or run an NTP client; set those up in the host OS. MQTT connects to the configured broker; restart after changing the broker settings.
Headless behaviour¶
| Area | Headless behaviour |
|---|---|
| Engine, scripts, notifications and rendering | Shared implementation |
| HTTP API, MQTT, assets and script stores | Shared host services with real files on disk |
| Script HTTP/HTTPS requests | Worker thread; HTTPS verifies the server certificate |
| LEDs | Shown in the web UI only |
| Buttons and sensors | None; no simulated sensor readings |
| Audio and internet radio | No audio output; the device reports no audio sinks |
| Wi-Fi setup, Art-Net and firmware updates | Not available |
| Reboot and sleep commands | Stop the process; Linux itself is not rebooted or suspended |
| Factory reset | Empties the data directory except its lock file, then exits |
Test¶
After building, run the integration contracts:
ctest --test-dir .pio/linux --output-on-failure
python -m unittest discover -s tools/tc002 -p "test_*.py" -v
The contracts start temporary instances of the program and local test services. Mosquitto is the MQTT broker; OpenSSL makes the local HTTPS test certificate. No clock, external broker or real data directory is needed. The TC002 tool tests use fixtures and local processes and never connect to a device.
The contract suite skips the MQTT and HTTPS fixtures when their tools are missing. Configure with
-DAWTRIX_REQUIRE_INTEGRATION_SERVICES=ON to make them mandatory; CI does this. The hardened
security suite always needs a non-root Linux account, openssl, mosquitto and
mosquitto_passwd.
CI builds awtrix-linux and runs these checks next to the core, web UI and ESP32 checks.