Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88e60f9bf9 | ||
|
|
eb0242c182 | ||
|
|
6733aacb6e |
No files matched your search
@@ -26,7 +26,7 @@ jobs:
|
|||||||
- name: Tests
|
- name: Tests
|
||||||
run: python3 -m pytest -p no:cacheprovider
|
run: python3 -m pytest -p no:cacheprovider
|
||||||
- name: Shellcheck
|
- name: Shellcheck
|
||||||
run: shellcheck -S warning install.sh install-online.sh update.sh uninstall.sh tools/release-upload.sh image/build.sh image/stage-voxip/prerun.sh image/stage-voxip/00-voxip/00-run.sh bin/voxip-kiosk-x
|
run: shellcheck -S warning install.sh install-online.sh update.sh uninstall.sh tools/release-upload.sh image/build.sh image/stage-daynivo/prerun.sh image/stage-daynivo/00-daynivo/00-run.sh bin/daynivo-kiosk-x
|
||||||
|
|
||||||
test-latest:
|
test-latest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
PY ?= .venv/bin/python
|
PY ?= .venv/bin/python
|
||||||
DEV := $(CURDIR)/.dev
|
DEV := $(CURDIR)/.dev
|
||||||
DEV_ENV := PYTHONPATH=src VOXIP_CONFIG_DIR=$(DEV)/etc VOXIP_STATE_DIR=$(DEV)/state VOXIP_LOG_DIR=$(DEV)/log \
|
DEV_ENV := PYTHONPATH=src DAYNIVO_CONFIG_DIR=$(DEV)/etc DAYNIVO_STATE_DIR=$(DEV)/state DAYNIVO_LOG_DIR=$(DEV)/log \
|
||||||
VOXIP_SHARE_DIR=$(DEV)/share VOXIP_AGENT_RUN_DIR=$(DEV)/run VOXIP_BROWSER_RUN_DIR=$(DEV)/run \
|
DAYNIVO_SHARE_DIR=$(DEV)/share DAYNIVO_AGENT_RUN_DIR=$(DEV)/run DAYNIVO_BROWSER_RUN_DIR=$(DEV)/run \
|
||||||
VOXIP_NETWORK_STATE_DIR=$(DEV)/net VOXIP_HELPER=/nonexistent/voxip-kiosk-helper
|
DAYNIVO_NETWORK_STATE_DIR=$(DEV)/net DAYNIVO_HELPER=/nonexistent/daynivo-kiosk-helper
|
||||||
|
|
||||||
.PHONY: venv test lint test-bookworm dev image clean
|
.PHONY: venv test lint test-bookworm dev image clean
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@ test:
|
|||||||
$(PY) -m pytest
|
$(PY) -m pytest
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
shellcheck -S warning install.sh update.sh uninstall.sh image/build.sh image/stage-voxip/prerun.sh \
|
shellcheck -S warning install.sh update.sh uninstall.sh image/build.sh image/stage-daynivo/prerun.sh \
|
||||||
image/stage-voxip/00-voxip/00-run.sh bin/voxip-kiosk-x
|
image/stage-daynivo/00-daynivo/00-run.sh bin/daynivo-kiosk-x
|
||||||
|
|
||||||
# The test suite against the exact Python/Flask/argon2 versions that Raspberry Pi OS Bookworm ships.
|
# The test suite against the exact Python/Flask/argon2 versions that Raspberry Pi OS Bookworm ships.
|
||||||
test-bookworm:
|
test-bookworm:
|
||||||
@@ -22,7 +22,7 @@ test-bookworm:
|
|||||||
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \
|
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \
|
||||||
python3 python3-flask python3-argon2 python3-websocket python3-pytest shellcheck >/dev/null && \
|
python3 python3-flask python3-argon2 python3-websocket python3-pytest shellcheck >/dev/null && \
|
||||||
cp -r /src /work && cd /work && rm -rf .venv && python3 -m pytest -p no:cacheprovider && \
|
cp -r /src /work && cd /work && rm -rf .venv && python3 -m pytest -p no:cacheprovider && \
|
||||||
shellcheck -S warning install.sh install-online.sh update.sh uninstall.sh tools/release-upload.sh image/build.sh bin/voxip-kiosk-x'
|
shellcheck -S warning install.sh install-online.sh update.sh uninstall.sh tools/release-upload.sh image/build.sh bin/daynivo-kiosk-x'
|
||||||
|
|
||||||
# Web interface on http://127.0.0.1:8080 with throwaway state in .dev/ (system actions fail gracefully).
|
# Web interface on http://127.0.0.1:8080 with throwaway state in .dev/ (system actions fail gracefully).
|
||||||
dev:
|
dev:
|
||||||
@@ -30,7 +30,7 @@ dev:
|
|||||||
test -f $(DEV)/etc/config.json || cp config/config.default.json $(DEV)/etc/config.json
|
test -f $(DEV)/etc/config.json || cp config/config.default.json $(DEV)/etc/config.json
|
||||||
cp VERSION $(DEV)/share/VERSION
|
cp VERSION $(DEV)/share/VERSION
|
||||||
@echo "Setupcode: zie $(DEV)/etc/setup-code (wordt aangemaakt bij de start)"
|
@echo "Setupcode: zie $(DEV)/etc/setup-code (wordt aangemaakt bij de start)"
|
||||||
$(DEV_ENV) $(PY) -m flask --app 'voxip_kiosk.web:create_app()' run --host 127.0.0.1 --port 8080
|
$(DEV_ENV) $(PY) -m flask --app 'daynivo_kiosk.web:create_app()' run --host 127.0.0.1 --port 8080
|
||||||
|
|
||||||
image:
|
image:
|
||||||
./image/build.sh
|
./image/build.sh
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ webinterface **Daynivo Kiosk Manager** op `http://kiosk.local:8080`.
|
|||||||
een setupcode die op het scherm staat.
|
een setupcode die op het scherm staat.
|
||||||
- Netwerkwijzigingen met automatische rollback.
|
- Netwerkwijzigingen met automatische rollback.
|
||||||
- Geen klantspecifieke code: alles per klant staat in
|
- Geen klantspecifieke code: alles per klant staat in
|
||||||
`/etc/voxip-kiosk/config.json` en kan bij uitrol via de bootpartitie
|
`/etc/daynivo-kiosk/config.json` en kan bij uitrol via de bootpartitie
|
||||||
worden meegegeven.
|
worden meegegeven.
|
||||||
|
|
||||||
De architectuur en de veiligheidskeuzes staan in
|
De architectuur en de veiligheidskeuzes staan in
|
||||||
@@ -61,7 +61,7 @@ sudo ./install.sh --url "https://schermen-ijsselflat.voxip.nl" --name "IJsselfla
|
|||||||
```
|
```
|
||||||
|
|
||||||
Alle opties zijn optioneel. Het script installeert de benodigde pakketten,
|
Alle opties zijn optioneel. Het script installeert de benodigde pakketten,
|
||||||
maakt de gebruikers `kiosk` en `voxip` aan, installeert de services en
|
maakt de gebruikers `kiosk` en `daynivo` aan, installeert de services en
|
||||||
start de kiosk. Aan het eind toont het de setupcode.
|
start de kiosk. Aan het eind toont het de setupcode.
|
||||||
|
|
||||||
Draaide hier eerder de Daynivo-kiosk (`raspberry-pi/install-kiosk.sh` uit
|
Draaide hier eerder de Daynivo-kiosk (`raspberry-pi/install-kiosk.sh` uit
|
||||||
@@ -72,14 +72,14 @@ de Daynivo-repository)? Dan neemt `install.sh` de display-URL (inclusief
|
|||||||
|
|
||||||
In de webinterface onder **Systeem → Software-updates**: *Nu controleren*,
|
In de webinterface onder **Systeem → Software-updates**: *Nu controleren*,
|
||||||
*Bijwerken naar …*, en het vinkje **Automatisch bijwerken**. Elke nacht
|
*Bijwerken naar …*, en het vinkje **Automatisch bijwerken**. Elke nacht
|
||||||
tussen 03:00 en 05:00 (`voxip-kiosk-update.timer`) kijkt de kiosk of er een
|
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
|
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.
|
ook op een apparaat dat met de image of vanuit een clone is geïnstalleerd.
|
||||||
Vanaf de commandoregel:
|
Vanaf de commandoregel:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo /usr/lib/voxip-kiosk/voxip-kiosk-updater --check # alleen kijken
|
sudo /usr/lib/daynivo-kiosk/daynivo-kiosk-updater --check # alleen kijken
|
||||||
sudo /usr/lib/voxip-kiosk/voxip-kiosk-updater --install # nieuwste release installeren
|
sudo /usr/lib/daynivo-kiosk/daynivo-kiosk-updater --install # nieuwste release installeren
|
||||||
```
|
```
|
||||||
|
|
||||||
De updater installeert alleen een nieuwere versie met een kloppende
|
De updater installeert alleen een nieuwere versie met een kloppende
|
||||||
@@ -89,15 +89,40 @@ het ook met git:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd daynivo-kiosk-os
|
cd daynivo-kiosk-os
|
||||||
sudo ./update.sh # git pull --ff-only + back-up van /etc/voxip-kiosk + install.sh --upgrade
|
sudo ./update.sh # git pull --ff-only + back-up van /etc/daynivo-kiosk + install.sh --upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
Een update overschrijft nooit bestaande configuratie of het
|
Een update overschrijft nooit bestaande configuratie of het
|
||||||
beheerderswachtwoord. Back-ups staan in `/var/backups/voxip-kiosk-*.tar.gz`
|
beheerderswachtwoord. Back-ups staan in `/var/backups/daynivo-kiosk-*.tar.gz`
|
||||||
(de laatste vijf). Op een apparaat met de image staat de broncode in
|
(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,
|
`/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`.
|
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
|
### Verwijderen
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -109,7 +134,7 @@ sudo ./uninstall.sh --purge # ook configuratie, status, logs, netwerkprofielen
|
|||||||
|
|
||||||
Het image wordt gebouwd met [pi-gen](https://github.com/RPi-Distro/pi-gen),
|
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
|
de officiële bouwtool van Raspberry Pi OS. De extra stage
|
||||||
`image/stage-voxip` voert hetzelfde `install.sh` uit als een handmatige
|
`image/stage-daynivo` voert hetzelfde `install.sh` uit als een handmatige
|
||||||
installatie.
|
installatie.
|
||||||
|
|
||||||
Vereist: een Linux-buildmachine (x86_64 of arm64) met Docker en git. Op
|
Vereist: een Linux-buildmachine (x86_64 of arm64) met Docker en git. Op
|
||||||
@@ -131,14 +156,14 @@ Instelbaar via omgevingsvariabelen:
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `PI_GEN_REF` | `2024-11-19-raspios-bookworm-armhf` | pi-gen-tag (32-bit) |
|
| `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) |
|
| `RELEASE` | `bookworm` | `bookworm` of `trixie` (moet bij `PI_GEN_REF` passen) |
|
||||||
| `VOXIP_DEFAULT_URL` | `https://schermen-ijsselflat.voxip.nl` | standaard kiosk-URL |
|
| `DAYNIVO_DEFAULT_URL` | `https://schermen-ijsselflat.voxip.nl` | standaard kiosk-URL |
|
||||||
| `VOXIP_DEVICE_NAME` | `Daynivo Kiosk` | standaard apparaatnaam |
|
| `DAYNIVO_DEVICE_NAME` | `Daynivo Kiosk` | standaard apparaatnaam |
|
||||||
| `TARGET_HOSTNAME` | `kiosk` | hostname (`http://<hostname>.local:8080`) |
|
| `TARGET_HOSTNAME` | `kiosk` | hostname (`http://<hostname>.local:8080`) |
|
||||||
| `ALLOW_DIRTY` | `0` | `1` = bouw de werkmap in plaats van de laatste commit |
|
| `ALLOW_DIRTY` | `0` | `1` = bouw de werkmap in plaats van de laatste commit |
|
||||||
|
|
||||||
**Reproduceerbaarheid.** pi-gen staat vast op een tag en de broncode
|
**Reproduceerbaarheid.** pi-gen staat vast op een tag en de broncode
|
||||||
gaat via `git archive` van één commit mee. Beide staan in `BUILD-INFO`
|
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
|
(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
|
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
|
bouwen zijn. Er bestaat geen snapshot-archief voor Raspberry Pi OS, dus
|
||||||
twee builds op verschillende dagen kunnen nieuwere pakketversies bevatten.
|
twee builds op verschillende dagen kunnen nieuwere pakketversies bevatten.
|
||||||
@@ -199,10 +224,10 @@ sudo daynivo-kiosk-ctl reload # pagina herladen
|
|||||||
sudo daynivo-kiosk-ctl restart-browser # Chromium herstarten
|
sudo daynivo-kiosk-ctl restart-browser # Chromium herstarten
|
||||||
sudo daynivo-kiosk-ctl health # healthcheck-rapport
|
sudo daynivo-kiosk-ctl health # healthcheck-rapport
|
||||||
sudo daynivo-kiosk-ctl maintenance on|off # healthcheck tijdelijk niets laten herstellen
|
sudo daynivo-kiosk-ctl maintenance on|off # healthcheck tijdelijk niets laten herstellen
|
||||||
journalctl -u voxip-kiosk-browser -u voxip-kiosk-agent -f
|
journalctl -u daynivo-kiosk-browser -u daynivo-kiosk-agent -f
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuratie — `/etc/voxip-kiosk/config.json`
|
### Configuratie — `/etc/daynivo-kiosk/config.json`
|
||||||
|
|
||||||
| Sleutel | Standaard | Betekenis |
|
| Sleutel | Standaard | Betekenis |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -270,8 +295,8 @@ make dev # http://127.0.0.1:8080 met tijdelijke mappen in .dev/
|
|||||||
|
|
||||||
| Symptoom | Oplossing |
|
| Symptoom | Oplossing |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Zwart scherm na opstarten | `sudo daynivo-kiosk-ctl status`. Kijk in de journal van `voxip-kiosk-x`/`voxip-kiosk-browser`. Staat de monitor aan vóór de Pi? |
|
| 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. |
|
| 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/voxip-kiosk/admin.json` met de SD-kaart in een Linux-pc. |
|
| 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. |
|
| `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. |
|
| Onderspanning in het dashboard | Gebruik de officiële 5,1 V/2,5 A-voeding. Onderspanning veroorzaakt crashes en SD-kaartcorruptie. |
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python3 -I
|
||||||
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
|
from daynivo_kiosk.agent import main # noqa: E402
|
||||||
|
|
||||||
|
sys.exit(main())
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python3 -I
|
||||||
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
|
from daynivo_kiosk.browser import main # noqa: E402
|
||||||
|
|
||||||
|
sys.exit(main())
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/python3 -I
|
#!/usr/bin/python3 -I
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
from voxip_kiosk.ctl import main # noqa: E402
|
from daynivo_kiosk.ctl import main # noqa: E402
|
||||||
|
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python3 -I
|
||||||
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
|
from daynivo_kiosk.healthcheck import main # noqa: E402
|
||||||
|
|
||||||
|
sys.exit(main())
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python3 -I
|
||||||
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
|
from daynivo_kiosk.helper import main # noqa: E402
|
||||||
|
|
||||||
|
sys.exit(main())
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python3 -I
|
||||||
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
|
from daynivo_kiosk.manager import main # noqa: E402
|
||||||
|
|
||||||
|
sys.exit(main())
|
||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python3 -I
|
||||||
|
# Installed to /usr/lib/daynivo-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
|
|
||||||
|
from daynivo_kiosk.updater import main # noqa: E402
|
||||||
|
|
||||||
|
sys.exit(main())
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# Starts the kiosk X server on vt7 for user "kiosk" (via Xorg.wrap).
|
# Starts the kiosk X server on vt7 for user "kiosk" (via Xorg.wrap).
|
||||||
# A fresh MIT cookie per start; Chromium reads it via XAUTHORITY.
|
# A fresh MIT cookie per start; Chromium reads it via XAUTHORITY.
|
||||||
set -eu
|
set -eu
|
||||||
AUTH="${RUNTIME_DIRECTORY:-/run/voxip-kiosk-x}/Xauthority"
|
AUTH="${RUNTIME_DIRECTORY:-/run/daynivo-kiosk-x}/Xauthority"
|
||||||
umask 077
|
umask 077
|
||||||
: > "$AUTH"
|
: > "$AUTH"
|
||||||
xauth -q -f "$AUTH" add :0 . "$(mcookie)"
|
xauth -q -f "$AUTH" add :0 . "$(mcookie)"
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/python3 -I
|
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
|
||||||
|
|
||||||
from voxip_kiosk.agent import main # noqa: E402
|
|
||||||
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/python3 -I
|
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
|
||||||
|
|
||||||
from voxip_kiosk.browser import main # noqa: E402
|
|
||||||
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/python3 -I
|
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
|
||||||
|
|
||||||
from voxip_kiosk.healthcheck import main # noqa: E402
|
|
||||||
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/python3 -I
|
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
|
||||||
|
|
||||||
from voxip_kiosk.helper import main # noqa: E402
|
|
||||||
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/python3 -I
|
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
|
||||||
|
|
||||||
from voxip_kiosk.manager import main # noqa: E402
|
|
||||||
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/python3 -I
|
|
||||||
# Installed to /usr/lib/voxip-kiosk/ by install.sh. -I: ignore PYTHON* env and user site-packages.
|
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
|
||||||
|
|
||||||
from voxip_kiosk.updater import main # noqa: E402
|
|
||||||
|
|
||||||
sys.exit(main())
|
|
||||||
File renamed without changes.
File renamed without changes.
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
/var/log/voxip-kiosk/*.log {
|
/var/log/daynivo-kiosk/*.log {
|
||||||
weekly
|
weekly
|
||||||
rotate 8
|
rotate 8
|
||||||
maxsize 2M
|
maxsize 2M
|
||||||
@@ -6,6 +6,6 @@
|
|||||||
delaycompress
|
delaycompress
|
||||||
missingok
|
missingok
|
||||||
notifempty
|
notifempty
|
||||||
create 0640 voxip voxip
|
create 0640 daynivo daynivo
|
||||||
su voxip voxip
|
su daynivo daynivo
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
[Plymouth Theme]
|
||||||
|
Name=daynivo-kiosk
|
||||||
|
Description=Daynivo Kiosk boot splash (logo on white)
|
||||||
|
ModuleName=script
|
||||||
|
|
||||||
|
[script]
|
||||||
|
ImageDir=/usr/share/plymouth/themes/daynivo-kiosk
|
||||||
|
ScriptFile=/usr/share/plymouth/themes/daynivo-kiosk/daynivo-kiosk.script
|
||||||
File renamed without changes.
File renamed without changes.
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
@@ -1,8 +0,0 @@
|
|||||||
[Plymouth Theme]
|
|
||||||
Name=voxip-kiosk
|
|
||||||
Description=Daynivo Kiosk boot splash (logo on white)
|
|
||||||
ModuleName=script
|
|
||||||
|
|
||||||
[script]
|
|
||||||
ImageDir=/usr/share/plymouth/themes/voxip-kiosk
|
|
||||||
ScriptFile=/usr/share/plymouth/themes/voxip-kiosk/voxip-kiosk.script
|
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
# Daynivo Kiosk OS: the web interface (user voxip) may run exactly one program
|
# Daynivo Kiosk OS: the web interface (user daynivo) may run exactly one program
|
||||||
# as root: the restricted helper, which validates all of its input itself.
|
# as root: the restricted helper, which validates all of its input itself.
|
||||||
Defaults:voxip !requiretty
|
Defaults:daynivo !requiretty
|
||||||
voxip ALL=(root) NOPASSWD: /usr/lib/voxip-kiosk/voxip-kiosk-helper
|
daynivo ALL=(root) NOPASSWD: /usr/lib/daynivo-kiosk/daynivo-kiosk-helper
|
||||||
+27
-27
@@ -11,7 +11,7 @@ samenwerken en waarom bepaalde keuzes zijn gemaakt.
|
|||||||
- Eén HTTPS-pagina fullscreen in Chromium, zonder desktopomgeving.
|
- Eén HTTPS-pagina fullscreen in Chromium, zonder desktopomgeving.
|
||||||
- Lokale webbeheerinterface (*Daynivo Kiosk Manager*) op poort 8080.
|
- Lokale webbeheerinterface (*Daynivo Kiosk Manager*) op poort 8080.
|
||||||
- Geen klantspecifieke code: alles wat per klant verschilt staat in
|
- Geen klantspecifieke code: alles wat per klant verschilt staat in
|
||||||
`/etc/voxip-kiosk/config.json` en kan bij uitrol via de bootpartitie
|
`/etc/daynivo-kiosk/config.json` en kan bij uitrol via de bootpartitie
|
||||||
worden meegegeven (`daynivo-config.json`).
|
worden meegegeven (`daynivo-config.json`).
|
||||||
|
|
||||||
## Overzicht
|
## Overzicht
|
||||||
@@ -19,25 +19,25 @@ samenwerken en waarom bepaalde keuzes zijn gemaakt.
|
|||||||
```
|
```
|
||||||
┌──────────────────────── Raspberry Pi ────────────────────────┐
|
┌──────────────────────── Raspberry Pi ────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
HDMI ◄────────┤ voxip-kiosk-x.service Xorg :0 op vt7 (user kiosk) │
|
HDMI ◄────────┤ daynivo-kiosk-x.service Xorg :0 op vt7 (user kiosk) │
|
||||||
│ ▲ │
|
│ ▲ │
|
||||||
│ │ DISPLAY=:0 │
|
│ │ DISPLAY=:0 │
|
||||||
│ voxip-kiosk-browser.service Chromium --kiosk (user kiosk) │
|
│ daynivo-kiosk-browser.service Chromium --kiosk (user kiosk) │
|
||||||
│ ▲ CDP 127.0.0.1:9222 │
|
│ ▲ CDP 127.0.0.1:9222 │
|
||||||
│ │ ┌─────────────────────────────┐ │
|
│ │ ┌─────────────────────────────┐ │
|
||||||
│ ├──┤ voxip-kiosk-agent.service │ navigatie, offline-│
|
│ ├──┤ daynivo-kiosk-agent.service │ navigatie, offline-│
|
||||||
│ │ │ (user kiosk) │ pagina, verversen, │
|
│ │ │ (user kiosk) │ pagina, verversen, │
|
||||||
│ │ └─────────────────────────────┘ hang-detectie │
|
│ │ └─────────────────────────────┘ hang-detectie │
|
||||||
│ │ │
|
│ │ │
|
||||||
LAN :8080 ───►│ voxip-kiosk-manager.service Flask + gunicorn (user voxip) │
|
LAN :8080 ───►│ daynivo-kiosk-manager.service Flask + gunicorn (user daynivo) │
|
||||||
│ │ sudo -n (één commando) │
|
│ │ sudo -n (één commando) │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ voxip-kiosk-helper root, vaste werkwoorden, │
|
│ daynivo-kiosk-helper root, vaste werkwoorden, │
|
||||||
│ strikte invoervalidatie │
|
│ strikte invoervalidatie │
|
||||||
│ │
|
│ │
|
||||||
│ voxip-kiosk-healthcheck.timer elke minuut, root │
|
│ daynivo-kiosk-healthcheck.timer elke minuut, root │
|
||||||
│ voxip-network-guard.service netwerk-rollback bij boot │
|
│ daynivo-network-guard.service netwerk-rollback bij boot │
|
||||||
│ voxip-boot-import.service config/SSH-sleutels vanaf │
|
│ daynivo-boot-import.service config/SSH-sleutels vanaf │
|
||||||
│ de bootpartitie │
|
│ de bootpartitie │
|
||||||
└──────────────────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
@@ -46,16 +46,16 @@ samenwerken en waarom bepaalde keuzes zijn gemaakt.
|
|||||||
|
|
||||||
| Onderdeel | Gebruiker | Taak |
|
| Onderdeel | Gebruiker | Taak |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `voxip-kiosk-x` | `kiosk` (via Xorg.wrap) | Minimale X-server op vt7, zonder cursor, zonder TCP. |
|
| `daynivo-kiosk-x` | `kiosk` (via Xorg.wrap) | Minimale X-server op vt7, zonder cursor, zonder TCP. |
|
||||||
| `voxip-kiosk-browser` | `kiosk` | Past rotatie/resolutie/DPMS toe (xrandr/xset), ruimt een vastgelopen profiel op en start Chromium. |
|
| `daynivo-kiosk-browser` | `kiosk` | Past rotatie/resolutie/DPMS toe (xrandr/xset), ruimt een vastgelopen profiel op en start Chromium. |
|
||||||
| `voxip-kiosk-agent` | `kiosk` | Bestuurt Chromium via het DevTools Protocol op localhost: offline-pagina, URL-wissel zonder herstart, periodiek verversen, hang-detectie. |
|
| `daynivo-kiosk-agent` | `kiosk` | Bestuurt Chromium via het DevTools Protocol op localhost: offline-pagina, URL-wissel zonder herstart, periodiek verversen, hang-detectie. |
|
||||||
| `voxip-kiosk-manager` | `voxip` | Flask-webinterface (gunicorn, 1 worker, 4 threads). |
|
| `daynivo-kiosk-manager` | `daynivo` | Flask-webinterface (gunicorn, 1 worker, 4 threads). |
|
||||||
| `voxip-kiosk-helper` | `root` (via sudo) | Enige geprivilegieerde ingang: reboot, uitschakelen, Chromium herstarten, hostname, wifi-land, wifi-scan, netwerkconfiguratie + rollback, updates controleren en starten. |
|
| `daynivo-kiosk-helper` | `root` (via sudo) | Enige geprivilegieerde ingang: reboot, uitschakelen, Chromium herstarten, hostname, wifi-land, wifi-scan, netwerkconfiguratie + rollback, updates controleren en starten. |
|
||||||
| `voxip-kiosk-updater` | `root` (timer, of eigen transient unit via de helper) | Haalt de nieuwste release op (HTTPS, SHA-256), pakt hem uit in `/opt/daynivo-kiosk-os/<versie>` en draait `update.sh --no-pull`. Nooit een oudere of gelijke versie. |
|
| `daynivo-kiosk-updater` | `root` (timer, of eigen transient unit via de helper) | Haalt de nieuwste release op (HTTPS, SHA-256), pakt hem uit in `/opt/daynivo-kiosk-os/<versie>` en draait `update.sh --no-pull`. Nooit een oudere of gelijke versie. |
|
||||||
| `voxip-kiosk-healthcheck` | `root` | Bewaakt alle services en herstelt ze, met logging. |
|
| `daynivo-kiosk-healthcheck` | `root` | Bewaakt alle services en herstelt ze, met logging. |
|
||||||
|
|
||||||
De webinterface draait **nooit** als root. De sudoers-regel staat
|
De webinterface draait **nooit** als root. De sudoers-regel staat
|
||||||
uitsluitend `/usr/lib/voxip-kiosk/voxip-kiosk-helper` toe. De helper:
|
uitsluitend `/usr/lib/daynivo-kiosk/daynivo-kiosk-helper` toe. De helper:
|
||||||
|
|
||||||
- draait met `python3 -I` (geen `PYTHONPATH`, geen user site-packages);
|
- draait met `python3 -I` (geen `PYTHONPATH`, geen user site-packages);
|
||||||
- kent alleen een vaste lijst werkwoorden; interne werkwoorden (zoals
|
- kent alleen een vaste lijst werkwoorden; interne werkwoorden (zoals
|
||||||
@@ -69,8 +69,8 @@ uitsluitend `/usr/lib/voxip-kiosk/voxip-kiosk-helper` toe. De helper:
|
|||||||
|
|
||||||
Xorg en Chromium zijn aparte services. Daardoor is *Chromium herstarten*
|
Xorg en Chromium zijn aparte services. Daardoor is *Chromium herstarten*
|
||||||
snel (X blijft draaien) en geeft het exitcode van Chromium direct aan
|
snel (X blijft draaien) en geeft het exitcode van Chromium direct aan
|
||||||
systemd door. `voxip-kiosk-browser` heeft `Requires=` en `PartOf=` op
|
systemd door. `daynivo-kiosk-browser` heeft `Requires=` en `PartOf=` op
|
||||||
`voxip-kiosk-x`: valt X weg, dan start de browser opnieuw mee.
|
`daynivo-kiosk-x`: valt X weg, dan start de browser opnieuw mee.
|
||||||
|
|
||||||
### Chromium besturen via CDP
|
### Chromium besturen via CDP
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ webinterface gebruiken dit om:
|
|||||||
### Offline-gedrag
|
### Offline-gedrag
|
||||||
|
|
||||||
Chromium start altijd op een lokale startpagina
|
Chromium start altijd op een lokale startpagina
|
||||||
(`/usr/share/voxip-kiosk/www/start.html`). De agent controleert met een
|
(`/usr/share/daynivo-kiosk/www/start.html`). De agent controleert met een
|
||||||
HTTPS-verzoek (mét certificaatvalidatie) of de doel-URL bereikbaar is en
|
HTTPS-verzoek (mét certificaatvalidatie) of de doel-URL bereikbaar is en
|
||||||
navigeert pas dan. De offline-pagina verschijnt alleen als de pagina niet
|
navigeert pas dan. De offline-pagina verschijnt alleen als de pagina niet
|
||||||
**geladen** kan worden (startpagina, Chromium-foutpagina). Valt het
|
**geladen** kan worden (startpagina, Chromium-foutpagina). Valt het
|
||||||
@@ -111,13 +111,13 @@ draait) kan het apparaat dus claimen, iemand anders op het netwerk niet.
|
|||||||
|
|
||||||
1. De helper maakt een snapshot van `/etc/NetworkManager/system-connections`
|
1. De helper maakt een snapshot van `/etc/NetworkManager/system-connections`
|
||||||
en van de actieve verbindingen.
|
en van de actieve verbindingen.
|
||||||
2. Hij schrijft het nieuwe profiel (`voxip-eth0` / `voxip-wlan0`, prioriteit
|
2. Hij schrijft het nieuwe profiel (`daynivo-eth0` / `daynivo-wlan0`, prioriteit
|
||||||
100) en plant een rollback-timer (`systemd-run`, 180 s).
|
100) en plant een rollback-timer (`systemd-run`, 180 s).
|
||||||
3. Activatie gebeurt asynchroon, zodat het HTTP-antwoord nog aankomt.
|
3. Activatie gebeurt asynchroon, zodat het HTTP-antwoord nog aankomt.
|
||||||
4. De beheerder bevestigt binnen 180 s (eventueel via het nieuwe adres),
|
4. De beheerder bevestigt binnen 180 s (eventueel via het nieuwe adres),
|
||||||
anders zet de timer de snapshot terug.
|
anders zet de timer de snapshot terug.
|
||||||
5. Valt de stroom uit tijdens die periode, dan zet
|
5. Valt de stroom uit tijdens die periode, dan zet
|
||||||
`voxip-network-guard.service` de snapshot terug bij het opstarten, nog
|
`daynivo-network-guard.service` de snapshot terug bij het opstarten, nog
|
||||||
vóór NetworkManager start.
|
vóór NetworkManager start.
|
||||||
6. Noodherstel: een leeg bestand `daynivo-network-reset` op de bootpartitie
|
6. Noodherstel: een leeg bestand `daynivo-network-reset` op de bootpartitie
|
||||||
verwijdert bij de volgende boot alle Daynivo-netwerkprofielen (terug naar
|
verwijdert bij de volgende boot alle Daynivo-netwerkprofielen (terug naar
|
||||||
@@ -125,12 +125,12 @@ draait) kan het apparaat dus claimen, iemand anders op het netwerk niet.
|
|||||||
|
|
||||||
### Configuratie
|
### Configuratie
|
||||||
|
|
||||||
- `/etc/voxip-kiosk/config.json`: eigenaar `voxip`, groep `kiosk`, 0640.
|
- `/etc/daynivo-kiosk/config.json`: eigenaar `daynivo`, groep `kiosk`, 0640.
|
||||||
Wordt atomair opgeslagen (tijdelijk bestand, `fsync`, `rename`, `fsync`
|
Wordt atomair opgeslagen (tijdelijk bestand, `fsync`, `rename`, `fsync`
|
||||||
van de map) met een `.bak` van de vorige versie. Ongeldige waarden vallen
|
van de map) met een `.bak` van de vorige versie. Ongeldige waarden vallen
|
||||||
bij het laden terug op de standaard, zodat de kiosk altijd start.
|
bij het laden terug op de standaard, zodat de kiosk altijd start.
|
||||||
Onbekende sleutels blijven bewaard (vooruit-/achteruitcompatibel).
|
Onbekende sleutels blijven bewaard (vooruit-/achteruitcompatibel).
|
||||||
- `/etc/voxip-kiosk/admin.json`: Argon2id-hash, 0600, alleen `voxip`.
|
- `/etc/daynivo-kiosk/admin.json`: Argon2id-hash, 0600, alleen `daynivo`.
|
||||||
- Updates (`install.sh --upgrade` / `update.sh` / de updater) overschrijven
|
- Updates (`install.sh --upgrade` / `update.sh` / de updater) overschrijven
|
||||||
nooit bestaande configuratie. De updater draait in een eigen systemd-unit,
|
nooit bestaande configuratie. De updater draait in een eigen systemd-unit,
|
||||||
zodat het herstarten van de beheerinterface tijdens `install.sh` de update
|
zodat het herstarten van de beheerinterface tijdens `install.sh` de update
|
||||||
@@ -179,8 +179,8 @@ daynivo-kiosk-os/
|
|||||||
├── install.sh installatie op bestaande Pi OS + gebruikt door image-build
|
├── install.sh installatie op bestaande Pi OS + gebruikt door image-build
|
||||||
├── update.sh update met backup van configuratie
|
├── update.sh update met backup van configuratie
|
||||||
├── uninstall.sh verwijderen (--purge voor alles)
|
├── uninstall.sh verwijderen (--purge voor alles)
|
||||||
├── bin/ dunne launchers → /usr/lib/voxip-kiosk/
|
├── bin/ dunne launchers → /usr/lib/daynivo-kiosk/
|
||||||
├── src/voxip_kiosk/ Python-package (alle logica)
|
├── src/daynivo_kiosk/ Python-package (alle logica)
|
||||||
│ ├── config.py laden/valideren/atomair opslaan
|
│ ├── config.py laden/valideren/atomair opslaan
|
||||||
│ ├── validation.py gedeelde invoervalidatie
|
│ ├── validation.py gedeelde invoervalidatie
|
||||||
│ ├── cdp.py Chrome DevTools Protocol-client
|
│ ├── cdp.py Chrome DevTools Protocol-client
|
||||||
@@ -197,7 +197,7 @@ daynivo-kiosk-os/
|
|||||||
├── www/ lokale kioskpagina's (start, offline, setup)
|
├── www/ lokale kioskpagina's (start, offline, setup)
|
||||||
├── systemd/ unit-bestanden
|
├── systemd/ unit-bestanden
|
||||||
├── config/ standaardconfig, sudoers, journald, logrotate, …
|
├── config/ standaardconfig, sudoers, journald, logrotate, …
|
||||||
├── image/ pi-gen image-builder (stage-voxip)
|
├── image/ pi-gen image-builder (stage-daynivo)
|
||||||
├── tests/ pytest-suite
|
├── tests/ pytest-suite
|
||||||
└── docs/ architectuur, hardwaretest
|
└── docs/ architectuur, hardwaretest
|
||||||
```
|
```
|
||||||
@@ -20,7 +20,7 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype.
|
|||||||
- [ ] Binnen 90 s na stroom aan verschijnt het setupscherm met de setupcode,
|
- [ ] Binnen 90 s na stroom aan verschijnt het setupscherm met de setupcode,
|
||||||
`http://kiosk.local:8080` en het IP-adres. Er is geen muiscursor en
|
`http://kiosk.local:8080` en het IP-adres. Er is geen muiscursor en
|
||||||
er zijn geen dialoogvensters.
|
er zijn geen dialoogvensters.
|
||||||
- [ ] SSH is uit (`ssh voxipadmin@kiosk.local` wordt geweigerd), en er is
|
- [ ] SSH is uit (`ssh daynivoadmin@kiosk.local` wordt geweigerd), en er is
|
||||||
geen bruikbaar standaardwachtwoord.
|
geen bruikbaar standaardwachtwoord.
|
||||||
|
|
||||||
## 2. Initiële configuratie
|
## 2. Initiële configuratie
|
||||||
@@ -47,7 +47,7 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype.
|
|||||||
(zie Logboek → Kiosk-agent).
|
(zie Logboek → Kiosk-agent).
|
||||||
- [ ] Screenshot op de Kiosk-pagina toont wat er op het scherm staat.
|
- [ ] Screenshot op de Kiosk-pagina toont wat er op het scherm staat.
|
||||||
- [ ] Daynivo-URL met `?token=`: het token is overal gemaskeerd
|
- [ ] Daynivo-URL met `?token=`: het token is overal gemaskeerd
|
||||||
(dashboard, `daynivo-kiosk-ctl status`, `journalctl -u voxip-kiosk-agent`).
|
(dashboard, `daynivo-kiosk-ctl status`, `journalctl -u daynivo-kiosk-agent`).
|
||||||
|
|
||||||
## 4. Herstel
|
## 4. Herstel
|
||||||
|
|
||||||
@@ -61,9 +61,9 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype.
|
|||||||
Zet de URL daarna terug.
|
Zet de URL daarna terug.
|
||||||
- [ ] Vastgelopen pagina: open via SSH-tunnel DevTools of zet een testpagina met
|
- [ ] Vastgelopen pagina: open via SSH-tunnel DevTools of zet een testpagina met
|
||||||
`while(true){}` in. Na ±15 s herlaadt de agent, na ±30 s herstart Chromium.
|
`while(true){}` in. Na ±15 s herlaadt de agent, na ±30 s herstart Chromium.
|
||||||
- [ ] `sudo systemctl stop voxip-kiosk-agent`: de healthcheck start hem binnen 2 minuten.
|
- [ ] `sudo systemctl stop daynivo-kiosk-agent`: de healthcheck start hem binnen 2 minuten.
|
||||||
- [ ] De webinterface blijft werken terwijl Chromium gestopt is
|
- [ ] De webinterface blijft werken terwijl Chromium gestopt is
|
||||||
(`sudo systemctl stop voxip-kiosk-browser`).
|
(`sudo systemctl stop daynivo-kiosk-browser`).
|
||||||
|
|
||||||
## 5. Netwerk
|
## 5. Netwerk
|
||||||
|
|
||||||
@@ -123,11 +123,11 @@ Noteer per stap: ✅ / ❌ + opmerking, de imageversie en het schermtype.
|
|||||||
op Gitea: "beschikbaar". *Bijwerken naar …*: binnen enkele minuten is de
|
op Gitea: "beschikbaar". *Bijwerken naar …*: binnen enkele minuten is de
|
||||||
nieuwe versie actief, de beheerinterface komt terug, configuratie en
|
nieuwe versie actief, de beheerinterface komt terug, configuratie en
|
||||||
wachtwoord ongewijzigd.
|
wachtwoord ongewijzigd.
|
||||||
- [ ] *Automatisch bijwerken* aan, `sudo systemctl start voxip-kiosk-update.service`:
|
- [ ] *Automatisch bijwerken* aan, `sudo systemctl start daynivo-kiosk-update.service`:
|
||||||
de nieuwere release wordt geïnstalleerd. Met het vinkje uit: alleen gecontroleerd.
|
de nieuwere release wordt geïnstalleerd. Met het vinkje uit: alleen gecontroleerd.
|
||||||
- [ ] `curl -fsSL https://daynivo.nl/kiosk/install.sh | sudo bash` op een verse
|
- [ ] `curl -fsSL https://daynivo.nl/kiosk/install.sh | sudo bash` op een verse
|
||||||
Raspberry Pi OS Lite: installeert de nieuwste release, setupcode op het scherm.
|
Raspberry Pi OS Lite: installeert de nieuwste release, setupcode op het scherm.
|
||||||
- [ ] `sudo ./uninstall.sh --purge` op een testkaart: geen Daynivo-services of
|
- [ ] `sudo ./uninstall.sh --purge` op een testkaart: geen Daynivo-services of
|
||||||
-bestanden meer (`systemctl list-unit-files | grep voxip` is leeg).
|
-bestanden meer (`systemctl list-unit-files | grep daynivo` is leeg).
|
||||||
- [ ] Installatie op een bestaande Raspberry Pi OS Lite (Bookworm) met de
|
- [ ] Installatie op een bestaande Raspberry Pi OS Lite (Bookworm) met de
|
||||||
Daynivo-kiosk erop: URL overgenomen, `display-kiosk.service` uitgeschakeld.
|
Daynivo-kiosk erop: URL overgenomen, `display-kiosk.service` uitgeschakeld.
|
||||||
@@ -8,7 +8,7 @@ een fout; de reden staat dan in daynivo-config.error.txt).
|
|||||||
|
|
||||||
daynivo-config.json
|
daynivo-config.json
|
||||||
Instellingen voor deze kiosk. Zie daynivo-config.example.json. Toegestaan:
|
Instellingen voor deze kiosk. Zie daynivo-config.example.json. Toegestaan:
|
||||||
alle sleutels uit /etc/voxip-kiosk/config.json plus "hostname" en
|
alle sleutels uit /etc/daynivo-kiosk/config.json plus "hostname" en
|
||||||
"wifi_country". Voorbeeld:
|
"wifi_country". Voorbeeld:
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -20,7 +20,7 @@ daynivo-config.json
|
|||||||
|
|
||||||
daynivo-authorized_keys
|
daynivo-authorized_keys
|
||||||
Openbare SSH-sleutels (één per regel). SSH wordt dan ingeschakeld, alleen
|
Openbare SSH-sleutels (één per regel). SSH wordt dan ingeschakeld, alleen
|
||||||
met sleutel-login, voor de beheerder (voxipadmin of de gebruiker die je
|
met sleutel-login, voor de beheerder (daynivoadmin of de gebruiker die je
|
||||||
in Raspberry Pi Imager hebt aangemaakt).
|
in Raspberry Pi Imager hebt aangemaakt).
|
||||||
|
|
||||||
daynivo-network-reset
|
daynivo-network-reset
|
||||||
|
|||||||
+14
-13
@@ -8,8 +8,8 @@
|
|||||||
# Environment (all optional):
|
# Environment (all optional):
|
||||||
# PI_GEN_REF pi-gen tag/branch (32-bit armhf). Default: pinned Bookworm release.
|
# PI_GEN_REF pi-gen tag/branch (32-bit armhf). Default: pinned Bookworm release.
|
||||||
# RELEASE bookworm | trixie (must match PI_GEN_REF). Default: bookworm.
|
# RELEASE bookworm | trixie (must match PI_GEN_REF). Default: bookworm.
|
||||||
# VOXIP_DEFAULT_URL kiosk URL baked into the default config.
|
# DAYNIVO_DEFAULT_URL kiosk URL baked into the default config.
|
||||||
# VOXIP_DEVICE_NAME default device name.
|
# DAYNIVO_DEVICE_NAME default device name.
|
||||||
# TARGET_HOSTNAME default hostname (the admin UI is at http://<hostname>.local:8080).
|
# TARGET_HOSTNAME default hostname (the admin UI is at http://<hostname>.local:8080).
|
||||||
# ALLOW_DIRTY=1 build from the working tree instead of the committed HEAD.
|
# ALLOW_DIRTY=1 build from the working tree instead of the committed HEAD.
|
||||||
#
|
#
|
||||||
@@ -23,8 +23,9 @@ OUT="$ROOT/image/deploy"
|
|||||||
PI_GEN_REPO="${PI_GEN_REPO:-https://github.com/RPi-Distro/pi-gen.git}"
|
PI_GEN_REPO="${PI_GEN_REPO:-https://github.com/RPi-Distro/pi-gen.git}"
|
||||||
PI_GEN_REF="${PI_GEN_REF:-2024-11-19-raspios-bookworm-armhf}"
|
PI_GEN_REF="${PI_GEN_REF:-2024-11-19-raspios-bookworm-armhf}"
|
||||||
RELEASE="${RELEASE:-bookworm}"
|
RELEASE="${RELEASE:-bookworm}"
|
||||||
VOXIP_DEFAULT_URL="${VOXIP_DEFAULT_URL:-https://schermen-ijsselflat.voxip.nl}"
|
# VOXIP_* are the names from before the rename and still work.
|
||||||
VOXIP_DEVICE_NAME="${VOXIP_DEVICE_NAME:-Daynivo Kiosk}"
|
DAYNIVO_DEFAULT_URL="${DAYNIVO_DEFAULT_URL:-${VOXIP_DEFAULT_URL:-https://schermen-ijsselflat.voxip.nl}}"
|
||||||
|
DAYNIVO_DEVICE_NAME="${DAYNIVO_DEVICE_NAME:-${VOXIP_DEVICE_NAME:-Daynivo Kiosk}}"
|
||||||
TARGET_HOSTNAME="${TARGET_HOSTNAME:-kiosk}"
|
TARGET_HOSTNAME="${TARGET_HOSTNAME:-kiosk}"
|
||||||
NATIVE=0
|
NATIVE=0
|
||||||
[[ ${1:-} == "--native" ]] && NATIVE=1
|
[[ ${1:-} == "--native" ]] && NATIVE=1
|
||||||
@@ -45,13 +46,13 @@ git clone --quiet --depth 1 --branch "$PI_GEN_REF" "$PI_GEN_REPO" "$WORK/pi-gen"
|
|||||||
PI_GEN_COMMIT="$(git -C "$WORK/pi-gen" rev-parse HEAD)"
|
PI_GEN_COMMIT="$(git -C "$WORK/pi-gen" rev-parse HEAD)"
|
||||||
PIGEN="$WORK/pi-gen"
|
PIGEN="$WORK/pi-gen"
|
||||||
|
|
||||||
# Do not export the plain Lite image from stage2; ours is exported after stage-voxip.
|
# Do not export the plain Lite image from stage2; ours is exported after stage-daynivo.
|
||||||
touch "$PIGEN/stage2/SKIP_IMAGES"
|
touch "$PIGEN/stage2/SKIP_IMAGES"
|
||||||
rm -f "$PIGEN/stage2/EXPORT_NOOBS"
|
rm -f "$PIGEN/stage2/EXPORT_NOOBS"
|
||||||
|
|
||||||
echo "==> Daynivo-stage voorbereiden"
|
echo "==> Daynivo-stage voorbereiden"
|
||||||
cp -a "$ROOT/image/stage-voxip" "$PIGEN/stage-voxip"
|
cp -a "$ROOT/image/stage-daynivo" "$PIGEN/stage-daynivo"
|
||||||
PAYLOAD="$PIGEN/stage-voxip/00-voxip/files/voxip-kiosk"
|
PAYLOAD="$PIGEN/stage-daynivo/00-daynivo/files/daynivo-kiosk"
|
||||||
mkdir -p "$PAYLOAD"
|
mkdir -p "$PAYLOAD"
|
||||||
if [[ ${ALLOW_DIRTY:-0} == 1 ]] || ! git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then
|
if [[ ${ALLOW_DIRTY:-0} == 1 ]] || ! git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then
|
||||||
echo " (werkmap wordt gebruikt, niet de laatste commit)"
|
echo " (werkmap wordt gebruikt, niet de laatste commit)"
|
||||||
@@ -67,12 +68,12 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
BUILD_DATE="$(date -u +%Y-%m-%d)"
|
BUILD_DATE="$(date -u +%Y-%m-%d)"
|
||||||
cat > "$PIGEN/stage-voxip/00-voxip/files/build.env" <<EOF
|
cat > "$PIGEN/stage-daynivo/00-daynivo/files/build.env" <<EOF
|
||||||
VOXIP_DEFAULT_URL=$(printf %q "$VOXIP_DEFAULT_URL")
|
DAYNIVO_DEFAULT_URL=$(printf %q "$DAYNIVO_DEFAULT_URL")
|
||||||
VOXIP_DEVICE_NAME=$(printf %q "$VOXIP_DEVICE_NAME")
|
DAYNIVO_DEVICE_NAME=$(printf %q "$DAYNIVO_DEVICE_NAME")
|
||||||
EOF
|
EOF
|
||||||
cat > "$PAYLOAD/BUILD-INFO" <<EOF
|
cat > "$PAYLOAD/BUILD-INFO" <<EOF
|
||||||
voxip_kiosk_os=$VERSION
|
daynivo_kiosk_os=$VERSION
|
||||||
source_revision=$SOURCE_REV
|
source_revision=$SOURCE_REV
|
||||||
pi_gen_ref=$PI_GEN_REF
|
pi_gen_ref=$PI_GEN_REF
|
||||||
pi_gen_commit=$PI_GEN_COMMIT
|
pi_gen_commit=$PI_GEN_COMMIT
|
||||||
@@ -97,11 +98,11 @@ KEYBOARD_LAYOUT="English (US)"
|
|||||||
TIMEZONE_DEFAULT=Europe/Amsterdam
|
TIMEZONE_DEFAULT=Europe/Amsterdam
|
||||||
WPA_COUNTRY=NL
|
WPA_COUNTRY=NL
|
||||||
TARGET_HOSTNAME=$TARGET_HOSTNAME
|
TARGET_HOSTNAME=$TARGET_HOSTNAME
|
||||||
FIRST_USER_NAME=voxipadmin
|
FIRST_USER_NAME=daynivoadmin
|
||||||
FIRST_USER_PASS=$FIRST_USER_PASS
|
FIRST_USER_PASS=$FIRST_USER_PASS
|
||||||
DISABLE_FIRST_BOOT_USER_RENAME=1
|
DISABLE_FIRST_BOOT_USER_RENAME=1
|
||||||
ENABLE_SSH=0
|
ENABLE_SSH=0
|
||||||
STAGE_LIST="stage0 stage1 stage2 stage-voxip"
|
STAGE_LIST="stage0 stage1 stage2 stage-daynivo"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "==> Image bouwen (dit duurt 30–90 minuten)"
|
echo "==> Image bouwen (dit duurt 30–90 minuten)"
|
||||||
|
|||||||
Executable
+23
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
# Install Daynivo Kiosk OS into the image with the same install.sh that is
|
||||||
|
# used on existing Raspberry Pi OS installations.
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
source files/build.env
|
||||||
|
|
||||||
|
rm -rf "${ROOTFS_DIR}/usr/src/daynivo-kiosk"
|
||||||
|
install -d "${ROOTFS_DIR}/usr/src/daynivo-kiosk"
|
||||||
|
cp -a files/daynivo-kiosk/. "${ROOTFS_DIR}/usr/src/daynivo-kiosk/"
|
||||||
|
|
||||||
|
on_chroot << EOF_CHROOT
|
||||||
|
/usr/src/daynivo-kiosk/install.sh --image --url $(printf %q "${DAYNIVO_DEFAULT_URL}") --name $(printf %q "${DAYNIVO_DEVICE_NAME}")
|
||||||
|
install -m 0644 /usr/src/daynivo-kiosk/BUILD-INFO /usr/share/daynivo-kiosk/BUILD-INFO
|
||||||
|
# No usable default password: unlocked only by Raspberry Pi Imager credentials.
|
||||||
|
passwd -l ${FIRST_USER_NAME}
|
||||||
|
systemctl disable ssh.service 2>/dev/null || true
|
||||||
|
apt-get clean
|
||||||
|
EOF_CHROOT
|
||||||
|
|
||||||
|
# Instructions next to config.txt for whoever opens the boot partition.
|
||||||
|
install -m 0644 files/daynivo-kiosk/image/boot-README.txt "${ROOTFS_DIR}/boot/firmware/DAYNIVO-LEESMIJ.txt"
|
||||||
|
install -m 0644 files/daynivo-kiosk/image/daynivo-config.example.json "${ROOTFS_DIR}/boot/firmware/daynivo-config.example.json"
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,23 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
# Install Daynivo Kiosk OS into the image with the same install.sh that is
|
|
||||||
# used on existing Raspberry Pi OS installations.
|
|
||||||
|
|
||||||
# shellcheck disable=SC1091
|
|
||||||
source files/build.env
|
|
||||||
|
|
||||||
rm -rf "${ROOTFS_DIR}/usr/src/voxip-kiosk"
|
|
||||||
install -d "${ROOTFS_DIR}/usr/src/voxip-kiosk"
|
|
||||||
cp -a files/voxip-kiosk/. "${ROOTFS_DIR}/usr/src/voxip-kiosk/"
|
|
||||||
|
|
||||||
on_chroot << EOF_CHROOT
|
|
||||||
/usr/src/voxip-kiosk/install.sh --image --url $(printf %q "${VOXIP_DEFAULT_URL}") --name $(printf %q "${VOXIP_DEVICE_NAME}")
|
|
||||||
install -m 0644 /usr/src/voxip-kiosk/BUILD-INFO /usr/share/voxip-kiosk/BUILD-INFO
|
|
||||||
# No usable default password: unlocked only by Raspberry Pi Imager credentials.
|
|
||||||
passwd -l ${FIRST_USER_NAME}
|
|
||||||
systemctl disable ssh.service 2>/dev/null || true
|
|
||||||
apt-get clean
|
|
||||||
EOF_CHROOT
|
|
||||||
|
|
||||||
# Instructions next to config.txt for whoever opens the boot partition.
|
|
||||||
install -m 0644 files/voxip-kiosk/image/boot-README.txt "${ROOTFS_DIR}/boot/firmware/VOXIP-LEESMIJ.txt"
|
|
||||||
install -m 0644 files/voxip-kiosk/image/daynivo-config.example.json "${ROOTFS_DIR}/boot/firmware/daynivo-config.example.json"
|
|
||||||
+125
-56
@@ -8,9 +8,9 @@
|
|||||||
#
|
#
|
||||||
# sudo ./install.sh [--url https://…] [--name "Hal begane grond"] [--hostname hal-bg]
|
# sudo ./install.sh [--url https://…] [--name "Hal begane grond"] [--hostname hal-bg]
|
||||||
# sudo ./install.sh --upgrade # update code, keep configuration
|
# sudo ./install.sh --upgrade # update code, keep configuration
|
||||||
# ./install.sh --image … # used by image/stage-voxip (no service starts)
|
# ./install.sh --image … # used by image/stage-daynivo (no service starts)
|
||||||
#
|
#
|
||||||
# Existing configuration in /etc/voxip-kiosk is never overwritten.
|
# Existing configuration in /etc/daynivo-kiosk is never overwritten.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -21,15 +21,15 @@ NAME=""
|
|||||||
NEW_HOSTNAME=""
|
NEW_HOSTNAME=""
|
||||||
FORCE=0
|
FORCE=0
|
||||||
|
|
||||||
LIB=/usr/lib/voxip-kiosk
|
LIB=/usr/lib/daynivo-kiosk
|
||||||
SHARE=/usr/share/voxip-kiosk
|
SHARE=/usr/share/daynivo-kiosk
|
||||||
DOC=/usr/share/doc/voxip-kiosk
|
DOC=/usr/share/doc/daynivo-kiosk
|
||||||
ETC=/etc/voxip-kiosk
|
ETC=/etc/daynivo-kiosk
|
||||||
UNITS=(voxip-kiosk-x.service voxip-kiosk-browser.service voxip-kiosk-agent.service voxip-kiosk-manager.service
|
UNITS=(daynivo-kiosk-x.service daynivo-kiosk-browser.service daynivo-kiosk-agent.service daynivo-kiosk-manager.service
|
||||||
voxip-kiosk-healthcheck.service voxip-kiosk-healthcheck.timer voxip-network-guard.service voxip-boot-import.service
|
daynivo-kiosk-healthcheck.service daynivo-kiosk-healthcheck.timer daynivo-network-guard.service daynivo-boot-import.service
|
||||||
voxip-kiosk-update.service voxip-kiosk-update.timer)
|
daynivo-kiosk-update.service daynivo-kiosk-update.timer)
|
||||||
ENABLE=(voxip-kiosk-x.service voxip-kiosk-browser.service voxip-kiosk-agent.service voxip-kiosk-manager.service
|
ENABLE=(daynivo-kiosk-x.service daynivo-kiosk-browser.service daynivo-kiosk-agent.service daynivo-kiosk-manager.service
|
||||||
voxip-kiosk-healthcheck.timer voxip-network-guard.service voxip-boot-import.service voxip-kiosk-update.timer)
|
daynivo-kiosk-healthcheck.timer daynivo-network-guard.service daynivo-boot-import.service daynivo-kiosk-update.timer)
|
||||||
|
|
||||||
say() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
say() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
||||||
warn() { printf '\033[1;33mLet op:\033[0m %s\n' "$*" >&2; }
|
warn() { printf '\033[1;33mLet op:\033[0m %s\n' "$*" >&2; }
|
||||||
@@ -54,7 +54,7 @@ while [[ $# -gt 0 ]]; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
[[ $EUID -eq 0 ]] || die "Voer dit script uit met sudo."
|
[[ $EUID -eq 0 ]] || die "Voer dit script uit met sudo."
|
||||||
[[ -f "$SRC/src/voxip_kiosk/config.py" ]] || die "Start install.sh vanuit de Daynivo Kiosk OS-repository."
|
[[ -f "$SRC/src/daynivo_kiosk/config.py" ]] || die "Start install.sh vanuit de Daynivo Kiosk OS-repository."
|
||||||
|
|
||||||
in_chroot() {
|
in_chroot() {
|
||||||
if command -v systemd-detect-virt >/dev/null 2>&1 && systemd-detect-virt --chroot --quiet; then
|
if command -v systemd-detect-virt >/dev/null 2>&1 && systemd-detect-virt --chroot --quiet; then
|
||||||
@@ -106,6 +106,75 @@ pkg_available() { apt-cache policy "$1" 2>/dev/null | grep -q 'Candidate: [0-9]'
|
|||||||
apt-get install -y --no-install-recommends "${PKGS[@]}"
|
apt-get install -y --no-install-recommends "${PKGS[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- migration from the VoxIP names ---------------------------------------------------
|
||||||
|
# Kiosks installed before the rename (up to 1.2.x) use voxip-* services and folders
|
||||||
|
# and a "voxip" user. Move them over once, keeping the configuration, the password,
|
||||||
|
# the browser profile (offline cache) and the network settings. The old folder
|
||||||
|
# names stay as symlinks for whatever still runs from the old version, such as
|
||||||
|
# the updater that started this upgrade.
|
||||||
|
if [[ -d /etc/voxip-kiosk && ! -L /etc/voxip-kiosk && ! -e /etc/daynivo-kiosk ]]; then
|
||||||
|
say "Overstappen van de VoxIP-namen naar Daynivo"
|
||||||
|
if [[ $LIVE -eq 1 ]]; then
|
||||||
|
# Not voxip-kiosk-update.service: a nightly auto-update runs this very script in it.
|
||||||
|
systemctl stop voxip-kiosk-healthcheck.timer voxip-kiosk-update.timer voxip-kiosk-agent.service \
|
||||||
|
voxip-kiosk-browser.service voxip-kiosk-x.service voxip-kiosk-manager.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
for unit in voxip-kiosk-x.service voxip-kiosk-browser.service voxip-kiosk-agent.service voxip-kiosk-manager.service \
|
||||||
|
voxip-kiosk-healthcheck.service voxip-kiosk-healthcheck.timer voxip-kiosk-update.service \
|
||||||
|
voxip-kiosk-update.timer voxip-network-guard.service voxip-boot-import.service; do
|
||||||
|
systemctl disable "$unit" >/dev/null 2>&1 || true
|
||||||
|
rm -f "/etc/systemd/system/$unit"
|
||||||
|
done
|
||||||
|
if [[ $LIVE -eq 1 ]]; then systemctl daemon-reload; fi
|
||||||
|
|
||||||
|
for old in /etc/voxip-kiosk /var/lib/voxip-kiosk /var/lib/voxip-kiosk-network /var/lib/voxip-kiosk-browser \
|
||||||
|
/var/log/voxip-kiosk /var/cache/voxip-kiosk; do
|
||||||
|
new="${old/voxip/daynivo}"
|
||||||
|
if [[ -d $old && ! -L $old && ! -e $new ]]; then
|
||||||
|
mv "$old" "$new"
|
||||||
|
ln -s "$new" "$old"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Same uid and gid, so every file keeps the right owner.
|
||||||
|
if id voxip >/dev/null 2>&1 && ! id daynivo >/dev/null 2>&1; then
|
||||||
|
usermod -l daynivo -d /var/lib/daynivo-kiosk voxip
|
||||||
|
if getent group voxip >/dev/null; then groupmod -n daynivo voxip; fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Network profiles written by the web interface; not while a change awaits confirmation.
|
||||||
|
if [[ ! -f /var/lib/daynivo-kiosk-network/pending.json ]]; then
|
||||||
|
renamed=0
|
||||||
|
for iface in eth0 wlan0; do
|
||||||
|
old=/etc/NetworkManager/system-connections/voxip-$iface.nmconnection
|
||||||
|
new=/etc/NetworkManager/system-connections/daynivo-$iface.nmconnection
|
||||||
|
if [[ -f $old && ! -e $new ]]; then
|
||||||
|
sed -i "s/^id=voxip-$iface\$/id=daynivo-$iface/" "$old"
|
||||||
|
mv "$old" "$new"
|
||||||
|
chmod 0600 "$new"
|
||||||
|
renamed=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ $renamed -eq 1 && $LIVE -eq 1 ]]; then nmcli connection reload 2>/dev/null || true; fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f /etc/sudoers.d/voxip-kiosk /etc/systemd/journald.conf.d/voxip-kiosk.conf \
|
||||||
|
/etc/systemd/system.conf.d/voxip-watchdog.conf /etc/logrotate.d/voxip-kiosk \
|
||||||
|
/etc/avahi/services/voxip-kiosk.service /etc/chromium/policies/managed/voxip-kiosk.json \
|
||||||
|
/etc/chromium-browser/policies/managed/voxip-kiosk.json /usr/local/sbin/voxip-kiosk-ctl
|
||||||
|
if [[ -f /etc/ssh/sshd_config.d/voxip-kiosk.conf ]]; then
|
||||||
|
mv /etc/ssh/sshd_config.d/voxip-kiosk.conf /etc/ssh/sshd_config.d/daynivo-kiosk.conf
|
||||||
|
fi
|
||||||
|
if [[ -f /etc/X11/Xwrapper.config.voxip-orig ]]; then
|
||||||
|
mv /etc/X11/Xwrapper.config.voxip-orig /etc/X11/Xwrapper.config.daynivo-orig
|
||||||
|
fi
|
||||||
|
if [[ -f /etc/systemd/system/display-kiosk.service.voxip-disabled ]]; then
|
||||||
|
mv /etc/systemd/system/display-kiosk.service.voxip-disabled /etc/systemd/system/display-kiosk.service.daynivo-disabled
|
||||||
|
fi
|
||||||
|
# The old programs: an updater that started this install has its code loaded already.
|
||||||
|
rm -rf /usr/lib/voxip-kiosk /usr/share/voxip-kiosk /usr/share/doc/voxip-kiosk /usr/share/plymouth/themes/voxip-kiosk
|
||||||
|
fi
|
||||||
|
|
||||||
# --- users ----------------------------------------------------------------------
|
# --- users ----------------------------------------------------------------------
|
||||||
say "Gebruikers aanmaken"
|
say "Gebruikers aanmaken"
|
||||||
getent group kiosk >/dev/null || groupadd --system kiosk
|
getent group kiosk >/dev/null || groupadd --system kiosk
|
||||||
@@ -114,11 +183,11 @@ id kiosk >/dev/null 2>&1 || useradd --system --gid kiosk --home-dir /home/kiosk
|
|||||||
for g in video render input audio; do
|
for g in video render input audio; do
|
||||||
getent group "$g" >/dev/null && usermod -aG "$g" kiosk
|
getent group "$g" >/dev/null && usermod -aG "$g" kiosk
|
||||||
done
|
done
|
||||||
getent group voxip >/dev/null || groupadd --system voxip
|
getent group daynivo >/dev/null || groupadd --system daynivo
|
||||||
id voxip >/dev/null 2>&1 || useradd --system --gid voxip --home-dir /var/lib/voxip-kiosk --no-create-home \
|
id daynivo >/dev/null 2>&1 || useradd --system --gid daynivo --home-dir /var/lib/daynivo-kiosk --no-create-home \
|
||||||
--shell /usr/sbin/nologin --comment "Daynivo Kiosk Manager" voxip
|
--shell /usr/sbin/nologin --comment "Daynivo Kiosk Manager" daynivo
|
||||||
for g in systemd-journal video; do
|
for g in systemd-journal video; do
|
||||||
getent group "$g" >/dev/null && usermod -aG "$g" voxip
|
getent group "$g" >/dev/null && usermod -aG "$g" daynivo
|
||||||
done
|
done
|
||||||
|
|
||||||
# --- application files --------------------------------------------------------------
|
# --- application files --------------------------------------------------------------
|
||||||
@@ -126,7 +195,7 @@ say "Programmabestanden installeren"
|
|||||||
install -d -m 0755 "$LIB" "$SHARE" "$DOC"
|
install -d -m 0755 "$LIB" "$SHARE" "$DOC"
|
||||||
rm -rf "$LIB/python.new"
|
rm -rf "$LIB/python.new"
|
||||||
install -d -m 0755 "$LIB/python.new"
|
install -d -m 0755 "$LIB/python.new"
|
||||||
tar -C "$SRC/src" --exclude='__pycache__' --exclude='*.pyc' -cf - voxip_kiosk | tar -C "$LIB/python.new" -xf -
|
tar -C "$SRC/src" --exclude='__pycache__' --exclude='*.pyc' -cf - daynivo_kiosk | tar -C "$LIB/python.new" -xf -
|
||||||
chown -R root:root "$LIB/python.new"
|
chown -R root:root "$LIB/python.new"
|
||||||
chmod -R u=rwX,go=rX "$LIB/python.new"
|
chmod -R u=rwX,go=rX "$LIB/python.new"
|
||||||
python3 -m compileall -q "$LIB/python.new" >/dev/null
|
python3 -m compileall -q "$LIB/python.new" >/dev/null
|
||||||
@@ -135,7 +204,7 @@ rm -rf "$LIB/python.old"
|
|||||||
mv "$LIB/python.new" "$LIB/python"
|
mv "$LIB/python.new" "$LIB/python"
|
||||||
rm -rf "$LIB/python.old"
|
rm -rf "$LIB/python.old"
|
||||||
|
|
||||||
for bin in voxip-kiosk-agent voxip-kiosk-browser voxip-kiosk-healthcheck voxip-kiosk-helper voxip-kiosk-manager voxip-kiosk-updater voxip-kiosk-x; do
|
for bin in daynivo-kiosk-agent daynivo-kiosk-browser daynivo-kiosk-healthcheck daynivo-kiosk-helper daynivo-kiosk-manager daynivo-kiosk-updater daynivo-kiosk-x; do
|
||||||
install -m 0755 -o root -g root "$SRC/bin/$bin" "$LIB/$bin"
|
install -m 0755 -o root -g root "$SRC/bin/$bin" "$LIB/$bin"
|
||||||
done
|
done
|
||||||
install -m 0755 -o root -g root "$SRC/bin/daynivo-kiosk-ctl" /usr/local/sbin/daynivo-kiosk-ctl
|
install -m 0755 -o root -g root "$SRC/bin/daynivo-kiosk-ctl" /usr/local/sbin/daynivo-kiosk-ctl
|
||||||
@@ -151,10 +220,10 @@ install -m 0644 "$SRC"/docs/*.md "$DOC/"
|
|||||||
|
|
||||||
# --- configuration -------------------------------------------------------------------
|
# --- configuration -------------------------------------------------------------------
|
||||||
say "Configuratie"
|
say "Configuratie"
|
||||||
install -d -o voxip -g kiosk -m 2750 "$ETC"
|
install -d -o daynivo -g kiosk -m 2750 "$ETC"
|
||||||
install -d -o voxip -g voxip -m 0750 /var/lib/voxip-kiosk
|
install -d -o daynivo -g daynivo -m 0750 /var/lib/daynivo-kiosk
|
||||||
install -d -o root -g root -m 0755 /var/lib/voxip-kiosk-network
|
install -d -o root -g root -m 0755 /var/lib/daynivo-kiosk-network
|
||||||
install -d -o voxip -g voxip -m 0750 /var/log/voxip-kiosk
|
install -d -o daynivo -g daynivo -m 0750 /var/log/daynivo-kiosk
|
||||||
|
|
||||||
# Migrate from Daynivo's raspberry-pi/install-kiosk.sh: take over its URL, then disable it.
|
# Migrate from Daynivo's raspberry-pi/install-kiosk.sh: take over its URL, then disable it.
|
||||||
LEGACY_KIOSK_UNIT=/etc/systemd/system/display-kiosk.service
|
LEGACY_KIOSK_UNIT=/etc/systemd/system/display-kiosk.service
|
||||||
@@ -165,14 +234,14 @@ if [[ -f $LEGACY_KIOSK_UNIT ]]; then
|
|||||||
say "URL overgenomen van de Daynivo-kioskinstallatie"
|
say "URL overgenomen van de Daynivo-kioskinstallatie"
|
||||||
fi
|
fi
|
||||||
if [[ $LIVE -eq 1 ]]; then systemctl disable --now display-kiosk.service 2>/dev/null || true; fi
|
if [[ $LIVE -eq 1 ]]; then systemctl disable --now display-kiosk.service 2>/dev/null || true; fi
|
||||||
mv "$LEGACY_KIOSK_UNIT" "$LEGACY_KIOSK_UNIT.voxip-disabled"
|
mv "$LEGACY_KIOSK_UNIT" "$LEGACY_KIOSK_UNIT.daynivo-disabled"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PYRUN=(python3 -I -c)
|
PYRUN=(python3 -I -c)
|
||||||
"${PYRUN[@]}" '
|
"${PYRUN[@]}" '
|
||||||
import json, os, sys
|
import json, os, sys
|
||||||
sys.path.insert(0, "/usr/lib/voxip-kiosk/python")
|
sys.path.insert(0, "/usr/lib/daynivo-kiosk/python")
|
||||||
from voxip_kiosk import config as c
|
from daynivo_kiosk import config as c
|
||||||
path, default, url, name = sys.argv[1:5]
|
path, default, url, name = sys.argv[1:5]
|
||||||
updates = {}
|
updates = {}
|
||||||
if url: updates["url"] = url
|
if url: updates["url"] = url
|
||||||
@@ -194,36 +263,36 @@ else:
|
|||||||
c.atomic_write_json(c.Path(path), data)
|
c.atomic_write_json(c.Path(path), data)
|
||||||
print("Nieuwe configuratie aangemaakt")
|
print("Nieuwe configuratie aangemaakt")
|
||||||
' "$ETC/config.json" "$SRC/config/config.default.json" "$URL" "$NAME" || die "Ongeldige --url of --name."
|
' "$ETC/config.json" "$SRC/config/config.default.json" "$URL" "$NAME" || die "Ongeldige --url of --name."
|
||||||
chown voxip:kiosk "$ETC/config.json" "$ETC/config.json.bak" 2>/dev/null || true
|
chown daynivo:kiosk "$ETC/config.json" "$ETC/config.json.bak" 2>/dev/null || true
|
||||||
chmod 0640 "$ETC/config.json"
|
chmod 0640 "$ETC/config.json"
|
||||||
touch "$ETC/.config.lock" && chown voxip:kiosk "$ETC/.config.lock" && chmod 0640 "$ETC/.config.lock"
|
touch "$ETC/.config.lock" && chown daynivo:kiosk "$ETC/.config.lock" && chmod 0640 "$ETC/.config.lock"
|
||||||
[[ -f $ETC/admin.json ]] && chown voxip:voxip "$ETC/admin.json" && chmod 0600 "$ETC/admin.json"
|
[[ -f $ETC/admin.json ]] && chown daynivo:daynivo "$ETC/admin.json" && chmod 0600 "$ETC/admin.json"
|
||||||
|
|
||||||
# --- system integration ----------------------------------------------------------------
|
# --- system integration ----------------------------------------------------------------
|
||||||
say "Systeemintegratie"
|
say "Systeemintegratie"
|
||||||
TMP_SUDOERS="$(mktemp)"
|
TMP_SUDOERS="$(mktemp)"
|
||||||
install -m 0440 "$SRC/config/sudoers" "$TMP_SUDOERS"
|
install -m 0440 "$SRC/config/sudoers" "$TMP_SUDOERS"
|
||||||
visudo -cqf "$TMP_SUDOERS" || die "sudoers-bestand ongeldig"
|
visudo -cqf "$TMP_SUDOERS" || die "sudoers-bestand ongeldig"
|
||||||
mv "$TMP_SUDOERS" /etc/sudoers.d/voxip-kiosk
|
mv "$TMP_SUDOERS" /etc/sudoers.d/daynivo-kiosk
|
||||||
chown root:root /etc/sudoers.d/voxip-kiosk
|
chown root:root /etc/sudoers.d/daynivo-kiosk
|
||||||
|
|
||||||
install -D -m 0644 "$SRC/config/journald.conf" /etc/systemd/journald.conf.d/voxip-kiosk.conf
|
install -D -m 0644 "$SRC/config/journald.conf" /etc/systemd/journald.conf.d/daynivo-kiosk.conf
|
||||||
install -D -m 0644 "$SRC/config/watchdog.conf" /etc/systemd/system.conf.d/voxip-watchdog.conf
|
install -D -m 0644 "$SRC/config/watchdog.conf" /etc/systemd/system.conf.d/daynivo-watchdog.conf
|
||||||
install -D -m 0644 "$SRC/config/logrotate" /etc/logrotate.d/voxip-kiosk
|
install -D -m 0644 "$SRC/config/logrotate" /etc/logrotate.d/daynivo-kiosk
|
||||||
|
|
||||||
if [[ -f /etc/X11/Xwrapper.config && ! -f /etc/X11/Xwrapper.config.voxip-orig ]]; then
|
if [[ -f /etc/X11/Xwrapper.config && ! -f /etc/X11/Xwrapper.config.daynivo-orig ]]; then
|
||||||
cp -a /etc/X11/Xwrapper.config /etc/X11/Xwrapper.config.voxip-orig
|
cp -a /etc/X11/Xwrapper.config /etc/X11/Xwrapper.config.daynivo-orig
|
||||||
fi
|
fi
|
||||||
install -D -m 0644 "$SRC/config/Xwrapper.config" /etc/X11/Xwrapper.config
|
install -D -m 0644 "$SRC/config/Xwrapper.config" /etc/X11/Xwrapper.config
|
||||||
|
|
||||||
for dir in /etc/chromium/policies/managed /etc/chromium-browser/policies/managed; do
|
for dir in /etc/chromium/policies/managed /etc/chromium-browser/policies/managed; do
|
||||||
install -D -m 0644 "$SRC/config/chromium/voxip-kiosk.json" "$dir/voxip-kiosk.json"
|
install -D -m 0644 "$SRC/config/chromium/daynivo-kiosk.json" "$dir/daynivo-kiosk.json"
|
||||||
done
|
done
|
||||||
|
|
||||||
ADMIN_PORT="$(python3 -I -c 'import sys; sys.path.insert(0, "/usr/lib/voxip-kiosk/python"); from voxip_kiosk.config import load_config; print(load_config(__import__("pathlib").Path(sys.argv[1]))["admin_port"])' "$ETC/config.json")"
|
ADMIN_PORT="$(python3 -I -c 'import sys; sys.path.insert(0, "/usr/lib/daynivo-kiosk/python"); from daynivo_kiosk.config import load_config; print(load_config(__import__("pathlib").Path(sys.argv[1]))["admin_port"])' "$ETC/config.json")"
|
||||||
install -d -m 0755 /etc/avahi/services
|
install -d -m 0755 /etc/avahi/services
|
||||||
sed "s#<port>8080</port>#<port>${ADMIN_PORT}</port>#" "$SRC/config/avahi-voxip.service" > /etc/avahi/services/voxip-kiosk.service
|
sed "s#<port>8080</port>#<port>${ADMIN_PORT}</port>#" "$SRC/config/avahi-daynivo.service" > /etc/avahi/services/daynivo-kiosk.service
|
||||||
chmod 0644 /etc/avahi/services/voxip-kiosk.service
|
chmod 0644 /etc/avahi/services/daynivo-kiosk.service
|
||||||
|
|
||||||
# Swap: zram in RAM instead of a swap file on the SD card (Trixie's rpi-swap already does this).
|
# Swap: zram in RAM instead of a swap file on the SD card (Trixie's rpi-swap already does this).
|
||||||
if dpkg -s systemd-zram-generator >/dev/null 2>&1 && ! dpkg -s rpi-swap >/dev/null 2>&1; then
|
if dpkg -s systemd-zram-generator >/dev/null 2>&1 && ! dpkg -s rpi-swap >/dev/null 2>&1; then
|
||||||
@@ -263,18 +332,18 @@ done
|
|||||||
|
|
||||||
# Boot splash: logo on white (config/plymouth). Rebuilding the initramfs takes a while
|
# Boot splash: logo on white (config/plymouth). Rebuilding the initramfs takes a while
|
||||||
# on a Pi 3, so only when the theme changed.
|
# on a Pi 3, so only when the theme changed.
|
||||||
SPLASH_DIR=/usr/share/plymouth/themes/voxip-kiosk
|
SPLASH_DIR=/usr/share/plymouth/themes/daynivo-kiosk
|
||||||
install -d -m 0755 "$SPLASH_DIR"
|
install -d -m 0755 "$SPLASH_DIR"
|
||||||
install -m 0644 "$SRC"/config/plymouth/voxip-kiosk/* "$SPLASH_DIR/"
|
install -m 0644 "$SRC"/config/plymouth/daynivo-kiosk/* "$SPLASH_DIR/"
|
||||||
if [[ ! -f /var/lib/voxip-kiosk/previous-plymouth-theme ]]; then
|
if [[ ! -f /var/lib/daynivo-kiosk/previous-plymouth-theme ]]; then
|
||||||
plymouth-set-default-theme > /var/lib/voxip-kiosk/previous-plymouth-theme 2>/dev/null || true
|
plymouth-set-default-theme > /var/lib/daynivo-kiosk/previous-plymouth-theme 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
SPLASH_SUM="$(cat "$SPLASH_DIR"/* | sha256sum | cut -d' ' -f1)"
|
SPLASH_SUM="$(cat "$SPLASH_DIR"/* | sha256sum | cut -d' ' -f1)"
|
||||||
if [[ "$(plymouth-set-default-theme 2>/dev/null)" != voxip-kiosk || "$(cat /var/lib/voxip-kiosk/splash.sha256 2>/dev/null)" != "$SPLASH_SUM" ]]; then
|
if [[ "$(plymouth-set-default-theme 2>/dev/null)" != daynivo-kiosk || "$(cat /var/lib/daynivo-kiosk/splash.sha256 2>/dev/null)" != "$SPLASH_SUM" ]]; then
|
||||||
say "Opstartscherm instellen (initramfs bijwerken, dit duurt even)"
|
say "Opstartscherm instellen (initramfs bijwerken, dit duurt even)"
|
||||||
plymouth-set-default-theme voxip-kiosk
|
plymouth-set-default-theme daynivo-kiosk
|
||||||
if update-initramfs -u -k all >/dev/null 2>&1; then
|
if update-initramfs -u -k all >/dev/null 2>&1; then
|
||||||
echo "$SPLASH_SUM" > /var/lib/voxip-kiosk/splash.sha256
|
echo "$SPLASH_SUM" > /var/lib/daynivo-kiosk/splash.sha256
|
||||||
else
|
else
|
||||||
warn "initramfs bijwerken mislukt; het opstartscherm verschijnt mogelijk pas later tijdens het opstarten."
|
warn "initramfs bijwerken mislukt; het opstartscherm verschijnt mogelijk pas later tijdens het opstarten."
|
||||||
fi
|
fi
|
||||||
@@ -286,8 +355,8 @@ for dm in lightdm.service gdm3.service sddm.service; do
|
|||||||
if systemctl is-enabled --quiet "$dm" 2>/dev/null; then
|
if systemctl is-enabled --quiet "$dm" 2>/dev/null; then
|
||||||
warn "$dm wordt uitgeschakeld (de kiosk gebruikt een eigen minimale X-sessie)."
|
warn "$dm wordt uitgeschakeld (de kiosk gebruikt een eigen minimale X-sessie)."
|
||||||
systemctl disable "$dm" 2>/dev/null || true
|
systemctl disable "$dm" 2>/dev/null || true
|
||||||
grep -qx "$dm" /var/lib/voxip-kiosk/disabled-display-managers 2>/dev/null \
|
grep -qx "$dm" /var/lib/daynivo-kiosk/disabled-display-managers 2>/dev/null \
|
||||||
|| echo "$dm" >> /var/lib/voxip-kiosk/disabled-display-managers
|
|| echo "$dm" >> /var/lib/daynivo-kiosk/disabled-display-managers
|
||||||
fi
|
fi
|
||||||
if [[ $LIVE -eq 1 ]] && systemctl is-active --quiet "$dm" 2>/dev/null; then
|
if [[ $LIVE -eq 1 ]] && systemctl is-active --quiet "$dm" 2>/dev/null; then
|
||||||
warn "$dm wordt gestopt: de desktop op het scherm sluit nu af."
|
warn "$dm wordt gestopt: de desktop op het scherm sluit nu af."
|
||||||
@@ -302,15 +371,15 @@ for unit in "${UNITS[@]}"; do
|
|||||||
done
|
done
|
||||||
if [[ $LIVE -eq 1 ]]; then systemctl daemon-reload; fi
|
if [[ $LIVE -eq 1 ]]; then systemctl daemon-reload; fi
|
||||||
systemctl enable "${ENABLE[@]}" NetworkManager.service avahi-daemon.service >/dev/null
|
systemctl enable "${ENABLE[@]}" NetworkManager.service avahi-daemon.service >/dev/null
|
||||||
if [[ ! -f /var/lib/voxip-kiosk/previous-default-target ]]; then
|
if [[ ! -f /var/lib/daynivo-kiosk/previous-default-target ]]; then
|
||||||
systemctl get-default > /var/lib/voxip-kiosk/previous-default-target 2>/dev/null || true
|
systemctl get-default > /var/lib/daynivo-kiosk/previous-default-target 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
systemctl set-default multi-user.target >/dev/null
|
systemctl set-default multi-user.target >/dev/null
|
||||||
|
|
||||||
if [[ -n $NEW_HOSTNAME && $LIVE -eq 0 ]]; then
|
if [[ -n $NEW_HOSTNAME && $LIVE -eq 0 ]]; then
|
||||||
warn "--hostname wordt genegeerd in image-modus (gebruik TARGET_HOSTNAME van pi-gen)."
|
warn "--hostname wordt genegeerd in image-modus (gebruik TARGET_HOSTNAME van pi-gen)."
|
||||||
elif [[ -n $NEW_HOSTNAME ]]; then
|
elif [[ -n $NEW_HOSTNAME ]]; then
|
||||||
"$LIB/voxip-kiosk-helper" set-hostname "$NEW_HOSTNAME" >/dev/null || die "Ongeldige hostname: $NEW_HOSTNAME"
|
"$LIB/daynivo-kiosk-helper" set-hostname "$NEW_HOSTNAME" >/dev/null || die "Ongeldige hostname: $NEW_HOSTNAME"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $LIVE -eq 0 ]]; then
|
if [[ $LIVE -eq 0 ]]; then
|
||||||
@@ -321,11 +390,11 @@ fi
|
|||||||
say "Services starten"
|
say "Services starten"
|
||||||
systemctl restart systemd-journald.service || true
|
systemctl restart systemd-journald.service || true
|
||||||
systemctl restart avahi-daemon.service || true
|
systemctl restart avahi-daemon.service || true
|
||||||
systemctl restart voxip-kiosk-manager.service voxip-kiosk-agent.service
|
systemctl restart daynivo-kiosk-manager.service daynivo-kiosk-agent.service
|
||||||
systemctl start voxip-kiosk-healthcheck.timer voxip-kiosk-update.timer
|
systemctl start daynivo-kiosk-healthcheck.timer daynivo-kiosk-update.timer
|
||||||
systemctl reset-failed voxip-kiosk-x.service voxip-kiosk-browser.service 2>/dev/null || true
|
systemctl reset-failed daynivo-kiosk-x.service daynivo-kiosk-browser.service 2>/dev/null || true
|
||||||
systemctl restart voxip-kiosk-x.service
|
systemctl restart daynivo-kiosk-x.service
|
||||||
systemctl restart voxip-kiosk-browser.service
|
systemctl restart daynivo-kiosk-browser.service
|
||||||
|
|
||||||
HOST="$(hostname)"
|
HOST="$(hostname)"
|
||||||
SCHEME=http
|
SCHEME=http
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "voxip-kiosk"
|
name = "daynivo-kiosk"
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
description = "Daynivo Kiosk OS — kiosk runtime and Daynivo Kiosk Manager"
|
description = "Daynivo Kiosk OS — kiosk runtime and Daynivo Kiosk Manager"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|||||||
File renamed without changes.
@@ -1,4 +1,4 @@
|
|||||||
"""voxip-kiosk-agent — keeps the kiosk page where it should be.
|
"""daynivo-kiosk-agent — keeps the kiosk page where it should be.
|
||||||
|
|
||||||
Runs as user ``kiosk`` and steers Chromium through the DevTools Protocol on
|
Runs as user ``kiosk`` and steers Chromium through the DevTools Protocol on
|
||||||
127.0.0.1:
|
127.0.0.1:
|
||||||
@@ -33,7 +33,7 @@ from .config import admin_url, load_config
|
|||||||
from .paths import Paths, load_paths
|
from .paths import Paths, load_paths
|
||||||
from .validation import mask_url
|
from .validation import mask_url
|
||||||
|
|
||||||
log = logging.getLogger("voxip-kiosk-agent")
|
log = logging.getLogger("daynivo-kiosk-agent")
|
||||||
|
|
||||||
TICK_SECONDS = 5
|
TICK_SECONDS = 5
|
||||||
PROBE_MAX_AGE_LOADING = 10
|
PROBE_MAX_AGE_LOADING = 10
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
"""voxip-kiosk-browser — prepares the display and runs Chromium.
|
"""daynivo-kiosk-browser — prepares the display and runs Chromium.
|
||||||
|
|
||||||
Started by ``voxip-kiosk-browser.service`` as user ``kiosk`` once the X
|
Started by ``daynivo-kiosk-browser.service`` as user ``kiosk`` once the X
|
||||||
server is up. Exit status tells systemd whether to restart: 1 when
|
server is up. Exit status tells systemd whether to restart: 1 when
|
||||||
``browser_restart`` is enabled (``Restart=on-failure`` restarts it and the
|
``browser_restart`` is enabled (``Restart=on-failure`` restarts it and the
|
||||||
start limit catches crash loops), 0 when it is disabled.
|
start limit catches crash loops), 0 when it is disabled.
|
||||||
@@ -25,7 +25,7 @@ from .config import admin_url, load_config
|
|||||||
from .paths import Paths, load_paths
|
from .paths import Paths, load_paths
|
||||||
from .validation import mask_url, parse_resolution
|
from .validation import mask_url, parse_resolution
|
||||||
|
|
||||||
log = logging.getLogger("voxip-kiosk-browser")
|
log = logging.getLogger("daynivo-kiosk-browser")
|
||||||
|
|
||||||
CDP_PORT = 9222
|
CDP_PORT = 9222
|
||||||
CHROMIUM_CANDIDATES = ("/usr/bin/chromium-browser", "/usr/bin/chromium")
|
CHROMIUM_CANDIDATES = ("/usr/bin/chromium-browser", "/usr/bin/chromium")
|
||||||
@@ -212,14 +212,14 @@ def clean_profile(profile_dir: Path) -> None:
|
|||||||
profile = data.setdefault("profile", {})
|
profile = data.setdefault("profile", {})
|
||||||
profile["exit_type"] = "Normal"
|
profile["exit_type"] = "Normal"
|
||||||
profile["exited_cleanly"] = True
|
profile["exited_cleanly"] = True
|
||||||
tmp = prefs.with_suffix(".voxip-tmp")
|
tmp = prefs.with_suffix(".daynivo-tmp")
|
||||||
tmp.write_text(json.dumps(data), encoding="utf-8")
|
tmp.write_text(json.dumps(data), encoding="utf-8")
|
||||||
os.replace(tmp, prefs)
|
os.replace(tmp, prefs)
|
||||||
|
|
||||||
|
|
||||||
def profile_dirs(config: dict[str, Any]) -> tuple[Path, Path]:
|
def profile_dirs(config: dict[str, Any]) -> tuple[Path, Path]:
|
||||||
runtime = Path(os.environ.get("RUNTIME_DIRECTORY", "/run/voxip-kiosk-browser"))
|
runtime = Path(os.environ.get("RUNTIME_DIRECTORY", "/run/daynivo-kiosk-browser"))
|
||||||
state = Path(os.environ.get("STATE_DIRECTORY", "/var/lib/voxip-kiosk-browser"))
|
state = Path(os.environ.get("STATE_DIRECTORY", "/var/lib/daynivo-kiosk-browser"))
|
||||||
profile = state / "profile" if config.get("browser_profile") == "persistent" else runtime / "profile"
|
profile = state / "profile" if config.get("browser_profile") == "persistent" else runtime / "profile"
|
||||||
if config.get("browser_profile") != "persistent" and (state / "profile").exists():
|
if config.get("browser_profile") != "persistent" and (state / "profile").exists():
|
||||||
shutil.rmtree(state / "profile", ignore_errors=True)
|
shutil.rmtree(state / "profile", ignore_errors=True)
|
||||||
File renamed without changes.
@@ -236,7 +236,7 @@ def save_config(path: Path, updates: dict[str, Any]) -> dict[str, Any]:
|
|||||||
lock_path = path.with_name(".config.lock")
|
lock_path = path.with_name(".config.lock")
|
||||||
with _thread_lock:
|
with _thread_lock:
|
||||||
# Read-only is enough for flock and works for every writer (the web
|
# Read-only is enough for flock and works for every writer (the web
|
||||||
# interface as voxip, the helper as root), whoever created the file.
|
# interface as daynivo, the helper as root), whoever created the file.
|
||||||
lock_fd = os.open(str(lock_path), os.O_RDONLY | os.O_CREAT, 0o640)
|
lock_fd = os.open(str(lock_path), os.O_RDONLY | os.O_CREAT, 0o640)
|
||||||
try:
|
try:
|
||||||
fcntl.flock(lock_fd, fcntl.LOCK_EX)
|
fcntl.flock(lock_fd, fcntl.LOCK_EX)
|
||||||
@@ -48,7 +48,7 @@ def cmd_setup_code(_args) -> int:
|
|||||||
return 1
|
return 1
|
||||||
code = setupcode.read(paths.setup_code_file)
|
code = setupcode.read(paths.setup_code_file)
|
||||||
if not code:
|
if not code:
|
||||||
print("Nog geen setupcode; start de beheerinterface: sudo systemctl restart voxip-kiosk-manager")
|
print("Nog geen setupcode; start de beheerinterface: sudo systemctl restart daynivo-kiosk-manager")
|
||||||
return 1
|
return 1
|
||||||
print(code)
|
print(code)
|
||||||
return 0
|
return 0
|
||||||
@@ -65,10 +65,10 @@ def cmd_reset_password(args) -> int:
|
|||||||
code = setupcode.generate()
|
code = setupcode.generate()
|
||||||
setupcode.write(paths.setup_code_file, code)
|
setupcode.write(paths.setup_code_file, code)
|
||||||
try:
|
try:
|
||||||
os.chown(paths.setup_code_file, pwd.getpwnam("voxip").pw_uid, grp.getgrnam("kiosk").gr_gid)
|
os.chown(paths.setup_code_file, pwd.getpwnam("daynivo").pw_uid, grp.getgrnam("kiosk").gr_gid)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
subprocess.run(["systemctl", "restart", "voxip-kiosk-manager.service"], check=False)
|
subprocess.run(["systemctl", "restart", "daynivo-kiosk-manager.service"], check=False)
|
||||||
print(f"Wachtwoord verwijderd. Nieuwe setupcode: {code}")
|
print(f"Wachtwoord verwijderd. Nieuwe setupcode: {code}")
|
||||||
print("Open de beheerinterface en stel een nieuw wachtwoord in; de code staat ook op het kioskscherm.")
|
print("Open de beheerinterface en stel een nieuw wachtwoord in; de code staat ook op het kioskscherm.")
|
||||||
return 0
|
return 0
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
"""voxip-kiosk-healthcheck — runs every minute (timer) as root.
|
"""daynivo-kiosk-healthcheck — runs every minute (timer) as root.
|
||||||
|
|
||||||
Keeps every kiosk service alive without hiding problems: each recovery is
|
Keeps every kiosk service alive without hiding problems: each recovery is
|
||||||
logged, and a crash loop that hit systemd's start limit is retried only
|
logged, and a crash loop that hit systemd's start limit is retried only
|
||||||
@@ -21,7 +21,7 @@ from .cdp import CDP, CDPError
|
|||||||
from .config import load_config
|
from .config import load_config
|
||||||
from .paths import Paths, load_paths
|
from .paths import Paths, load_paths
|
||||||
|
|
||||||
log = logging.getLogger("voxip-kiosk-healthcheck")
|
log = logging.getLogger("daynivo-kiosk-healthcheck")
|
||||||
|
|
||||||
ALWAYS_ON = (services.AGENT_UNIT, services.MANAGER_UNIT)
|
ALWAYS_ON = (services.AGENT_UNIT, services.MANAGER_UNIT)
|
||||||
DISPLAY_UNITS = (services.X_UNIT, services.BROWSER_UNIT)
|
DISPLAY_UNITS = (services.X_UNIT, services.BROWSER_UNIT)
|
||||||
@@ -147,7 +147,7 @@ class HealthCheck:
|
|||||||
|
|
||||||
|
|
||||||
def main(argv: list[str] | None = None) -> int:
|
def main(argv: list[str] | None = None) -> int:
|
||||||
parser = argparse.ArgumentParser(prog="voxip-kiosk-healthcheck")
|
parser = argparse.ArgumentParser(prog="daynivo-kiosk-healthcheck")
|
||||||
parser.add_argument("--check-only", action="store_true", help="alleen rapporteren, niets herstellen")
|
parser.add_argument("--check-only", action="store_true", help="alleen rapporteren, niets herstellen")
|
||||||
parser.add_argument("--json", action="store_true", help="rapport als JSON")
|
parser.add_argument("--json", action="store_true", help="rapport als JSON")
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
"""voxip-kiosk-helper — the only privileged entry point of Daynivo Kiosk OS.
|
"""daynivo-kiosk-helper — the only privileged entry point of Daynivo Kiosk OS.
|
||||||
|
|
||||||
Runs as root, either through ``sudo -n`` from the web interface (user
|
Runs as root, either through ``sudo -n`` from the web interface (user
|
||||||
``voxip``) or from systemd units. It accepts a fixed set of verbs, validates
|
``daynivo``) or from systemd units. It accepts a fixed set of verbs, validates
|
||||||
every argument itself, never invokes a shell and prints a single JSON
|
every argument itself, never invokes a shell and prints a single JSON
|
||||||
object on stdout.
|
object on stdout.
|
||||||
|
|
||||||
Usage: voxip-kiosk-helper <verb> [args] (network-apply reads JSON on stdin)
|
Usage: daynivo-kiosk-helper <verb> [args] (network-apply reads JSON on stdin)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -27,13 +27,13 @@ from . import netconfig, updater
|
|||||||
from . import validation as v
|
from . import validation as v
|
||||||
from .paths import Paths, default_paths
|
from .paths import Paths, default_paths
|
||||||
|
|
||||||
HELPER_PATH = "/usr/lib/voxip-kiosk/voxip-kiosk-helper"
|
HELPER_PATH = "/usr/lib/daynivo-kiosk/daynivo-kiosk-helper"
|
||||||
ROLLBACK_UNIT = "voxip-network-rollback"
|
ROLLBACK_UNIT = "daynivo-network-rollback"
|
||||||
UPDATE_UNIT = "voxip-kiosk-update-now"
|
UPDATE_UNIT = "daynivo-kiosk-update-now"
|
||||||
UPDATER_PATH = "/usr/lib/voxip-kiosk/voxip-kiosk-updater"
|
UPDATER_PATH = "/usr/lib/daynivo-kiosk/daynivo-kiosk-updater"
|
||||||
ACTIVATE_UNIT = "voxip-network-activate"
|
ACTIVATE_UNIT = "daynivo-network-activate"
|
||||||
BOOT_DIRS = (Path("/boot/firmware"), Path("/boot"))
|
BOOT_DIRS = (Path("/boot/firmware"), Path("/boot"))
|
||||||
# Files on the boot partition. The voxip-* names are from before the rename to
|
# Files on the boot partition. The daynivo-* names are from before the rename to
|
||||||
# Daynivo and keep working, so existing SD cards and instructions stay valid.
|
# Daynivo and keep working, so existing SD cards and instructions stay valid.
|
||||||
RESET_TRIGGERS = ("daynivo-network-reset", "voxip-network-reset")
|
RESET_TRIGGERS = ("daynivo-network-reset", "voxip-network-reset")
|
||||||
IMPORT_CONFIGS = ("voxip-config.json", "daynivo-config.json") # applied in this order: the Daynivo name wins
|
IMPORT_CONFIGS = ("voxip-config.json", "daynivo-config.json") # applied in this order: the Daynivo name wins
|
||||||
@@ -83,24 +83,24 @@ class Helper:
|
|||||||
# -- power & browser -------------------------------------------------
|
# -- power & browser -------------------------------------------------
|
||||||
|
|
||||||
def reboot(self) -> dict[str, Any]:
|
def reboot(self) -> dict[str, Any]:
|
||||||
self.run(["systemd-run", "--on-active=3", "--unit=voxip-power-reboot", "/bin/systemctl", "reboot"])
|
self.run(["systemd-run", "--on-active=3", "--unit=daynivo-power-reboot", "/bin/systemctl", "reboot"])
|
||||||
log(syslog.LOG_NOTICE, "Herstart aangevraagd via beheerinterface")
|
log(syslog.LOG_NOTICE, "Herstart aangevraagd via beheerinterface")
|
||||||
return {"message": "De Raspberry Pi wordt over enkele seconden herstart."}
|
return {"message": "De Raspberry Pi wordt over enkele seconden herstart."}
|
||||||
|
|
||||||
def poweroff(self) -> dict[str, Any]:
|
def poweroff(self) -> dict[str, Any]:
|
||||||
self.run(["systemd-run", "--on-active=3", "--unit=voxip-power-off", "/bin/systemctl", "poweroff"])
|
self.run(["systemd-run", "--on-active=3", "--unit=daynivo-power-off", "/bin/systemctl", "poweroff"])
|
||||||
log(syslog.LOG_NOTICE, "Uitschakelen aangevraagd via beheerinterface")
|
log(syslog.LOG_NOTICE, "Uitschakelen aangevraagd via beheerinterface")
|
||||||
return {"message": "De Raspberry Pi wordt over enkele seconden uitgeschakeld."}
|
return {"message": "De Raspberry Pi wordt over enkele seconden uitgeschakeld."}
|
||||||
|
|
||||||
def restart_browser(self) -> dict[str, Any]:
|
def restart_browser(self) -> dict[str, Any]:
|
||||||
self.run(["systemctl", "reset-failed", "voxip-kiosk-browser.service", "voxip-kiosk-x.service"], check=False)
|
self.run(["systemctl", "reset-failed", "daynivo-kiosk-browser.service", "daynivo-kiosk-x.service"], check=False)
|
||||||
self.run(["systemctl", "restart", "--no-block", "voxip-kiosk-browser.service"])
|
self.run(["systemctl", "restart", "--no-block", "daynivo-kiosk-browser.service"])
|
||||||
log(syslog.LOG_NOTICE, "Chromium wordt herstart")
|
log(syslog.LOG_NOTICE, "Chromium wordt herstart")
|
||||||
return {"message": "Chromium wordt herstart."}
|
return {"message": "Chromium wordt herstart."}
|
||||||
|
|
||||||
def restart_manager(self) -> dict[str, Any]:
|
def restart_manager(self) -> dict[str, Any]:
|
||||||
# Delayed so the web interface can still answer the request that asked for it.
|
# Delayed so the web interface can still answer the request that asked for it.
|
||||||
self.run(["systemd-run", "--on-active=2", "--unit=voxip-manager-restart", "/bin/systemctl", "restart", "voxip-kiosk-manager.service"])
|
self.run(["systemd-run", "--on-active=2", "--unit=daynivo-manager-restart", "/bin/systemctl", "restart", "daynivo-kiosk-manager.service"])
|
||||||
log(syslog.LOG_NOTICE, "Beheerinterface wordt herstart")
|
log(syslog.LOG_NOTICE, "Beheerinterface wordt herstart")
|
||||||
return {"message": "De beheerinterface wordt herstart."}
|
return {"message": "De beheerinterface wordt herstart."}
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ class Helper:
|
|||||||
|
|
||||||
def _chown_config(self, path: Path) -> None:
|
def _chown_config(self, path: Path) -> None:
|
||||||
try:
|
try:
|
||||||
uid = pwd.getpwnam("voxip").pw_uid
|
uid = pwd.getpwnam("daynivo").pw_uid
|
||||||
gid = grp.getgrnam("kiosk").gr_gid
|
gid = grp.getgrnam("kiosk").gr_gid
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
@@ -392,7 +392,7 @@ class Helper:
|
|||||||
os.chown(ssh_dir, user.pw_uid, user.pw_gid)
|
os.chown(ssh_dir, user.pw_uid, user.pw_gid)
|
||||||
sshd_dir = self.etc / "ssh" / "sshd_config.d"
|
sshd_dir = self.etc / "ssh" / "sshd_config.d"
|
||||||
sshd_dir.mkdir(parents=True, exist_ok=True)
|
sshd_dir.mkdir(parents=True, exist_ok=True)
|
||||||
(sshd_dir / "voxip-kiosk.conf").write_text(
|
(sshd_dir / "daynivo-kiosk.conf").write_text(
|
||||||
"# Beheerd door Daynivo Kiosk OS: alleen inloggen met SSH-sleutels.\n"
|
"# Beheerd door Daynivo Kiosk OS: alleen inloggen met SSH-sleutels.\n"
|
||||||
"PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin no\n",
|
"PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin no\n",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
@@ -449,9 +449,9 @@ def _parse_json(text: str) -> Any:
|
|||||||
def main(argv: list[str] | None = None, helper: Helper | None = None, environ: dict[str, str] | None = None) -> int:
|
def main(argv: list[str] | None = None, helper: Helper | None = None, environ: dict[str, str] | None = None) -> int:
|
||||||
argv = sys.argv[1:] if argv is None else argv
|
argv = sys.argv[1:] if argv is None else argv
|
||||||
environ = os.environ if environ is None else environ
|
environ = os.environ if environ is None else environ
|
||||||
syslog.openlog("voxip-kiosk-helper", 0, syslog.LOG_DAEMON)
|
syslog.openlog("daynivo-kiosk-helper", 0, syslog.LOG_DAEMON)
|
||||||
if not argv:
|
if not argv:
|
||||||
print(json.dumps({"ok": False, "error": "Gebruik: voxip-kiosk-helper <opdracht> [argumenten]"}))
|
print(json.dumps({"ok": False, "error": "Gebruik: daynivo-kiosk-helper <opdracht> [argumenten]"}))
|
||||||
return 2
|
return 2
|
||||||
verb, args = argv[0], argv[1:]
|
verb, args = argv[0], argv[1:]
|
||||||
caller = environ.get("SUDO_USER")
|
caller = environ.get("SUDO_USER")
|
||||||
@@ -460,7 +460,7 @@ def main(argv: list[str] | None = None, helper: Helper | None = None, environ: d
|
|||||||
print(json.dumps({"ok": False, "error": "Opdracht niet toegestaan"}))
|
print(json.dumps({"ok": False, "error": "Opdracht niet toegestaan"}))
|
||||||
return 1
|
return 1
|
||||||
if helper is None and os.geteuid() != 0:
|
if helper is None and os.geteuid() != 0:
|
||||||
print(json.dumps({"ok": False, "error": "voxip-kiosk-helper moet als root draaien"}))
|
print(json.dumps({"ok": False, "error": "daynivo-kiosk-helper moet als root draaien"}))
|
||||||
return 1
|
return 1
|
||||||
helper = helper or Helper()
|
helper = helper or Helper()
|
||||||
stdin = sys.stdin.read(16385) if verb == "network-apply" else ""
|
stdin = sys.stdin.read(16385) if verb == "network-apply" else ""
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
|||||||
"""voxip-kiosk-manager — starts the web interface under gunicorn.
|
"""daynivo-kiosk-manager — starts the web interface under gunicorn.
|
||||||
|
|
||||||
Reads port and HTTPS settings from the kiosk configuration, creates a
|
Reads port and HTTPS settings from the kiosk configuration, creates a
|
||||||
self-signed certificate when HTTPS is enabled and none exists yet, then
|
self-signed certificate when HTTPS is enabled and none exists yet, then
|
||||||
@@ -19,8 +19,8 @@ from . import logutil
|
|||||||
from .config import load_config
|
from .config import load_config
|
||||||
from .paths import Paths, load_paths
|
from .paths import Paths, load_paths
|
||||||
|
|
||||||
log = logging.getLogger("voxip-kiosk-manager")
|
log = logging.getLogger("daynivo-kiosk-manager")
|
||||||
PYTHON_LIB = "/usr/lib/voxip-kiosk/python"
|
PYTHON_LIB = "/usr/lib/daynivo-kiosk/python"
|
||||||
|
|
||||||
|
|
||||||
def ensure_certificate(paths: Paths) -> tuple[Path, Path]:
|
def ensure_certificate(paths: Paths) -> tuple[Path, Path]:
|
||||||
@@ -55,7 +55,7 @@ def gunicorn_argv(paths: Paths, config: dict) -> list[str]:
|
|||||||
if config["admin_https"]:
|
if config["admin_https"]:
|
||||||
cert, key = ensure_certificate(paths)
|
cert, key = ensure_certificate(paths)
|
||||||
argv += ["--certfile", str(cert), "--keyfile", str(key)]
|
argv += ["--certfile", str(cert), "--keyfile", str(key)]
|
||||||
argv.append("voxip_kiosk.web:create_app()")
|
argv.append("daynivo_kiosk.web:create_app()")
|
||||||
return argv
|
return argv
|
||||||
|
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ from typing import Any
|
|||||||
from . import validation as v
|
from . import validation as v
|
||||||
|
|
||||||
INTERFACES = {"eth0": "ethernet", "wlan0": "wifi"}
|
INTERFACES = {"eth0": "ethernet", "wlan0": "wifi"}
|
||||||
PROFILE_PREFIX = "voxip-"
|
PROFILE_PREFIX = "daynivo-"
|
||||||
ROLLBACK_SECONDS = 180
|
ROLLBACK_SECONDS = 180
|
||||||
|
|
||||||
|
|
||||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
|||||||
"""Filesystem locations used by every Daynivo Kiosk component.
|
"""Filesystem locations used by every Daynivo Kiosk component.
|
||||||
|
|
||||||
The defaults match the installed layout. Unprivileged components may
|
The defaults match the installed layout. Unprivileged components may
|
||||||
override them through ``VOXIP_*`` environment variables (used by the test
|
override them through ``DAYNIVO_*`` environment variables (used by the test
|
||||||
suite and for local development). The root helper always uses
|
suite and for local development). The root helper always uses
|
||||||
:func:`default_paths` and never reads the environment.
|
:func:`default_paths` and never reads the environment.
|
||||||
"""
|
"""
|
||||||
@@ -15,15 +15,15 @@ from pathlib import Path
|
|||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Paths:
|
class Paths:
|
||||||
config_dir: Path = Path("/etc/voxip-kiosk")
|
config_dir: Path = Path("/etc/daynivo-kiosk")
|
||||||
state_dir: Path = Path("/var/lib/voxip-kiosk")
|
state_dir: Path = Path("/var/lib/daynivo-kiosk")
|
||||||
network_state_dir: Path = Path("/var/lib/voxip-kiosk-network")
|
network_state_dir: Path = Path("/var/lib/daynivo-kiosk-network")
|
||||||
agent_run_dir: Path = Path("/run/voxip-kiosk-agent")
|
agent_run_dir: Path = Path("/run/daynivo-kiosk-agent")
|
||||||
browser_run_dir: Path = Path("/run/voxip-kiosk-browser")
|
browser_run_dir: Path = Path("/run/daynivo-kiosk-browser")
|
||||||
health_run_dir: Path = Path("/run/voxip-kiosk-health")
|
health_run_dir: Path = Path("/run/daynivo-kiosk-health")
|
||||||
share_dir: Path = Path("/usr/share/voxip-kiosk")
|
share_dir: Path = Path("/usr/share/daynivo-kiosk")
|
||||||
log_dir: Path = Path("/var/log/voxip-kiosk")
|
log_dir: Path = Path("/var/log/daynivo-kiosk")
|
||||||
helper: Path = Path("/usr/lib/voxip-kiosk/voxip-kiosk-helper")
|
helper: Path = Path("/usr/lib/daynivo-kiosk/daynivo-kiosk-helper")
|
||||||
nm_connections_dir: Path = Path("/etc/NetworkManager/system-connections")
|
nm_connections_dir: Path = Path("/etc/NetworkManager/system-connections")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -90,15 +90,15 @@ def default_paths() -> Paths:
|
|||||||
|
|
||||||
|
|
||||||
_ENV = {
|
_ENV = {
|
||||||
"config_dir": "VOXIP_CONFIG_DIR",
|
"config_dir": "DAYNIVO_CONFIG_DIR",
|
||||||
"state_dir": "VOXIP_STATE_DIR",
|
"state_dir": "DAYNIVO_STATE_DIR",
|
||||||
"network_state_dir": "VOXIP_NETWORK_STATE_DIR",
|
"network_state_dir": "DAYNIVO_NETWORK_STATE_DIR",
|
||||||
"agent_run_dir": "VOXIP_AGENT_RUN_DIR",
|
"agent_run_dir": "DAYNIVO_AGENT_RUN_DIR",
|
||||||
"browser_run_dir": "VOXIP_BROWSER_RUN_DIR",
|
"browser_run_dir": "DAYNIVO_BROWSER_RUN_DIR",
|
||||||
"health_run_dir": "VOXIP_HEALTH_RUN_DIR",
|
"health_run_dir": "DAYNIVO_HEALTH_RUN_DIR",
|
||||||
"share_dir": "VOXIP_SHARE_DIR",
|
"share_dir": "DAYNIVO_SHARE_DIR",
|
||||||
"log_dir": "VOXIP_LOG_DIR",
|
"log_dir": "DAYNIVO_LOG_DIR",
|
||||||
"helper": "VOXIP_HELPER",
|
"helper": "DAYNIVO_HELPER",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5,11 +5,11 @@ from __future__ import annotations
|
|||||||
import subprocess
|
import subprocess
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
BROWSER_UNIT = "voxip-kiosk-browser.service"
|
BROWSER_UNIT = "daynivo-kiosk-browser.service"
|
||||||
X_UNIT = "voxip-kiosk-x.service"
|
X_UNIT = "daynivo-kiosk-x.service"
|
||||||
AGENT_UNIT = "voxip-kiosk-agent.service"
|
AGENT_UNIT = "daynivo-kiosk-agent.service"
|
||||||
MANAGER_UNIT = "voxip-kiosk-manager.service"
|
MANAGER_UNIT = "daynivo-kiosk-manager.service"
|
||||||
HEALTH_UNIT = "voxip-kiosk-healthcheck.service"
|
HEALTH_UNIT = "daynivo-kiosk-healthcheck.service"
|
||||||
|
|
||||||
# Units whose logs the web interface may show (label → journalctl -u args).
|
# Units whose logs the web interface may show (label → journalctl -u args).
|
||||||
LOG_SOURCES: dict[str, tuple[str, list[str]]] = {
|
LOG_SOURCES: dict[str, tuple[str, list[str]]] = {
|
||||||
@@ -18,7 +18,7 @@ LOG_SOURCES: dict[str, tuple[str, list[str]]] = {
|
|||||||
"agent": ("Kiosk-agent", [AGENT_UNIT]),
|
"agent": ("Kiosk-agent", [AGENT_UNIT]),
|
||||||
"health": ("Healthcheck", [HEALTH_UNIT]),
|
"health": ("Healthcheck", [HEALTH_UNIT]),
|
||||||
"manager": ("Beheerinterface", [MANAGER_UNIT]),
|
"manager": ("Beheerinterface", [MANAGER_UNIT]),
|
||||||
"network": ("Netwerk", ["NetworkManager.service", "voxip-network-guard.service", "voxip-network-rollback.service", "voxip-network-activate.service"]),
|
"network": ("Netwerk", ["NetworkManager.service", "daynivo-network-guard.service", "daynivo-network-rollback.service", "daynivo-network-activate.service"]),
|
||||||
"system": ("Volledig systeem", []),
|
"system": ("Volledig systeem", []),
|
||||||
}
|
}
|
||||||
LOG_LINES = (50, 100, 200, 500)
|
LOG_LINES = (50, 100, 200, 500)
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
|||||||
"""voxip-kiosk-updater — installs new Daynivo Kiosk OS releases (runs as root).
|
"""daynivo-kiosk-updater — installs new Daynivo Kiosk OS releases (runs as root).
|
||||||
|
|
||||||
A release is a tag ``vX.Y.Z`` on the Gitea repository with two assets:
|
A release is a tag ``vX.Y.Z`` on the Gitea repository with two assets:
|
||||||
``daynivo-kiosk-os-X.Y.Z.tar.gz`` and its ``.sha256``. The updater
|
``daynivo-kiosk-os-X.Y.Z.tar.gz`` and its ``.sha256``. The updater
|
||||||
@@ -11,9 +11,9 @@ A release is a tag ``vX.Y.Z`` on the Gitea repository with two assets:
|
|||||||
|
|
||||||
It never installs an older or equal version. Usage::
|
It never installs an older or equal version. Usage::
|
||||||
|
|
||||||
voxip-kiosk-updater --check # only check
|
daynivo-kiosk-updater --check # only check
|
||||||
voxip-kiosk-updater --auto # check; install when auto_update is on (daily timer)
|
daynivo-kiosk-updater --auto # check; install when auto_update is on (daily timer)
|
||||||
voxip-kiosk-updater --install # check and install when newer (button in the web interface)
|
daynivo-kiosk-updater --install # check and install when newer (button in the web interface)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
@@ -39,12 +39,12 @@ from . import logutil
|
|||||||
from .config import atomic_write_json, load_config
|
from .config import atomic_write_json, load_config
|
||||||
from .paths import Paths, default_paths, read_version
|
from .paths import Paths, default_paths, read_version
|
||||||
|
|
||||||
log = logging.getLogger("voxip-kiosk-updater")
|
log = logging.getLogger("daynivo-kiosk-updater")
|
||||||
|
|
||||||
RELEASE_API = "https://git.rothman.nl/api/v1/repos/rothman/daynivo-kiosk-os/releases/latest"
|
RELEASE_API = "https://git.rothman.nl/api/v1/repos/rothman/daynivo-kiosk-os/releases/latest"
|
||||||
ASSET_PREFIX = "daynivo-kiosk-os-"
|
ASSET_PREFIX = "daynivo-kiosk-os-"
|
||||||
RELEASE_DIR = Path("/opt/daynivo-kiosk-os")
|
RELEASE_DIR = Path("/opt/daynivo-kiosk-os")
|
||||||
CACHE_DIR = Path("/var/cache/voxip-kiosk")
|
CACHE_DIR = Path("/var/cache/daynivo-kiosk")
|
||||||
KEEP_RELEASES = 2
|
KEEP_RELEASES = 2
|
||||||
MAX_DOWNLOAD = 64 * 1024 * 1024
|
MAX_DOWNLOAD = 64 * 1024 * 1024
|
||||||
USER_AGENT = "Daynivo-Kiosk-OS/updater"
|
USER_AGENT = "Daynivo-Kiosk-OS/updater"
|
||||||
@@ -219,7 +219,7 @@ class Updater:
|
|||||||
|
|
||||||
|
|
||||||
def main(argv: list[str] | None = None, updater: Updater | None = None) -> int:
|
def main(argv: list[str] | None = None, updater: Updater | None = None) -> int:
|
||||||
parser = argparse.ArgumentParser(prog="voxip-kiosk-updater", description="Daynivo Kiosk OS bijwerken.")
|
parser = argparse.ArgumentParser(prog="daynivo-kiosk-updater", description="Daynivo Kiosk OS bijwerken.")
|
||||||
mode = parser.add_mutually_exclusive_group(required=True)
|
mode = parser.add_mutually_exclusive_group(required=True)
|
||||||
mode.add_argument("--check", action="store_true", help="alleen controleren")
|
mode.add_argument("--check", action="store_true", help="alleen controleren")
|
||||||
mode.add_argument("--auto", action="store_true", help="controleren en bijwerken als automatisch bijwerken aan staat")
|
mode.add_argument("--auto", action="store_true", help="controleren en bijwerken als automatisch bijwerken aan staat")
|
||||||
File renamed without changes.
@@ -48,7 +48,7 @@ def create_app(paths: Paths | None = None, *, helper: Any = None, cdp: Any = Non
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = _secret_key(paths)
|
app.secret_key = _secret_key(paths)
|
||||||
app.config.update(
|
app.config.update(
|
||||||
SESSION_COOKIE_NAME="voxip_session",
|
SESSION_COOKIE_NAME="daynivo_session",
|
||||||
SESSION_COOKIE_HTTPONLY=True,
|
SESSION_COOKIE_HTTPONLY=True,
|
||||||
SESSION_COOKIE_SAMESITE="Strict",
|
SESSION_COOKIE_SAMESITE="Strict",
|
||||||
SESSION_COOKIE_SECURE=config["admin_https"],
|
SESSION_COOKIE_SECURE=config["admin_https"],
|
||||||
@@ -58,7 +58,7 @@ def create_app(paths: Paths | None = None, *, helper: Any = None, cdp: Any = Non
|
|||||||
)
|
)
|
||||||
credentials = CredentialStore(paths.admin_file, paths.setup_code_file)
|
credentials = CredentialStore(paths.admin_file, paths.setup_code_file)
|
||||||
credentials.ensure_setup_code()
|
credentials.ensure_setup_code()
|
||||||
app.extensions["voxip"] = Services(
|
app.extensions["daynivo"] = Services(
|
||||||
paths=paths,
|
paths=paths,
|
||||||
credentials=credentials,
|
credentials=credentials,
|
||||||
throttle=LoginThrottle(),
|
throttle=LoginThrottle(),
|
||||||
@@ -21,7 +21,7 @@ HASHER = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=2, hash_len=
|
|||||||
|
|
||||||
MIN_LENGTH = 10
|
MIN_LENGTH = 10
|
||||||
MAX_LENGTH = 128
|
MAX_LENGTH = 128
|
||||||
WEAK = {"admin", "administrator", "password", "wachtwoord", "raspberry", "voxip", "kiosk", "welkom", "welcome", "qwerty", "123456"}
|
WEAK = {"admin", "administrator", "password", "wachtwoord", "raspberry", "daynivo", "kiosk", "welkom", "welcome", "qwerty", "123456"}
|
||||||
|
|
||||||
|
|
||||||
def password_problem(password: str, confirm: str | None = None) -> str | None:
|
def password_problem(password: str, confirm: str | None = None) -> str | None:
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
File renamed without changes.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -22,14 +22,14 @@ from . import security
|
|||||||
from .auth import password_problem
|
from .auth import password_problem
|
||||||
|
|
||||||
bp = Blueprint("ui", __name__)
|
bp = Blueprint("ui", __name__)
|
||||||
audit_log = logging.getLogger("voxip-kiosk-audit")
|
audit_log = logging.getLogger("daynivo-kiosk-audit")
|
||||||
|
|
||||||
IDLE_TIMEOUT = 3600
|
IDLE_TIMEOUT = 3600
|
||||||
PUBLIC_ENDPOINTS = {"ui.login", "ui.setup", "static"}
|
PUBLIC_ENDPOINTS = {"ui.login", "ui.setup", "static"}
|
||||||
|
|
||||||
|
|
||||||
def svc():
|
def svc():
|
||||||
return current_app.extensions["voxip"]
|
return current_app.extensions["daynivo"]
|
||||||
|
|
||||||
|
|
||||||
def cfg() -> dict[str, Any]:
|
def cfg() -> dict[str, Any]:
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Daynivo configuratie en SSH-sleutels importeren vanaf de bootpartitie
|
Description=Daynivo configuratie en SSH-sleutels importeren vanaf de bootpartitie
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
After=local-fs.target
|
After=local-fs.target
|
||||||
Before=voxip-kiosk-manager.service voxip-kiosk-browser.service ssh.service
|
Before=daynivo-kiosk-manager.service daynivo-kiosk-browser.service ssh.service
|
||||||
ConditionPathExistsGlob=|/boot/firmware/daynivo-config.json
|
ConditionPathExistsGlob=|/boot/firmware/daynivo-config.json
|
||||||
ConditionPathExistsGlob=|/boot/firmware/daynivo-authorized_keys
|
ConditionPathExistsGlob=|/boot/firmware/daynivo-authorized_keys
|
||||||
ConditionPathExistsGlob=|/boot/daynivo-config.json
|
ConditionPathExistsGlob=|/boot/daynivo-config.json
|
||||||
@@ -15,7 +15,7 @@ ConditionPathExistsGlob=|/boot/voxip-authorized_keys
|
|||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-helper boot-import
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-helper boot-import
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Daynivo Kiosk agent (navigatie, offlinepagina, verversen)
|
Description=Daynivo Kiosk agent (navigatie, offlinepagina, verversen)
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
After=voxip-kiosk-browser.service
|
After=daynivo-kiosk-browser.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=kiosk
|
User=kiosk
|
||||||
Group=kiosk
|
Group=kiosk
|
||||||
RuntimeDirectory=voxip-kiosk-agent
|
RuntimeDirectory=daynivo-kiosk-agent
|
||||||
RuntimeDirectoryMode=0755
|
RuntimeDirectoryMode=0755
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-agent
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-agent
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
SyslogIdentifier=voxip-kiosk-agent
|
SyslogIdentifier=daynivo-kiosk-agent
|
||||||
NoNewPrivileges=yes
|
NoNewPrivileges=yes
|
||||||
ProtectSystem=strict
|
ProtectSystem=strict
|
||||||
ProtectHome=yes
|
ProtectHome=yes
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Daynivo Kiosk Chromium
|
||||||
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
|
Requires=daynivo-kiosk-x.service
|
||||||
|
After=daynivo-kiosk-x.service daynivo-boot-import.service
|
||||||
|
# Restarting or stopping X restarts/stops the browser as well.
|
||||||
|
PartOf=daynivo-kiosk-x.service
|
||||||
|
# A crash loop stops after 6 starts in 10 minutes; the healthcheck logs it
|
||||||
|
# and retries after a cool-down (see daynivo-kiosk-healthcheck).
|
||||||
|
StartLimitIntervalSec=600
|
||||||
|
StartLimitBurst=6
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=kiosk
|
||||||
|
Group=kiosk
|
||||||
|
Environment=DISPLAY=:0
|
||||||
|
Environment=XAUTHORITY=/run/daynivo-kiosk-x/Xauthority
|
||||||
|
Environment=HOME=/home/kiosk
|
||||||
|
RuntimeDirectory=daynivo-kiosk-browser
|
||||||
|
RuntimeDirectoryMode=0755
|
||||||
|
StateDirectory=daynivo-kiosk-browser
|
||||||
|
StateDirectoryMode=0700
|
||||||
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-browser
|
||||||
|
# daynivo-kiosk-browser exits 1 after a crash when browser_restart is on, 0 when it is off.
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
TimeoutStopSec=15
|
||||||
|
KillMode=control-group
|
||||||
|
OOMScoreAdjust=-100
|
||||||
|
LogRateLimitIntervalSec=30s
|
||||||
|
LogRateLimitBurst=300
|
||||||
|
SyslogIdentifier=daynivo-kiosk-browser
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Daynivo Kiosk healthcheck
|
||||||
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RuntimeDirectory=daynivo-kiosk-health
|
||||||
|
RuntimeDirectoryPreserve=yes
|
||||||
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-healthcheck
|
||||||
|
SyslogIdentifier=daynivo-kiosk-healthcheck
|
||||||
|
TimeoutStartSec=60
|
||||||
File renamed without changes.
@@ -1,27 +1,27 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Daynivo Kiosk Manager (webbeheer)
|
Description=Daynivo Kiosk Manager (webbeheer)
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
After=network.target voxip-boot-import.service
|
After=network.target daynivo-boot-import.service
|
||||||
StartLimitIntervalSec=300
|
StartLimitIntervalSec=300
|
||||||
StartLimitBurst=10
|
StartLimitBurst=10
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=voxip
|
User=daynivo
|
||||||
Group=voxip
|
Group=daynivo
|
||||||
# systemd-journal: read logs; video: vcgencmd (voltage/throttling)
|
# systemd-journal: read logs; video: vcgencmd (voltage/throttling)
|
||||||
SupplementaryGroups=systemd-journal video
|
SupplementaryGroups=systemd-journal video
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-manager
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-manager
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=3
|
RestartSec=3
|
||||||
UMask=0027
|
UMask=0027
|
||||||
LogsDirectory=voxip-kiosk
|
LogsDirectory=daynivo-kiosk
|
||||||
LogsDirectoryMode=0750
|
LogsDirectoryMode=0750
|
||||||
SyslogIdentifier=voxip-kiosk-manager
|
SyslogIdentifier=daynivo-kiosk-manager
|
||||||
# No NoNewPrivileges/ProtectSystem/ProtectHome: the helper started through
|
# No NoNewPrivileges/ProtectSystem/ProtectHome: the helper started through
|
||||||
# "sudo -n voxip-kiosk-helper" inherits this unit's mount namespace and must
|
# "sudo -n daynivo-kiosk-helper" inherits this unit's mount namespace and must
|
||||||
# be able to write /etc (hostname, NetworkManager profiles). The web process
|
# be able to write /etc (hostname, NetworkManager profiles). The web process
|
||||||
# itself runs unprivileged as user voxip and can only write its own dirs.
|
# itself runs unprivileged as user daynivo and can only write its own dirs.
|
||||||
# Also no ProtectKernelTunables/ProtectKernelModules/LockPersonality,
|
# Also no ProtectKernelTunables/ProtectKernelModules/LockPersonality,
|
||||||
# RestrictSUIDSGID, SystemCall*, ...: for a non-root unit those imply
|
# RestrictSUIDSGID, SystemCall*, ...: for a non-root unit those imply
|
||||||
# NoNewPrivileges, and sudo then refuses to run (tests/test_units.py).
|
# NoNewPrivileges, and sudo then refuses to run (tests/test_units.py).
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Daynivo Kiosk OS: controleren op updates (en installeren als dat aan staat)
|
Description=Daynivo Kiosk OS: controleren op updates (en installeren als dat aan staat)
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-updater --auto
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-updater --auto
|
||||||
TimeoutStartSec=1h
|
TimeoutStartSec=1h
|
||||||
SyslogIdentifier=voxip-kiosk-updater
|
SyslogIdentifier=daynivo-kiosk-updater
|
||||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Daynivo Kiosk X-server (vt7)
|
Description=Daynivo Kiosk X-server (vt7)
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
After=systemd-user-sessions.service systemd-logind.service
|
After=systemd-user-sessions.service systemd-logind.service
|
||||||
Conflicts=getty@tty7.service
|
Conflicts=getty@tty7.service
|
||||||
StartLimitIntervalSec=600
|
StartLimitIntervalSec=600
|
||||||
@@ -20,10 +20,10 @@ StandardOutput=journal
|
|||||||
StandardError=journal
|
StandardError=journal
|
||||||
UtmpIdentifier=tty7
|
UtmpIdentifier=tty7
|
||||||
UtmpMode=user
|
UtmpMode=user
|
||||||
RuntimeDirectory=voxip-kiosk-x
|
RuntimeDirectory=daynivo-kiosk-x
|
||||||
RuntimeDirectoryMode=0700
|
RuntimeDirectoryMode=0700
|
||||||
ExecStartPre=+/usr/bin/chvt 7
|
ExecStartPre=+/usr/bin/chvt 7
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-x
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-x
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=3
|
RestartSec=3
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Daynivo netwerkherstel bij opstarten (rollback en noodreset)
|
Description=Daynivo netwerkherstel bij opstarten (rollback en noodreset)
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
Documentation=file:///usr/share/doc/daynivo-kiosk/README.md
|
||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
After=local-fs.target
|
After=local-fs.target
|
||||||
Before=NetworkManager.service network-pre.target shutdown.target
|
Before=NetworkManager.service network-pre.target shutdown.target
|
||||||
@@ -10,7 +10,7 @@ Conflicts=shutdown.target
|
|||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-helper network-boot-guard
|
ExecStart=/usr/lib/daynivo-kiosk/daynivo-kiosk-helper network-boot-guard
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Daynivo Kiosk Chromium
|
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
|
||||||
Requires=voxip-kiosk-x.service
|
|
||||||
After=voxip-kiosk-x.service voxip-boot-import.service
|
|
||||||
# Restarting or stopping X restarts/stops the browser as well.
|
|
||||||
PartOf=voxip-kiosk-x.service
|
|
||||||
# A crash loop stops after 6 starts in 10 minutes; the healthcheck logs it
|
|
||||||
# and retries after a cool-down (see voxip-kiosk-healthcheck).
|
|
||||||
StartLimitIntervalSec=600
|
|
||||||
StartLimitBurst=6
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=kiosk
|
|
||||||
Group=kiosk
|
|
||||||
Environment=DISPLAY=:0
|
|
||||||
Environment=XAUTHORITY=/run/voxip-kiosk-x/Xauthority
|
|
||||||
Environment=HOME=/home/kiosk
|
|
||||||
RuntimeDirectory=voxip-kiosk-browser
|
|
||||||
RuntimeDirectoryMode=0755
|
|
||||||
StateDirectory=voxip-kiosk-browser
|
|
||||||
StateDirectoryMode=0700
|
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-browser
|
|
||||||
# voxip-kiosk-browser exits 1 after a crash when browser_restart is on, 0 when it is off.
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
TimeoutStopSec=15
|
|
||||||
KillMode=control-group
|
|
||||||
OOMScoreAdjust=-100
|
|
||||||
LogRateLimitIntervalSec=30s
|
|
||||||
LogRateLimitBurst=300
|
|
||||||
SyslogIdentifier=voxip-kiosk-browser
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Daynivo Kiosk healthcheck
|
|
||||||
Documentation=file:///usr/share/doc/voxip-kiosk/README.md
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
RuntimeDirectory=voxip-kiosk-health
|
|
||||||
RuntimeDirectoryPreserve=yes
|
|
||||||
ExecStart=/usr/lib/voxip-kiosk/voxip-kiosk-healthcheck
|
|
||||||
SyslogIdentifier=voxip-kiosk-healthcheck
|
|
||||||
TimeoutStartSec=60
|
|
||||||
+7
-7
@@ -4,7 +4,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk.paths import Paths
|
from daynivo_kiosk.paths import Paths
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class FakeHelper:
|
|||||||
self.responses = {}
|
self.responses = {}
|
||||||
|
|
||||||
def call(self, verb, *args, payload=None, timeout=60):
|
def call(self, verb, *args, payload=None, timeout=60):
|
||||||
from voxip_kiosk.helper_client import HelperError
|
from daynivo_kiosk.helper_client import HelperError
|
||||||
|
|
||||||
self.calls.append((verb, args, payload))
|
self.calls.append((verb, args, payload))
|
||||||
if self.fail:
|
if self.fail:
|
||||||
@@ -53,7 +53,7 @@ class FakeCDP:
|
|||||||
self.fail = None
|
self.fail = None
|
||||||
|
|
||||||
def _do(self, name, *args):
|
def _do(self, name, *args):
|
||||||
from voxip_kiosk.cdp import CDPError
|
from daynivo_kiosk.cdp import CDPError
|
||||||
|
|
||||||
self.calls.append((name, args))
|
self.calls.append((name, args))
|
||||||
if self.fail:
|
if self.fail:
|
||||||
@@ -80,7 +80,7 @@ def fake_cdp():
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def quiet_system(monkeypatch):
|
def quiet_system(monkeypatch):
|
||||||
"""Keep the web tests independent of the machine they run on."""
|
"""Keep the web tests independent of the machine they run on."""
|
||||||
from voxip_kiosk import netinfo, services, sysinfo
|
from daynivo_kiosk import netinfo, services, sysinfo
|
||||||
|
|
||||||
monkeypatch.setattr(services, "summary", lambda: {
|
monkeypatch.setattr(services, "summary", lambda: {
|
||||||
"browser": {"unit": services.BROWSER_UNIT, "status": "ok", "label": "Actief", "restarts": "2", "since": ""},
|
"browser": {"unit": services.BROWSER_UNIT, "status": "ok", "label": "Actief", "restarts": "2", "since": ""},
|
||||||
@@ -96,7 +96,7 @@ def quiet_system(monkeypatch):
|
|||||||
"available": True, "wifi_country": "NL",
|
"available": True, "wifi_country": "NL",
|
||||||
"devices": {
|
"devices": {
|
||||||
iface: {"interface": iface, "kind": kind, "present": True, "state": "connected", "state_label": "Verbonden",
|
iface: {"interface": iface, "kind": kind, "present": True, "state": "connected", "state_label": "Verbonden",
|
||||||
"connected": True, "connection": f"voxip-{iface}", "addresses": ["192.168.10.20/24"], "gateway": "192.168.10.1",
|
"connected": True, "connection": f"daynivo-{iface}", "addresses": ["192.168.10.20/24"], "gateway": "192.168.10.1",
|
||||||
"dns": ["192.168.10.1"], "hwaddr": "B8:27:EB:00:00:01",
|
"dns": ["192.168.10.1"], "hwaddr": "B8:27:EB:00:00:01",
|
||||||
"profile": {"exists": True, "method": "dhcp", "address": "", "gateway": "", "dns": "", "ssid": "Kantoor", "hidden": False}}
|
"profile": {"exists": True, "method": "dhcp", "address": "", "gateway": "", "dns": "", "ssid": "Kantoor", "hidden": False}}
|
||||||
for iface, kind in (("eth0", "ethernet"), ("wlan0", "wifi"))
|
for iface, kind in (("eth0", "ethernet"), ("wlan0", "wifi"))
|
||||||
@@ -106,7 +106,7 @@ def quiet_system(monkeypatch):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def app(paths, fake_helper, fake_cdp, quiet_system):
|
def app(paths, fake_helper, fake_cdp, quiet_system):
|
||||||
from voxip_kiosk.web import create_app
|
from daynivo_kiosk.web import create_app
|
||||||
|
|
||||||
application = create_app(paths, helper=fake_helper, cdp=fake_cdp)
|
application = create_app(paths, helper=fake_helper, cdp=fake_cdp)
|
||||||
application.config["TESTING"] = True
|
application.config["TESTING"] = True
|
||||||
@@ -130,7 +130,7 @@ PASSWORD = "Correct-Paard-Batterij-42"
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def logged_in(app, client, paths):
|
def logged_in(app, client, paths):
|
||||||
"""A client with a configured admin password and an active session."""
|
"""A client with a configured admin password and an active session."""
|
||||||
app.extensions["voxip"].credentials.set_password(PASSWORD)
|
app.extensions["daynivo"].credentials.set_password(PASSWORD)
|
||||||
page = client.get("/login")
|
page = client.get("/login")
|
||||||
token = csrf_from(page)
|
token = csrf_from(page)
|
||||||
resp = client.post("/login", data={"password": PASSWORD, "csrf_token": token})
|
resp = client.post("/login", data={"password": PASSWORD, "csrf_token": token})
|
||||||
|
|||||||
+3
-3
@@ -2,9 +2,9 @@ import json
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk.agent import Agent, HUNG_RELOAD_AFTER, HUNG_RESTART_AFTER
|
from daynivo_kiosk.agent import Agent, HUNG_RELOAD_AFTER, HUNG_RESTART_AFTER
|
||||||
from voxip_kiosk.cdp import CDPError
|
from daynivo_kiosk.cdp import CDPError
|
||||||
from voxip_kiosk.config import save_config
|
from daynivo_kiosk.config import save_config
|
||||||
|
|
||||||
|
|
||||||
class Clock:
|
class Clock:
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import parse_qs, urlsplit
|
from urllib.parse import parse_qs, urlsplit
|
||||||
|
|
||||||
from voxip_kiosk import browser as b
|
from daynivo_kiosk import browser as b
|
||||||
from voxip_kiosk.config import DEFAULTS
|
from daynivo_kiosk.config import DEFAULTS
|
||||||
|
|
||||||
XRANDR = """Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 7680 x 7680
|
XRANDR = """Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 7680 x 7680
|
||||||
HDMI-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 531mm x 299mm
|
HDMI-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 531mm x 299mm
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import stat
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk import config as c
|
from daynivo_kiosk import config as c
|
||||||
|
|
||||||
|
|
||||||
def test_default_file_matches_defaults(paths):
|
def test_default_file_matches_defaults(paths):
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk import services
|
from daynivo_kiosk import services
|
||||||
from voxip_kiosk.cdp import CDPError
|
from daynivo_kiosk.cdp import CDPError
|
||||||
from voxip_kiosk.config import save_config
|
from daynivo_kiosk.config import save_config
|
||||||
from voxip_kiosk.healthcheck import CDP_FAILURES_BEFORE_RESTART, DISPLAY_RETRY_AFTER, HealthCheck
|
from daynivo_kiosk.healthcheck import CDP_FAILURES_BEFORE_RESTART, DISPLAY_RETRY_AFTER, HealthCheck
|
||||||
|
|
||||||
|
|
||||||
class World:
|
class World:
|
||||||
|
|||||||
+20
-20
@@ -3,8 +3,8 @@ import subprocess
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk import helper as h
|
from daynivo_kiosk import helper as h
|
||||||
from voxip_kiosk.config import load_config
|
from daynivo_kiosk.config import load_config
|
||||||
|
|
||||||
|
|
||||||
class Recorder:
|
class Recorder:
|
||||||
@@ -35,7 +35,7 @@ def helper(paths, tmp_path, boot):
|
|||||||
etc.mkdir()
|
etc.mkdir()
|
||||||
(etc / "hosts").write_text("127.0.0.1\tlocalhost\n127.0.1.1\tkiosk\n")
|
(etc / "hosts").write_text("127.0.0.1\tlocalhost\n127.0.1.1\tkiosk\n")
|
||||||
run = Recorder({"nmcli -t -f": "aaaa-1111\n"})
|
run = Recorder({"nmcli -t -f": "aaaa-1111\n"})
|
||||||
return h.Helper(paths=paths, run=run, etc=etc, boot_dirs=(boot,), helper_path="/usr/lib/voxip-kiosk/voxip-kiosk-helper")
|
return h.Helper(paths=paths, run=run, etc=etc, boot_dirs=(boot,), helper_path="/usr/lib/daynivo-kiosk/daynivo-kiosk-helper")
|
||||||
|
|
||||||
|
|
||||||
def run_main(helper, argv, env=None, capsys=None):
|
def run_main(helper, argv, env=None, capsys=None):
|
||||||
@@ -45,17 +45,17 @@ def run_main(helper, argv, env=None, capsys=None):
|
|||||||
|
|
||||||
|
|
||||||
def test_internal_verbs_refused_via_sudo(helper, capsys):
|
def test_internal_verbs_refused_via_sudo(helper, capsys):
|
||||||
code, out = run_main(helper, ["network-restore"], {"SUDO_USER": "voxip"}, capsys)
|
code, out = run_main(helper, ["network-restore"], {"SUDO_USER": "daynivo"}, capsys)
|
||||||
assert code == 1 and out["ok"] is False
|
assert code == 1 and out["ok"] is False
|
||||||
code, out = run_main(helper, ["boot-import"], {"SUDO_USER": "voxip"}, capsys)
|
code, out = run_main(helper, ["boot-import"], {"SUDO_USER": "daynivo"}, capsys)
|
||||||
assert code == 1
|
assert code == 1
|
||||||
assert helper.run.commands == []
|
assert helper.run.commands == []
|
||||||
|
|
||||||
|
|
||||||
def test_public_verb_via_sudo(helper, capsys):
|
def test_public_verb_via_sudo(helper, capsys):
|
||||||
code, out = run_main(helper, ["restart-browser"], {"SUDO_USER": "voxip"}, capsys)
|
code, out = run_main(helper, ["restart-browser"], {"SUDO_USER": "daynivo"}, capsys)
|
||||||
assert code == 0 and out["ok"] is True
|
assert code == 0 and out["ok"] is True
|
||||||
assert helper.run.ran("systemctl", "restart", "--no-block", "voxip-kiosk-browser.service")
|
assert helper.run.ran("systemctl", "restart", "--no-block", "daynivo-kiosk-browser.service")
|
||||||
|
|
||||||
|
|
||||||
def test_unknown_verb_and_bad_arity(helper, capsys):
|
def test_unknown_verb_and_bad_arity(helper, capsys):
|
||||||
@@ -99,7 +99,7 @@ ETH_STATIC = {"interface": "eth0", "method": "static", "address": "192.168.5.10/
|
|||||||
def test_network_apply_snapshot_pending_and_timers(helper, paths):
|
def test_network_apply_snapshot_pending_and_timers(helper, paths):
|
||||||
(paths.nm_connections_dir / "Wired connection 1.nmconnection").write_text("[connection]\nid=Wired connection 1\n")
|
(paths.nm_connections_dir / "Wired connection 1.nmconnection").write_text("[connection]\nid=Wired connection 1\n")
|
||||||
result = helper.network_apply(ETH_STATIC)
|
result = helper.network_apply(ETH_STATIC)
|
||||||
keyfile = paths.nm_connections_dir / "voxip-eth0.nmconnection"
|
keyfile = paths.nm_connections_dir / "daynivo-eth0.nmconnection"
|
||||||
assert keyfile.exists() and oct(keyfile.stat().st_mode & 0o777) == "0o600"
|
assert keyfile.exists() and oct(keyfile.stat().st_mode & 0o777) == "0o600"
|
||||||
assert "address1=192.168.5.10/24,192.168.5.1" in keyfile.read_text()
|
assert "address1=192.168.5.10/24,192.168.5.1" in keyfile.read_text()
|
||||||
assert (paths.network_backup_dir / "Wired connection 1.nmconnection").exists()
|
assert (paths.network_backup_dir / "Wired connection 1.nmconnection").exists()
|
||||||
@@ -108,8 +108,8 @@ def test_network_apply_snapshot_pending_and_timers(helper, paths):
|
|||||||
assert pending["deadline"] - pending["created"] == 180
|
assert pending["deadline"] - pending["created"] == 180
|
||||||
assert result["pending"]["interface"] == "eth0"
|
assert result["pending"]["interface"] == "eth0"
|
||||||
runs = [c for c in helper.run.commands if c[0] == "systemd-run"]
|
runs = [c for c in helper.run.commands if c[0] == "systemd-run"]
|
||||||
assert runs[0][1:3] == ["--unit=voxip-network-rollback", "--on-active=180"] and runs[0][-1] == "network-restore"
|
assert runs[0][1:3] == ["--unit=daynivo-network-rollback", "--on-active=180"] and runs[0][-1] == "network-restore"
|
||||||
assert runs[1][1:3] == ["--unit=voxip-network-activate", "--on-active=2"] and runs[1][-2:] == ["network-activate", "eth0"]
|
assert runs[1][1:3] == ["--unit=daynivo-network-activate", "--on-active=2"] and runs[1][-2:] == ["network-activate", "eth0"]
|
||||||
|
|
||||||
|
|
||||||
def test_second_apply_refused_while_pending(helper):
|
def test_second_apply_refused_while_pending(helper):
|
||||||
@@ -123,8 +123,8 @@ def test_confirm_clears_pending(helper, paths):
|
|||||||
helper.network_confirm()
|
helper.network_confirm()
|
||||||
assert not paths.network_pending_file.exists()
|
assert not paths.network_pending_file.exists()
|
||||||
assert not paths.network_backup_dir.exists()
|
assert not paths.network_backup_dir.exists()
|
||||||
assert (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
|
assert (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
|
||||||
assert helper.run.ran("systemctl", "stop", "voxip-network-rollback.timer")
|
assert helper.run.ran("systemctl", "stop", "daynivo-network-rollback.timer")
|
||||||
|
|
||||||
|
|
||||||
def test_restore_puts_old_profiles_back(helper, paths):
|
def test_restore_puts_old_profiles_back(helper, paths):
|
||||||
@@ -134,7 +134,7 @@ def test_restore_puts_old_profiles_back(helper, paths):
|
|||||||
old.unlink()
|
old.unlink()
|
||||||
helper.network_restore()
|
helper.network_restore()
|
||||||
assert old.exists()
|
assert old.exists()
|
||||||
assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
|
assert not (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
|
||||||
assert not paths.network_pending_file.exists()
|
assert not paths.network_pending_file.exists()
|
||||||
assert helper.run.ran("nmcli", "--wait", "30", "connection", "up", "uuid", "aaaa-1111")
|
assert helper.run.ran("nmcli", "--wait", "30", "connection", "up", "uuid", "aaaa-1111")
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ def test_wifi_keeps_existing_password_for_same_ssid(helper, paths):
|
|||||||
helper.network_confirm()
|
helper.network_confirm()
|
||||||
helper.network_apply({"interface": "wlan0", "method": "static", "address": "10.0.0.9/24", "gateway": "10.0.0.1", "dns": "10.0.0.1",
|
helper.network_apply({"interface": "wlan0", "method": "static", "address": "10.0.0.9/24", "gateway": "10.0.0.1", "dns": "10.0.0.1",
|
||||||
"wifi": {"ssid": "Kantoor", "psk": ""}})
|
"wifi": {"ssid": "Kantoor", "psk": ""}})
|
||||||
assert "psk=geheim-wachtwoord" in (paths.nm_connections_dir / "voxip-wlan0.nmconnection").read_text()
|
assert "psk=geheim-wachtwoord" in (paths.nm_connections_dir / "daynivo-wlan0.nmconnection").read_text()
|
||||||
helper.network_confirm()
|
helper.network_confirm()
|
||||||
with pytest.raises(h.HelperError, match="wachtwoord"):
|
with pytest.raises(h.HelperError, match="wachtwoord"):
|
||||||
helper.network_apply({"interface": "wlan0", "method": "dhcp", "wifi": {"ssid": "Ander", "psk": ""}})
|
helper.network_apply({"interface": "wlan0", "method": "dhcp", "wifi": {"ssid": "Ander", "psk": ""}})
|
||||||
@@ -165,22 +165,22 @@ def test_boot_guard_rolls_back_and_honours_reset(helper, paths, boot):
|
|||||||
helper.run.commands.clear()
|
helper.run.commands.clear()
|
||||||
result = helper.network_boot_guard()
|
result = helper.network_boot_guard()
|
||||||
assert result == {"rolled_back": True}
|
assert result == {"rolled_back": True}
|
||||||
assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
|
assert not (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
|
||||||
assert not any(c[0] == "nmcli" for c in helper.run.commands), "NetworkManager is not running yet at boot"
|
assert not any(c[0] == "nmcli" for c in helper.run.commands), "NetworkManager is not running yet at boot"
|
||||||
|
|
||||||
(paths.nm_connections_dir / "voxip-wlan0.nmconnection").write_text("x")
|
(paths.nm_connections_dir / "daynivo-wlan0.nmconnection").write_text("x")
|
||||||
(boot / "daynivo-network-reset").write_text("")
|
(boot / "daynivo-network-reset").write_text("")
|
||||||
assert helper.network_boot_guard() == {"reset": True}
|
assert helper.network_boot_guard() == {"reset": True}
|
||||||
assert not (paths.nm_connections_dir / "voxip-wlan0.nmconnection").exists()
|
assert not (paths.nm_connections_dir / "daynivo-wlan0.nmconnection").exists()
|
||||||
assert not (boot / "daynivo-network-reset").exists()
|
assert not (boot / "daynivo-network-reset").exists()
|
||||||
assert old.exists()
|
assert old.exists()
|
||||||
|
|
||||||
|
|
||||||
def test_boot_guard_still_honours_the_old_reset_name(helper, paths, boot):
|
def test_boot_guard_still_honours_the_old_reset_name(helper, paths, boot):
|
||||||
(paths.nm_connections_dir / "voxip-eth0.nmconnection").write_text("x")
|
(paths.nm_connections_dir / "daynivo-eth0.nmconnection").write_text("x")
|
||||||
(boot / "voxip-network-reset").write_text("")
|
(boot / "voxip-network-reset").write_text("")
|
||||||
assert helper.network_boot_guard() == {"reset": True}
|
assert helper.network_boot_guard() == {"reset": True}
|
||||||
assert not (paths.nm_connections_dir / "voxip-eth0.nmconnection").exists()
|
assert not (paths.nm_connections_dir / "daynivo-eth0.nmconnection").exists()
|
||||||
assert not (boot / "voxip-network-reset").exists()
|
assert not (boot / "voxip-network-reset").exists()
|
||||||
|
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ def test_update_verbs_are_public_and_install_runs_in_its_own_unit(helper):
|
|||||||
|
|
||||||
def test_update_install_reports_a_running_update(helper):
|
def test_update_install_reports_a_running_update(helper):
|
||||||
def busy(args, timeout=30, check=True, input=None):
|
def busy(args, timeout=30, check=True, input=None):
|
||||||
return subprocess.CompletedProcess(args, 1, stdout="", stderr="Unit voxip-kiosk-update-now.service already exists.")
|
return subprocess.CompletedProcess(args, 1, stdout="", stderr="Unit daynivo-kiosk-update-now.service already exists.")
|
||||||
|
|
||||||
helper.run = busy
|
helper.run = busy
|
||||||
with pytest.raises(h.HelperError, match="al een update"):
|
with pytest.raises(h.HelperError, match="al een update"):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk import netconfig as n
|
from daynivo_kiosk import netconfig as n
|
||||||
from voxip_kiosk.validation import ValidationError
|
from daynivo_kiosk.validation import ValidationError
|
||||||
|
|
||||||
|
|
||||||
def test_validate_static_ethernet():
|
def test_validate_static_ethernet():
|
||||||
@@ -27,7 +27,7 @@ def test_keyfile_static_ethernet():
|
|||||||
req = n.validate_request({"interface": "eth0", "method": "static", "address": "10.1.2.3/16", "gateway": "10.1.0.1", "dns": ["10.1.0.1"]})
|
req = n.validate_request({"interface": "eth0", "method": "static", "address": "10.1.2.3/16", "gateway": "10.1.0.1", "dns": ["10.1.0.1"]})
|
||||||
text = n.build_keyfile(req, uuid="11111111-2222-3333-4444-555555555555")
|
text = n.build_keyfile(req, uuid="11111111-2222-3333-4444-555555555555")
|
||||||
kf = n.read_keyfile(text)
|
kf = n.read_keyfile(text)
|
||||||
assert kf.get("connection", "id") == "voxip-eth0"
|
assert kf.get("connection", "id") == "daynivo-eth0"
|
||||||
assert kf.get("connection", "type") == "ethernet"
|
assert kf.get("connection", "type") == "ethernet"
|
||||||
assert kf.get("connection", "autoconnect-priority") == "100"
|
assert kf.get("connection", "autoconnect-priority") == "100"
|
||||||
assert kf.get("ipv4", "method") == "manual"
|
assert kf.get("ipv4", "method") == "manual"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from voxip_kiosk import services, sysinfo
|
from daynivo_kiosk import services, sysinfo
|
||||||
|
|
||||||
|
|
||||||
def test_parse_throttled():
|
def test_parse_throttled():
|
||||||
|
|||||||
+2
-2
@@ -22,8 +22,8 @@ def settings(unit):
|
|||||||
|
|
||||||
|
|
||||||
def test_manager_can_use_sudo_for_the_helper():
|
def test_manager_can_use_sudo_for_the_helper():
|
||||||
unit = settings("voxip-kiosk-manager.service")
|
unit = settings("daynivo-kiosk-manager.service")
|
||||||
assert unit["User"] == "voxip"
|
assert unit["User"] == "daynivo"
|
||||||
for key in IMPLY_NO_NEW_PRIVILEGES:
|
for key in IMPLY_NO_NEW_PRIVILEGES:
|
||||||
assert unit.get(key, "no") in ("no", "false", ""), key
|
assert unit.get(key, "no") in ("no", "false", ""), key
|
||||||
for key in ("ProtectSystem", "ProtectHome", "PrivateTmp"):
|
for key in ("ProtectSystem", "ProtectHome", "PrivateTmp"):
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import tarfile
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk import updater as u
|
from daynivo_kiosk import updater as u
|
||||||
from voxip_kiosk.config import save_config
|
from daynivo_kiosk.config import save_config
|
||||||
|
|
||||||
API = u.RELEASE_API
|
API = u.RELEASE_API
|
||||||
BASE = "https://git.example.nl/rothman/daynivo-kiosk-os/releases/download"
|
BASE = "https://git.example.nl/rothman/daynivo-kiosk-os/releases/download"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk import validation as v
|
from daynivo_kiosk import validation as v
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("url", [
|
@pytest.mark.parametrize("url", [
|
||||||
|
|||||||
+9
-9
@@ -2,8 +2,8 @@ import json
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from voxip_kiosk.config import load_config
|
from daynivo_kiosk.config import load_config
|
||||||
from voxip_kiosk.web import auth
|
from daynivo_kiosk.web import auth
|
||||||
|
|
||||||
from .conftest import PASSWORD, csrf_from, token
|
from .conftest import PASSWORD, csrf_from, token
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ def test_setup_without_csrf_is_rejected(client, paths):
|
|||||||
# --- login & session -------------------------------------------------------------
|
# --- login & session -------------------------------------------------------------
|
||||||
|
|
||||||
def test_login_logout(app, client):
|
def test_login_logout(app, client):
|
||||||
app.extensions["voxip"].credentials.set_password(PASSWORD)
|
app.extensions["daynivo"].credentials.set_password(PASSWORD)
|
||||||
assert client.get("/").status_code == 302
|
assert client.get("/").status_code == 302
|
||||||
tok = csrf_from(client.get("/login"))
|
tok = csrf_from(client.get("/login"))
|
||||||
assert "Onjuist" in client.post("/login", data={"csrf_token": tok, "password": "fout-wachtwoord"}).get_data(as_text=True)
|
assert "Onjuist" in client.post("/login", data={"csrf_token": tok, "password": "fout-wachtwoord"}).get_data(as_text=True)
|
||||||
@@ -63,7 +63,7 @@ def test_login_logout(app, client):
|
|||||||
|
|
||||||
|
|
||||||
def test_session_cookie_flags(app, client):
|
def test_session_cookie_flags(app, client):
|
||||||
app.extensions["voxip"].credentials.set_password(PASSWORD)
|
app.extensions["daynivo"].credentials.set_password(PASSWORD)
|
||||||
tok = csrf_from(client.get("/login"))
|
tok = csrf_from(client.get("/login"))
|
||||||
resp = client.post("/login", data={"csrf_token": tok, "password": PASSWORD})
|
resp = client.post("/login", data={"csrf_token": tok, "password": PASSWORD})
|
||||||
cookie = resp.headers["Set-Cookie"]
|
cookie = resp.headers["Set-Cookie"]
|
||||||
@@ -71,7 +71,7 @@ def test_session_cookie_flags(app, client):
|
|||||||
|
|
||||||
|
|
||||||
def test_login_throttling(app, client):
|
def test_login_throttling(app, client):
|
||||||
app.extensions["voxip"].credentials.set_password(PASSWORD)
|
app.extensions["daynivo"].credentials.set_password(PASSWORD)
|
||||||
tok = csrf_from(client.get("/login"))
|
tok = csrf_from(client.get("/login"))
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
client.post("/login", data={"csrf_token": tok, "password": "verkeerd-wachtwoord"})
|
client.post("/login", data={"csrf_token": tok, "password": "verkeerd-wachtwoord"})
|
||||||
@@ -113,7 +113,7 @@ def test_password_change_invalidates_other_sessions(app, logged_in):
|
|||||||
|
|
||||||
|
|
||||||
def test_idle_session_expires(app, logged_in, monkeypatch):
|
def test_idle_session_expires(app, logged_in, monkeypatch):
|
||||||
from voxip_kiosk.web import views
|
from daynivo_kiosk.web import views
|
||||||
|
|
||||||
real = views.time.time
|
real = views.time.time
|
||||||
monkeypatch.setattr(views.time, "time", lambda: real() + views.IDLE_TIMEOUT + 5)
|
monkeypatch.setattr(views.time, "time", lambda: real() + views.IDLE_TIMEOUT + 5)
|
||||||
@@ -141,7 +141,7 @@ def test_public_clients_blocked(client, addr, allowed):
|
|||||||
|
|
||||||
|
|
||||||
def test_same_subnet_global_ipv6_allowed():
|
def test_same_subnet_global_ipv6_allowed():
|
||||||
from voxip_kiosk.web.security import client_allowed
|
from daynivo_kiosk.web.security import client_allowed
|
||||||
|
|
||||||
assert client_allowed("2a02:a210:1:2::99", False, ["2a02:a210:1:2::5/64"])
|
assert client_allowed("2a02:a210:1:2::99", False, ["2a02:a210:1:2::5/64"])
|
||||||
assert not client_allowed("2a02:a210:9:9::99", False, ["2a02:a210:1:2::5/64"])
|
assert not client_allowed("2a02:a210:9:9::99", False, ["2a02:a210:1:2::5/64"])
|
||||||
@@ -156,7 +156,7 @@ def test_security_headers(client):
|
|||||||
|
|
||||||
|
|
||||||
def test_api_requires_login(app, client):
|
def test_api_requires_login(app, client):
|
||||||
app.extensions["voxip"].credentials.set_password(PASSWORD)
|
app.extensions["daynivo"].credentials.set_password(PASSWORD)
|
||||||
resp = client.get("/api/status")
|
resp = client.get("/api/status")
|
||||||
assert resp.status_code == 401 and resp.json["error"]
|
assert resp.status_code == 401 and resp.json["error"]
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ def test_pages_render(logged_in, path):
|
|||||||
|
|
||||||
|
|
||||||
def test_dashboard_masks_token(logged_in, paths):
|
def test_dashboard_masks_token(logged_in, paths):
|
||||||
from voxip_kiosk.config import save_config
|
from daynivo_kiosk.config import save_config
|
||||||
|
|
||||||
save_config(paths.config_file, {"url": "https://portal.example.nl/display/hal?token=supergeheimtoken99"})
|
save_config(paths.config_file, {"url": "https://portal.example.nl/display/hal?token=supergeheimtoken99"})
|
||||||
body = logged_in.get("/").get_data(as_text=True)
|
body = logged_in.get("/").get_data(as_text=True)
|
||||||
|
|||||||
Loaded 100 of 102 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user