2026-07-06 16:06:06 +02:00
2026-07-06 20:21:39 +02:00
2026-07-04 14:16:05 +02:00
2026-07-06 16:32:50 +02:00

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.

  1. display-manager Container: Runs a central Xorg server with direct access to the GPU (/dev/dri). It exposes the X11 Unix socket to the other containers.
  2. kiosk Containers: Individual, scalable containers running Node.js and Chromium.
    • Resolution Independence: On startup, each kiosk uses xrandr to 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.

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

  1. Clone the repository and navigate to the root directory.
  2. Build and start the stack:
    docker-compose up -d --build
    
  3. 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: Returns HTTP 200 OK if 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 .png screenshot 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|1 and kiosk=0|1 alongside the URL.
  • POST /refresh: Reloads the current page.
  • POST /autorefresh/{interval}: Automatically refreshes the browser window every X seconds (send 0 to disable).

Configuration

  • GET /kiosk: Returns 1 if kiosk mode is enabled, 0 if disabled.
  • PUT /kiosk/{value}: Enables (1) or disables (0) kiosk mode (restarts the browser).
  • GET /gpu: Returns 1 if GPU acceleration is enabled, 0 if disabled.
  • PUT /gpu/{value}: Enables (1) or disables (0) hardware acceleration (restarts the browser).
S
Description
No description provided
Readme 70 KiB
Languages
JavaScript 82.5%
Dockerfile 9.3%
Shell 8.2%