Getting Started¶
This guide walks you through generating an SSH key, configuring wallpanel-control, and sending your first MQTT commands.
Prerequisites¶
| Requirement | Details |
|---|---|
| Wall panel | Linux device with a GNOME desktop session (Intel NUC, SBC, mini-PC, ...) |
| GNOME session | Required for screen on/off (D-Bus/Mutter); brightness uses sysfs and works without GNOME |
| SSH access | Public-key login enabled on the wall panel |
| WoL-capable NIC | Required only for the wake system action |
| MQTT broker | Mosquitto, EMQX, or any MQTT 3.1.1+ broker |
| Python | 3.14+ (Docker image includes this) |
SSH Key Setup¶
wallpanel-control uses public-key SSH authentication. Generate a dedicated key (no passphrase so the container can connect unattended):
Copy the public key to the wall panel:
Verify the connection works before running the container:
Capture the wall panel's host key in your local known_hosts (this step also seeds the
file that will be mounted into the container):
Container host-key verification
The container user (appuser) has no SSH history. The Compose file mounts your
host ~/.ssh/known_hosts read-only into the container, so the ssh-keyscan step
above is required before starting the container. Without a known_hosts entry the
container will refuse the connection.
Run as a dedicated user
Create a locked-down system user on the wall panel that only has permission to write
to the sysfs backlight path and run systemctl suspend / systemctl hibernate.
This limits the blast radius of a compromised key.
Installation¶
Docker is the simplest deployment from a checkout of this monorepo. The checked-in
Compose file includes a local build: block for development and an image: name for
the release image:
services:
wallpanel-control:
build:
context: ../..
dockerfile: apps/wallpanel-control/Dockerfile
image: ghcr.io/ff-fab/wallpanel-control:latest
restart: unless-stopped
env_file: .env
environment:
WALLPANEL_CONTROL_MQTT__HOST: mosquitto
WALLPANEL_CONTROL_SSH_KEY_PATH: /run/secrets/wallpanel_ssh_key
WALLPANEL_CONTROL_SSH_KNOWN_HOSTS: /run/secrets/wallpanel_known_hosts
volumes:
- wallpanel_control-data:/app/data
secrets:
- wallpanel_ssh_key
- wallpanel_known_hosts
depends_on:
- mosquitto
mosquitto:
image: eclipse-mosquitto:2
restart: unless-stopped
ports:
- '127.0.0.1:1883:1883'
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- mosquitto-data:/mosquitto/data
- mosquitto-log:/mosquitto/log
volumes:
wallpanel_control-data:
mosquitto-data:
mosquitto-log:
secrets:
wallpanel_ssh_key:
file: ${HOST_WALLPANEL_SSH_KEY_PATH:-${HOME}/.ssh/wallpanel}
wallpanel_known_hosts:
file: ${HOST_WALLPANEL_KNOWN_HOSTS_PATH:-${HOME}/.ssh/known_hosts}
From the app directory, create your env file:
cd apps/wallpanel-control
cp .env.example .env
# Edit .env: set WALLPANEL_CONTROL_WOL_MAC to your panel's MAC address
Start the stack:
Pin to a specific version
Replace latest with a release tag (e.g. 0.2.0) in the image: line to pin
the deployment and avoid surprises on restart.
SSH key and known-hosts location
Export HOST_WALLPANEL_SSH_KEY_PATH and/or HOST_WALLPANEL_KNOWN_HOSTS_PATH
in your shell to override the host-side paths for these Docker secrets. Do not
set them in .env (they would be injected into the container as env vars).
The container always reads from /run/secrets/wallpanel_ssh_key and
/run/secrets/wallpanel_known_hosts.
First MQTT Commands¶
With the stack running, open a second terminal and subscribe to all wallpanel topics:
Turn the display on¶
Example state response on wallpanel-control/display/state:
Set brightness to 40%¶
Turn display off¶
Send a system action¶
Expected acknowledgement on wallpanel-control/system/action/state:
WoL requires same-subnet broadcast
The wake action sends a magic packet to WALLPANEL_CONTROL_WOL_BROADCAST
(default 255.255.255.255). If the wall panel is on a different subnet, set
this to the directed broadcast address for that subnet.