41bc1a7ef51b4f5e499079f671b9b984a444cd45
Scalable Multi-Monitor Kiosk
A Docker Compose-based project designed to run multiple hardware-accelerated Chromium kiosk instances across multiple monitors (e.g., the dual HDMI ports of a Raspberry Pi 4).
Each Chromium instance provides an HTTP API (inspired by the balena browser block) that allows you to dynamically control the browser's URL, refresh behavior, kiosk mode, and GPU settings on the fly.
Architecture
This project uses a robust X11 Architecture designed specifically to avoid the complexities of Virtual Terminals and Session Management inside headless Docker containers.
display-managerContainer: Runs a central Xorg server with direct access to the GPU (/dev/dri). It exposes the X11 Unix socket to the other containers.kioskContainers: Individual, scalable containers running Node.js and Chromium.- Resolution Independence: On startup, each kiosk uses
xrandrto dynamically detect the exact resolution and physical offset of its assigned monitor (e.g.,HDMI-1). It then perfectly frames its Chromium window to that specific screen.
- Resolution Independence: On startup, each kiosk uses
Prerequisites
- Docker and Docker Compose installed.
- A host machine with KMS/DRM graphics capabilities (like a Raspberry Pi 4 running Debian/Raspberry Pi OS).
- Multiple displays connected.
Getting Started
- Clone the repository and navigate to the root directory.
- Build and start the stack:
docker-compose up -d --build - The display manager will initialize the X server, and the two kiosk instances will launch on their respective monitors.
Scaling
To add a third monitor (e.g., HDMI-3), simply add a new service to docker-compose.yml:
kiosk-3:
build: ./kiosk
restart: always
depends_on:
- display-manager
ports:
- "5013:5011"
volumes:
- x11-socket:/tmp/.X11-unix
devices:
- "/dev/dri:/dev/dri"
environment:
- DISPLAY=:0
- MONITOR=HDMI-3
- PORT=5011
- LAUNCH_URL=https://example.com
API Reference
Each kiosk exposes an API on its mapped port (e.g., 5011 for HDMI-1, 5012 for HDMI-2).
Status & Information
GET /ping: ReturnsHTTP 200 OKif the browser is ready.GET /url: Returns the URL currently being displayed.GET /flags: Returns the internal flags Chromium was started with.GET /version: Returns the version of Chromium running.GET /screenshot: Returns a.pngscreenshot of the X11 display.
Navigation
POST /url: Sets the URL to be displayed (send as JSON or URL-encoded form data).- Example:
curl -X POST -d "url=https://wikipedia.org" http://localhost:5011/url - Note: You can also pass
gpu=0|1andkiosk=0|1alongside the URL.
- Example:
POST /refresh: Reloads the current page.POST /autorefresh/{interval}: Automatically refreshes the browser window every X seconds (send0to disable).
Configuration
GET /kiosk: Returns1if kiosk mode is enabled,0if disabled.PUT /kiosk/{value}: Enables (1) or disables (0) kiosk mode (restarts the browser).GET /gpu: Returns1if GPU acceleration is enabled,0if disabled.PUT /gpu/{value}: Enables (1) or disables (0) hardware acceleration (restarts the browser).
Description
Languages
JavaScript
82.5%
Dockerfile
9.3%
Shell
8.2%