Files
daynivo-kiosk-os/README.md
T
rothmanandClaude Opus 5.5 eb0242c182
CI / test-bookworm (push) Successful in 29s
CI / test-latest (push) Successful in 31s
Rename every remaining voxip name to daynivo, with a one-time migration
Services (daynivo-kiosk-*, daynivo-network-guard, daynivo-boot-import),
programs in /usr/lib/daynivo-kiosk, folders /etc, /var/lib, /var/log and
/var/cache daynivo-kiosk*, the system user daynivo, DAYNIVO_* settings,
the plymouth theme, network profiles daynivo-eth0/wlan0, the image stage
and its first user daynivoadmin.

install.sh moves a kiosk installed up to 1.2.x over once: old services
stopped and removed, folders moved (configuration, password, browser
profile, logs) with symlinks under the old names, the voxip user renamed
with the same uid, network profiles renamed unless a change awaits
confirmation, and old leftovers removed. Tested by upgrading a configured
1.2.0 installation in a container, and running the install a second time.

Old names keep working where people type or place them: voxip-config.json,
voxip-authorized_keys, voxip-network-reset, voxip-kiosk-ctl, and
VOXIP_DEFAULT_URL / VOXIP_DEVICE_NAME for image builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:58:03 +01:00

303 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Daynivo Kiosk OS
Lichte, onderhoudbare kioskdistributie voor de Raspberry Pi 3 (Model B/B+)
op basis van Raspberry Pi OS Lite 32-bit (Bookworm of Trixie). Na het
opstarten toont Chromium fullscreen één HTTPS-pagina. Beheer gaat via de
webinterface **Daynivo Kiosk Manager** op `http://kiosk.local:8080`.
- Geen desktopomgeving: alleen een minimale X-server plus Chromium.
- Herstelt zichzelf: browsercrashes, een vastgelopen pagina, netwerkuitval
en stroomuitval.
- Geen standaardwachtwoorden: de eerste beheerder claimt het apparaat met
een setupcode die op het scherm staat.
- Netwerkwijzigingen met automatische rollback.
- Geen klantspecifieke code: alles per klant staat in
`/etc/daynivo-kiosk/config.json` en kan bij uitrol via de bootpartitie
worden meegegeven.
De architectuur en de veiligheidskeuzes staan in
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md). De testprocedure op echte
hardware staat in [`docs/HARDWARE-TEST.md`](docs/HARDWARE-TEST.md).
## Snel aan de slag
### Optie A — kant-en-klare image
1. Download de nieuwste `*-daynivo-kiosk-os-*.img.xz` bij de
[releases](https://git.rothman.nl/rothman/daynivo-kiosk-os/releases),
of bouw hem zelf (zie hieronder).
2. Schrijf hem met **Raspberry Pi Imager** (*Eigen image gebruiken*) of
**balenaEtcher** naar een microSD-kaart van 16 GB of groter.
3. Optioneel, in Raspberry Pi Imager → *OS-aanpassingen*: wifi, gebruiker
met wachtwoord en/of SSH-sleutel, tijdzone. Zonder aanpassingen heeft de
image **geen** bruikbaar wachtwoord en staat SSH uit.
4. Optioneel: zet een `daynivo-config.json` op de bootpartitie (zie
[Uitrol bij meerdere klanten](#uitrol-bij-meerdere-klanten)).
5. Start de Pi. Bij de eerste boot wordt de rootpartitie automatisch
vergroot tot de hele SD-kaart. Daarna verschijnt een setupscherm met de
setupcode en het adres van de beheerinterface.
6. Open `http://kiosk.local:8080` (of het getoonde IP-adres), voer de
setupcode in en kies een uniek beheerderswachtwoord.
### Optie B — installeren op een bestaande Raspberry Pi OS Lite
Vereist: Raspberry Pi OS Lite Bookworm of Trixie met NetworkManager (de
standaard sinds Bookworm).
```bash
curl -fsSL https://daynivo.nl/kiosk/install.sh | sudo bash -s -- \
--url "https://schermen-ijsselflat.voxip.nl" --name "IJsselflat" --hostname ijsselflat
```
`install-online.sh` (dat is wat daynivo.nl serveert, en het hangt ook bij
elke release) haalt de nieuwste release op, controleert de SHA-256, pakt hem
uit in `/opt/daynivo-kiosk-os/<versie>` en draait daar `install.sh`. Git is
niet nodig. Vanuit een clone kan het ook:
```bash
git clone https://git.rothman.nl/rothman/daynivo-kiosk-os.git
cd daynivo-kiosk-os
sudo ./install.sh --url "https://schermen-ijsselflat.voxip.nl" --name "IJsselflat" --hostname ijsselflat
```
Alle opties zijn optioneel. Het script installeert de benodigde pakketten,
maakt de gebruikers `kiosk` en `daynivo` aan, installeert de services en
start de kiosk. Aan het eind toont het de setupcode.
Draaide hier eerder de Daynivo-kiosk (`raspberry-pi/install-kiosk.sh` uit
de Daynivo-repository)? Dan neemt `install.sh` de display-URL (inclusief
`?token=`) automatisch over en schakelt `display-kiosk.service` uit.
### Updaten
In de webinterface onder **Systeem → Software-updates**: *Nu controleren*,
*Bijwerken naar …*, en het vinkje **Automatisch bijwerken**. Elke nacht
tussen 03:00 en 05:00 (`daynivo-kiosk-update.timer`) kijkt de kiosk of er een
nieuwe release is; met het vinkje aan installeert hij die meteen. Dat werkt
ook op een apparaat dat met de image of vanuit een clone is geïnstalleerd.
Vanaf de commandoregel:
```bash
sudo /usr/lib/daynivo-kiosk/daynivo-kiosk-updater --check # alleen kijken
sudo /usr/lib/daynivo-kiosk/daynivo-kiosk-updater --install # nieuwste release installeren
```
De updater installeert alleen een nieuwere versie met een kloppende
checksum, pakt hem uit in `/opt/daynivo-kiosk-os/<versie>` (de laatste twee
blijven bewaard) en draait daar `update.sh --no-pull`. Vanuit een clone kan
het ook met git:
```bash
cd daynivo-kiosk-os
sudo ./update.sh # git pull --ff-only + back-up van /etc/daynivo-kiosk + install.sh --upgrade
```
Een update overschrijft nooit bestaande configuratie of het
beheerderswachtwoord. Back-ups staan in `/var/backups/daynivo-kiosk-*.tar.gz`
(de laatste vijf). Op een apparaat met de image staat de broncode in
`/usr/src/daynivo-kiosk`. Clone de repository voor updates naar een eigen map,
of pak een release uit en draai daar `sudo ./update.sh --no-pull`.
### Van de VoxIP-namen naar Daynivo
Kiosks tot en met versie 1.2.x gebruiken nog de oude namen: services
`voxip-kiosk-*`, mappen `/etc/voxip-kiosk`, `/var/lib/voxip-kiosk*` en
`/usr/lib/voxip-kiosk`, en de gebruiker `voxip`. De eerste update naar een
nieuwere versie zet zo'n kiosk eenmalig over, gewoon via de webinterface of
's nachts automatisch:
- services, programma's en instellingen krijgen de `daynivo-`-namen; de oude
services worden uitgeschakeld en verwijderd;
- configuratie, beheerderswachtwoord, browserprofiel (offline-cache), logs en
updatestatus verhuizen naar de `daynivo-`-mappen; de oude mapnamen blijven
als verwijzing bestaan;
- de gebruiker `voxip` wordt `daynivo`, met hetzelfde uid, zodat alle
bestanden hun eigenaar houden;
- de netwerkprofielen `voxip-eth0`/`voxip-wlan0` worden `daynivo-eth0`/
`daynivo-wlan0` (niet zolang er een netwerkwijziging op bevestiging wacht;
dan bij de volgende update);
- wie in de Kiosk Manager was ingelogd, moet één keer opnieuw inloggen.
Op de bootpartitie blijven `voxip-config.json`, `voxip-authorized_keys` en
`voxip-network-reset` werken, net als de opdracht `voxip-kiosk-ctl`. Bij het
bouwen van een image worden `VOXIP_DEFAULT_URL` en `VOXIP_DEVICE_NAME` nog
gelezen als de `DAYNIVO_`-varianten ontbreken.
### Verwijderen
```bash
sudo ./uninstall.sh # programma's en services weg, configuratie blijft
sudo ./uninstall.sh --purge # ook configuratie, status, logs, netwerkprofielen en gebruikers
```
## Image bouwen
Het image wordt gebouwd met [pi-gen](https://github.com/RPi-Distro/pi-gen),
de officiële bouwtool van Raspberry Pi OS. De extra stage
`image/stage-daynivo` voert hetzelfde `install.sh` uit als een handmatige
installatie.
Vereist: een Linux-buildmachine (x86_64 of arm64) met Docker en git. Op
x86_64 is ook `binfmt`/qemu nodig voor ARM-emulatie:
```bash
sudo apt-get install -y qemu-user-static binfmt-support # alleen op x86_64
./image/build.sh # bouwt in Docker
# of zonder Docker, op Debian/Ubuntu met de pi-gen-afhankelijkheden:
sudo ./image/build.sh --native
```
Resultaat: `image/deploy/<datum>-daynivo-kiosk-os-<versie>.img.xz` plus een
`.sha256` en `BUILD-INFO-<versie>.txt`.
Instelbaar via omgevingsvariabelen:
| Variabele | Standaard | Betekenis |
|---|---|---|
| `PI_GEN_REF` | `2024-11-19-raspios-bookworm-armhf` | pi-gen-tag (32-bit) |
| `RELEASE` | `bookworm` | `bookworm` of `trixie` (moet bij `PI_GEN_REF` passen) |
| `DAYNIVO_DEFAULT_URL` | `https://schermen-ijsselflat.voxip.nl` | standaard kiosk-URL |
| `DAYNIVO_DEVICE_NAME` | `Daynivo Kiosk` | standaard apparaatnaam |
| `TARGET_HOSTNAME` | `kiosk` | hostname (`http://<hostname>.local:8080`) |
| `ALLOW_DIRTY` | `0` | `1` = bouw de werkmap in plaats van de laatste commit |
**Reproduceerbaarheid.** pi-gen staat vast op een tag en de broncode
gaat via `git archive` van één commit mee. Beide staan in `BUILD-INFO`
(ook in de image: `/usr/share/daynivo-kiosk/BUILD-INFO`). De Debian- en
Raspberry Pi-pakketten komen uit de archieven zoals die op het moment van
bouwen zijn. Er bestaat geen snapshot-archief voor Raspberry Pi OS, dus
twee builds op verschillende dagen kunnen nieuwere pakketversies bevatten.
Bewaar voor een uitrol daarom de gebouwde `.img.xz` zelf.
## Releases
Een release maak je door `VERSION` te verhogen, te committen en een tag met
hetzelfde nummer te pushen:
```bash
echo 1.2.0 > VERSION && git commit -am "Release 1.2.0"
git tag v1.2.0 && git push && git push origin v1.2.0
```
Gitea Actions (`.github/workflows/release.yml`) draait dan de tests en maakt
een release met `daynivo-kiosk-os-<versie>.tar.gz` (+ `.sha256`) en
`install-online.sh`. Daarna bouwt dezelfde workflow het SD-image en hangt het
`.img.xz` (+ `.sha256`) aan dezelfde release; dat duurt 30 tot 90 minuten of
langer. Zodra de tar-bestanden er staan, zien de kiosks de nieuwe versie.
Vereist op de Gitea-server:
- een **act_runner** met het label `ubuntu-latest`;
- voor het image: `container.privileged: true` in de runnerconfiguratie
(pi-gen heeft loop-devices en binfmt_misc nodig) en genoeg schijfruimte
(± 15 GB tijdens het bouwen);
- de maximale bijlagegrootte (`[attachment] MAX_SIZE` in `app.ini`, in MB)
groter dan het image (± 1 GB);
- optioneel een repository-secret `RELEASE_TOKEN` (token met schrijfrecht op
de repository), als het standaardtoken van de workflow geen releases mag
maken.
## Beheer
### Webinterface — `http://<hostname>.local:8080`
| Pagina | Functies |
|---|---|
| **Dashboard** | Chromium-status, kiosk-URL, uptime, CPU, temperatuur, voeding (onderspanning), RAM, SD-kaart, IP-adressen, verbinding, versie. Grote knoppen voor *Pagina herladen*, *Chromium herstarten* en *Raspberry Pi herstarten*. |
| **Kiosk** | URL (alleen HTTPS), apparaatnaam, automatisch verversen, browserprofiel, herstart na crash, screenshot van het scherm, laatste meldingen. |
| **Systeem** | Herstarten, veilig uitschakelen, hostname, rotatie, resolutie, zoom, screensaver/DPMS, poort/HTTPS van de beheerinterface. |
| **Netwerk** | Status van ethernet en wifi, wifi scannen, wifi instellen, DHCP of statisch IP, DNS, wifi-land. Iedere wijziging moet binnen 3 minuten bevestigd worden, anders volgt een rollback. |
| **Logboek** | Logs per onderdeel (kiosk, Chromium, agent, healthcheck, beheer, netwerk, systeem). |
*Pagina herladen* gebruikt het Chrome DevTools Protocol op localhost: de
browser blijft draaien. *Chromium herstarten* herstart alleen de browser.
*Raspberry Pi herstarten* herstart het hele systeem.
### Commandoregel (via SSH)
```bash
sudo daynivo-kiosk-ctl status # overzicht
sudo daynivo-kiosk-ctl setup-code # setupcode voor de eerste configuratie
sudo daynivo-kiosk-ctl reset-password # wachtwoord vergeten: nieuwe setupcode
sudo daynivo-kiosk-ctl set-url https://… # URL wijzigen
sudo daynivo-kiosk-ctl reload # pagina herladen
sudo daynivo-kiosk-ctl restart-browser # Chromium herstarten
sudo daynivo-kiosk-ctl health # healthcheck-rapport
sudo daynivo-kiosk-ctl maintenance on|off # healthcheck tijdelijk niets laten herstellen
journalctl -u daynivo-kiosk-browser -u daynivo-kiosk-agent -f
```
### Configuratie — `/etc/daynivo-kiosk/config.json`
| Sleutel | Standaard | Betekenis |
|---|---|---|
| `device_name` | `Daynivo Kiosk` | naam in beheer en op de offlinepagina |
| `url` | `https://schermen-ijsselflat.voxip.nl` | kiosk-URL, alleen HTTPS |
| `refresh_interval` | `0` | 0 = uit, anders 30–86400 seconden |
| `screen_always_on` | `true` | geen screensaver/DPMS |
| `screen_off_minutes` | `10` | scherm uit na N minuten (als `screen_always_on` uit staat) |
| `rotation` | `0` | 0, 90, 180, 270 |
| `resolution` | `auto` | `auto` of bijv. `1920x1080` / `1280x720@60` |
| `zoom` | `1.0` | 0,25–4, schaalt de pagina (grote tv's) |
| `browser_restart` | `true` | Chromium automatisch herstarten na een crash |
| `browser_profile` | `persistent` | `persistent` = cookies en offline-cache blijven bewaard, `ephemeral` = alleen in RAM |
| `admin_port` | `8080` | poort van de beheerinterface |
| `admin_https` | `false` | HTTPS met zelfondertekend certificaat |
| `admin_allow_public` | `false` | ook toegang vanaf publieke IP-adressen (afgeraden) |
| `auto_update` | `false` | elke nacht een nieuwe release installeren |
Wijzigingen via de webinterface of `daynivo-kiosk-ctl` worden atomair
opgeslagen, met een `.bak` van de vorige versie. Een URL-wijziging gaat in
zonder dat Chromium herstart. Scherminstellingen gelden na een herstart van
Chromium (een vinkje in de webinterface doet dat direct).
## Uitrol bij meerdere klanten
Eén image voor alle klanten. Per apparaat zet je na het flashen op de
bootpartitie (`bootfs`, zichtbaar op Windows en macOS):
- **`daynivo-config.json`**: instellingen voor deze kiosk, plus optioneel
`hostname` en `wifi_country`. Een voorbeeld staat als
`daynivo-config.example.json` op de bootpartitie.
- **`daynivo-authorized_keys`**: openbare SSH-sleutels. SSH gaat dan aan, alleen
met sleutel-login.
- Wifi en een eigen gebruiker stel je in via Raspberry Pi Imager.
De bestanden worden bij het opstarten verwerkt en hernoemd naar
`*.applied`, of naar `*.rejected` met de reden in `daynivo-config.error.txt`.
### Daynivo-schermen
Voor een Daynivo-display gebruik je als `url` de kiosk-URL van het scherm
uit Daynivo (*Schermen* → scherm → kiosk-URL, inclusief `?token=`). Het
token wordt in de webinterface, de CLI en de logs afgeschermd
(`?token=…ab12`). De kiosk laat een lopende pagina staan als het netwerk
wegvalt. Daynivo toont dan zijn eigen laatst bekende inhoud, en
automatisch verversen wordt overgeslagen zolang de server niet bereikbaar
is.
## Ontwikkelen en testen
```bash
python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest # unit- en webtests
make lint # shellcheck (indien geïnstalleerd)
make test-bookworm # dezelfde tests in Debian Bookworm met de apt-pakketten van de Pi (Docker)
```
Lokaal draaien van de webinterface (zonder Pi; systeemacties falen netjes):
```bash
make dev # http://127.0.0.1:8080 met tijdelijke mappen in .dev/
```
## Probleemoplossing
| Symptoom | Oplossing |
|---|---|
| Zwart scherm na opstarten | `sudo daynivo-kiosk-ctl status`. Kijk in de journal van `daynivo-kiosk-x`/`daynivo-kiosk-browser`. Staat de monitor aan vóór de Pi? |
| Beheerinterface onbereikbaar na netwerkwijziging | Wacht 3 minuten (automatische rollback) of zet `daynivo-network-reset` op de bootpartitie en herstart. |
| Wachtwoord vergeten | `sudo daynivo-kiosk-ctl reset-password` via SSH, of verwijder `/etc/daynivo-kiosk/admin.json` met de SD-kaart in een Linux-pc. |
| `kiosk.local` werkt niet | Gebruik het IP-adres (staat op het setupscherm en in je router). Windows heeft soms Bonjour/mDNS nodig. Geef iedere kiosk een unieke hostname. |
| Onderspanning in het dashboard | Gebruik de officiële 5,1 V/2,5 A-voeding. Onderspanning veroorzaakt crashes en SD-kaartcorruptie. |