diff --git a/README.md b/README.md new file mode 100644 index 0000000..240ad35 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# 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](https://github.com/balena-io-experimental/browser)) 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**: + ```bash + 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`: + +```yaml + 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).