VoxIP Kiosk OS 1.0.0: Raspberry Pi kiosk with web management
Chromium kiosk without a desktop for the Raspberry Pi 3, a Flask web interface on port 8080 (kiosk, system and network management), a restricted root helper, network changes with automatic rollback, a healthcheck timer, install/update/uninstall scripts and a pi-gen image build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
a33c4822bf
96 files changed
+7535
No files matched your search
@@ -0,0 +1,221 @@
|
||||
# VoxIP 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 **VoxIP 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/voxip-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. Bouw de image (zie hieronder) of gebruik een uitgebrachte
|
||||
`*-voxip-kiosk-os-*.img.xz`.
|
||||
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 `voxip-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
|
||||
sudo apt-get install -y git
|
||||
git clone <url-van-deze-repository> voxip-kiosk-os
|
||||
cd voxip-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 `voxip` aan, installeert de services en
|
||||
start de kiosk. Aan het eind toont het de setupcode.
|
||||
|
||||
Draaide hier eerder de InfoFlow-kiosk (`raspberry-pi/install-kiosk.sh` uit
|
||||
de InfoFlow-repository)? Dan neemt `install.sh` de display-URL (inclusief
|
||||
`?token=`) automatisch over en schakelt `display-kiosk.service` uit.
|
||||
|
||||
### Updaten
|
||||
|
||||
```bash
|
||||
cd voxip-kiosk-os
|
||||
sudo ./update.sh # git pull --ff-only + back-up van /etc/voxip-kiosk + install.sh --upgrade
|
||||
```
|
||||
|
||||
Een update overschrijft nooit bestaande configuratie of het
|
||||
beheerderswachtwoord. Back-ups staan in `/var/backups/voxip-kiosk-*.tar.gz`
|
||||
(de laatste vijf). Op een apparaat met de image staat de broncode in
|
||||
`/usr/src/voxip-kiosk`. Clone de repository voor updates naar een eigen map,
|
||||
of pak een release uit en draai daar `sudo ./update.sh --no-pull`.
|
||||
|
||||
### 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-voxip` 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>-voxip-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) |
|
||||
| `VOXIP_DEFAULT_URL` | `https://schermen-ijsselflat.voxip.nl` | standaard kiosk-URL |
|
||||
| `VOXIP_DEVICE_NAME` | `VoxIP 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/voxip-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.
|
||||
|
||||
## 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 voxip-kiosk-ctl status # overzicht
|
||||
sudo voxip-kiosk-ctl setup-code # setupcode voor de eerste configuratie
|
||||
sudo voxip-kiosk-ctl reset-password # wachtwoord vergeten: nieuwe setupcode
|
||||
sudo voxip-kiosk-ctl set-url https://… # URL wijzigen
|
||||
sudo voxip-kiosk-ctl reload # pagina herladen
|
||||
sudo voxip-kiosk-ctl restart-browser # Chromium herstarten
|
||||
sudo voxip-kiosk-ctl health # healthcheck-rapport
|
||||
sudo voxip-kiosk-ctl maintenance on|off # healthcheck tijdelijk niets laten herstellen
|
||||
journalctl -u voxip-kiosk-browser -u voxip-kiosk-agent -f
|
||||
```
|
||||
|
||||
### Configuratie — `/etc/voxip-kiosk/config.json`
|
||||
|
||||
| Sleutel | Standaard | Betekenis |
|
||||
|---|---|---|
|
||||
| `device_name` | `VoxIP 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) |
|
||||
|
||||
Wijzigingen via de webinterface of `voxip-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):
|
||||
|
||||
- **`voxip-config.json`**: instellingen voor deze kiosk, plus optioneel
|
||||
`hostname` en `wifi_country`. Een voorbeeld staat als
|
||||
`voxip-config.example.json` op de bootpartitie.
|
||||
- **`voxip-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 `voxip-config.error.txt`.
|
||||
|
||||
### InfoFlow-schermen
|
||||
|
||||
Voor een InfoFlow-display gebruik je als `url` de kiosk-URL van het scherm
|
||||
uit InfoFlow (*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. InfoFlow 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 voxip-kiosk-ctl status`. Kijk in de journal van `voxip-kiosk-x`/`voxip-kiosk-browser`. Staat de monitor aan vóór de Pi? |
|
||||
| Beheerinterface onbereikbaar na netwerkwijziging | Wacht 3 minuten (automatische rollback) of zet `voxip-network-reset` op de bootpartitie en herstart. |
|
||||
| Wachtwoord vergeten | `sudo voxip-kiosk-ctl reset-password` via SSH, of verwijder `/etc/voxip-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. |
|
||||
Reference in new issue
Block a user