# Setting up a display kiosk A display is a screen — a television with a small computer, or a mini PC on a wall — that opens one module's display page full screen and keeps it open unattended. This guide sets one up so it starts on boot, stays paired, recovers from network and server outages on its own, and never opens a second copy of itself. Pairing and display identity belong to the platform (ADR 0036). Today an administrator approves a screen in the Dashboard sidebar's **Display devices** panel; a later release moves this to **Settings → Displays**. Nothing below changes when that happens. ## What the screen needs - Chromium or Google Chrome, current stable. The display page is tested against Chromium. - A **dedicated, persistent browser profile directory**. The device credential is an HttpOnly cookie in that profile; it is what keeps the screen paired across reboots. Never use a guest, incognito, or "clear data on exit" profile, and never share the profile with a person's browsing. - Network access to the installation's **API hostname** (the display page, its realtime stream, and its module requests) and to the storage hostname that serves images. - A clock that is roughly right. Playback follows the server's clock, but TLS does not tolerate a wildly wrong one. ## The address Every display-capable module has one display page on the API hostname: ```text https:///display/ ``` For Signage that is `https:///display/signage`. The Signage **Displays** tab shows the exact address under **Copy setup address**. Open it on the screen itself; opening it on an administrator's own computer only previews the display (and that browser appears in the roster as a *Signed-in browser*, which can be removed once it is offline). ## Launching the browser Run exactly **one** launcher, and launch the page as an app window with a fixed profile: ```bash chromium \ --user-data-dir=/var/lib/display-kiosk/profile \ --app=https:///display/signage \ --kiosk \ --no-first-run \ --noerrdialogs \ --disable-session-crashed-bubble \ --hide-crash-restore-bubble \ --disable-features=Translate \ --autoplay-policy=no-user-gesture-required \ --check-for-update-interval=31536000 ``` - `--app` opens the page with no tab strip and no address bar. `--kiosk` makes it full screen. - `--user-data-dir` is the persistent profile that holds the pairing. Keep it on persistent storage and back it up with nothing: if it is lost, the screen simply shows a new pairing code. - Do **not** add `--restore-last-session`, and do not also start the browser from a desktop autostart entry. Chromium allows one process per profile; a second launch hands its URL to the running process, which opens a **second window or tab** of the display. That is the usual cause of "duplicate" displays. One launcher, one profile, one window. ### Start on boot and restart on exit (systemd) Run the browser as an unprivileged user in that user's graphical session, from a single user unit: ```ini # ~/.config/systemd/user/display-kiosk.service [Unit] Description=Display kiosk After=graphical-session.target network-online.target Wants=network-online.target PartOf=graphical-session.target [Service] ExecStart=/usr/bin/chromium --user-data-dir=%h/.local/share/display-kiosk --app=https:///display/signage --kiosk --no-first-run --noerrdialogs --disable-session-crashed-bubble --hide-crash-restore-bubble --disable-features=Translate --autoplay-policy=no-user-gesture-required --check-for-update-interval=31536000 Restart=always RestartSec=5 [Install] WantedBy=graphical-session.target ``` ```bash systemctl --user daemon-reload systemctl --user enable --now display-kiosk.service loginctl enable-linger # with the desktop set to log this user in automatically ``` `systemctl --user stop display-kiosk` closes the browser cleanly, which is what keeps its profile — and the pairing cookie — intact. Avoid cutting power to a running kiosk when you can: a clean shutdown is always safer for a browser profile. ## Pairing 1. Start the kiosk. With no credential it shows a **six-digit pairing code**. 2. In the Dashboard, enter the code under **Display devices**, give the screen a name, and approve. 3. Within a few seconds the screen collects its credential and starts showing content. 4. In Signage → **Displays**, name the display and choose its group and audience. A paired screen stays paired across browser restarts and reboots, and for as long as it is in use: its credential is renewed each time it checks in, and only expires after **180 days without being used** (ADR 0056). A screen that is switched off and stored for longer than that, or that is revoked, returns to its pairing code and is paired again the same way. ## What happens when things go wrong | Event | What the screen does | | --- | --- | | Network drops for seconds | Nothing visible. The display keeps running; the realtime stream reconnects. | | Network or API down for longer | Keeps playing what it has cached, with a small corner note; recovers by itself when the server is back. No remount, no reload. | | API restarted or upgraded | Reconnects by itself. A new module version is picked up within five minutes and swapped in. | | Browser crashes or is restarted | systemd restarts it; the same profile is still paired. | | Machine reboots | Starts on boot and resumes. If the server is not up yet, the screen retries on its own (every few seconds, backing off to once a minute) until it is. | | Display revoked in the Dashboard | Stops showing content within seconds and returns to its pairing code. | | Display moved to another group or audience | Switches content within about one heartbeat (≈12 s), no reload. | **Offline cold start is not supported yet.** A screen that is already showing content survives an outage. A screen that *boots* while the server is completely unreachable can load its cached page but cannot mount the module until the server answers, because the authorization it needs is never cached (ADR 0043, Signage ADR 0006). It shows a short message and retries on its own until the server is reachable — nobody needs to touch it. ## Checklist for a new kiosk - [ ] One systemd unit, no desktop autostart entry, no second launcher. - [ ] `--user-data-dir` on persistent storage, not shared, not cleared on exit. - [ ] Automatic login of the kiosk user, and screen blanking/power saving disabled. - [ ] Paired and named; assigned in Signage. - [ ] Unplug the network for a minute: content keeps playing, then the note clears on reconnect. - [ ] Reboot: the screen comes back paired without anyone touching it.