Schermtijdcontrole voor lokale accounts op Fedora/KDE Plasma (Wayland), vergelijkbaar met Google Family Link. Eén daemon kan meerdere accounts tegelijk bewaken (bv. meerdere kinderen op dezelfde machine, elk met hun eigen budget). Bestaat uit:
screentimectld — root-daemon die de schermtijd van elke geconfigureerde gebruiker
([[users]] in config.toml) bijhoudt, dagelijks reset, een waarschuwingspopup toont
en bij het verstrijken van de tijd het scherm vergrendelt en het account vergrendelt
(usermod -L).screentimectl — CLI om via sudo voor een specifieke gebruiker (--user <naam>)
tijd toe te voegen of af te trekken, het account direct te (ont)grendelen, of de
status op te vragen.Taal van popups, statuspagina's, CLI-uitvoer en de plasmoid-widget: standaard Engels,
instelbaar op Nederlands via language = "nl" in config.toml (zie
packaging/config.toml.example). Logregels (journalctl) en de installatiescripts
blijven altijd in het Engels/Nederlands zoals ze in de broncode staan — dat is voor de
beheerder, niet voor het gemonitorde account.
screentimectld telt elke seconde (app.rs::tick), voor elke gebruiker in [[users]]
afzonderlijk, de resterende tijd terug — maar uitsluitend terwijl die gebruiker een
actieve grafische sessie heeft: een sessie van Class=user en Type!=tty waarvan de
Active-property van logind op true staat. Active betekent hier letterlijk "heeft op
dit moment focus op het scherm/de VT" — bij meerdere gebruikers op één fysieke seat (bv.
via VT-wisselen met Ctrl+Alt+Fx) loopt de teller van een gebruiker dus alleen terwijl die
gebruiker ook echt in beeld is, niet terwijl de sessie op de achtergrond draait. De
gebruikers staan volledig los van elkaar: het budget, de waarschuwing en het
vergrendelen van de ene gebruiker raken de andere niet.
Bij het bereiken van warning_before_seconds resterend toont de daemon een passieve
kdialog-popup in de Wayland-sessie van target_user (popup.rs, draait als die
gebruiker via expliciete uid/gid/env-vars).
Bij 0 seconden resterend (app.rs::enforce):
session::lock_screen — vergrendelt het scherm via loginctl lock-session <id>.session::lock_account — vergrendelt het account via usermod -L, zodat een
nieuwe inlogpoging (en het ontgrendelen van het scherm met wachtwoord) faalt via PAM.Elk CLI-commando werkt op precies één gebruiker, aangegeven met de verplichte
--user <naam>-vlag (moet overeenkomen met een target_user uit [[users]]). Let op:
--user moet vóór het subcommando staan (screentimectl --user <naam> <commando>),
niet erna — dat is een beperking van de clap-argumentparser.
sudo screentimectl --user <naam> add <minuten> voegt tijd toe en ontgrendelt het
account automatisch zodra de resterende tijd weer positief is (app.rs::handle_add).
sudo screentimectl --user <naam> remove <minuten> (alias subtract) trekt tijd af van
het budget van vandaag (app.rs::handle_remove). Het ontgrendelt niets en vergrendelt
ook niets rechtstreeks — komt de teller hierdoor op of onder 0, dan grendelt de daemon
vanzelf af bij de eerstvolgende tick (binnen 1 seconde), op dezelfde manier als wanneer
de tijd gewoon afloopt.
sudo screentimectl --user <naam> lock vergrendelt scherm en account direct, ongeacht
hoeveel tijd er nog over is (app.rs::handle_lock). De remaining_seconds van het
budget blijven ongewijzigd staan.
sudo screentimectl --user <naam> unlock ontgrendelt alleen het account (usermod -U,
app.rs::handle_unlock) zonder de resterende tijd te wijzigen. Het scherm zelf blijft
vergrendeld totdat er met het wachtwoord wordt ingelogd — dat kan nu weer, omdat het
account niet langer geblokkeerd is via PAM.
Optioneel start de daemon een kleine HTTP-server (status_server.rs) die de resterende
tijd toont, als status_port is ingesteld in config.toml. Bewust zonder
authenticatie: dit is juist bedoeld zodat een gecontroleerd account dit zelf kan
opvragen. De server luistert alleen op 127.0.0.1, dus niet bereikbaar vanaf het LAN —
alleen vanaf de machine zelf.
http://127.0.0.1:<status_port>/status/<naam> — leesbare pagina voor één gebruiker
("Nog 42m 0s schermtijd over."), bedoeld om aan dat kind te geven als link/bookmark.
Puur informatief, geen instellingen — niets om aan te passen.http://127.0.0.1:<status_port>/status/<naam>.json — JSON
({"remaining_seconds":...,"locked":...}) voor diezelfde gebruiker; dit is ook wat de
KDE-plasmoid (packaging/plasmoid/) gebruikt.http://127.0.0.1:<status_port>/ — overzichtspagina met de resterende tijd van alle
geconfigureerde gebruikers samen (verversd elke 5 seconden) — bedoeld voor de ouder,
niet om met een kind te delen als er broers/zussen meedoen.Vanaf je eigen apparaat kun je dit nog steeds bekijken via een SSH-tunnel:
ssh -L 8765:127.0.0.1:8765 <gebruiker>@<machine-ip>
curl http://127.0.0.1:8765/
Een eerdere implementatie gebruikte login1.Manager.KillUser(uid, SIGKILL) om de
volledige desktopsessie (alle ~470 processen onder user-<uid>.slice, inclusief
compositor, audio, Akonadi/MySQL) in één klap te beëindigen. Dat werkte, maar gaf een
merkbare, korte systeemhang door de massale gelijktijdige SIGKILL en risico op corrupte
state in apps die niet netjes konden afsluiten. De huidige aanpak (alleen vergrendelen,
niets killen) is zachter en voldoende: het account is alsnog niet meer te gebruiken
zodra het scherm ontgrendeld moet worden.
Een tussenstap die de rauwe D-Bus-aanroep org.freedesktop.login1.Session.Lock() direct
via zbus deed, faalde onvoorspelbaar met NotSupported, ook met retries tot 15
seconden. Shellen naar loginctl lock-session <id> (dezelfde onderliggende aanroep,
maar via de systemd-eigen CLI) werkte wel betrouwbaar — vandaar de keuze om hier net als
bij usermod een bestaand CLI-commando te gebruiken in plaats van de D-Bus-aanroep zelf
te reproduceren.
Voor handmatig testen van de volledige waarschuwing/lock-flow zonder een hele dag te
wachten staat er een tweede, lokaal testaccount (bv. testkid) met een eigen ingelogde
Plasma-sessie op een losse tty (bv. tty3/seat0), en twee hulpbestanden in packaging/:
test-config.toml — budget van 1 minuut, waarschuwing bij 30s, popup van 5s.set-test-state.sh — zet /var/lib/screentimectl/state.json terug op 40s resterend,
niet gewaarschuwd, niet vergrendeld.Testcyclus (elke regel apart uitvoeren, niet als één geplakt blok — lange regels kunnen in de terminal op de visuele line-wrap afbreken en dan deels als los commando worden uitgevoerd):
sudo install -m 755 target/release/screentimectld /usr/local/bin/screentimectld
sudo usermod -U testkid
sudo bash packaging/set-test-state.sh
sudo /usr/local/bin/screentimectld
Wissel daarna direct naar de tty van het testaccount (Ctrl+Alt+Fx) en blijf daar, anders
telt de tijd niet af (zie "Werking" hierboven over de Active-vereiste). Tijd toevoegen
tijdens het testen kan vanuit een andere terminal met
sudo screentimectl --user testkid add 30.
cargo build --release --workspace
Voor het overzetten naar een andere machine (zelfde soort systeem: Fedora/KDE Plasma
Wayland) hoef je niet op die machine te bouwen. packaging/package.sh bouwt hier de
release-binaries en verzamelt ze samen met het install-script en de systemd-unit in
één map dist/, zodat je daar één zip van kunt maken en versturen:
packaging/package.sh
cd .. && zip -r screentimectl-dist.zip dist # of: cd screenctrl && zip -r screentimectl-dist.zip dist
Op de doelmachine: unzip, en draai als root (de accounts van de kinderen moeten daar al bestaan):
cd dist
sudo ./install.sh
Het script installeert de binaries naar /usr/local/bin en de systemd-service, en
schrijft — alleen als er nog geen config bestaat — een voorbeeld
/etc/screentimectl/config.toml (uit config.toml.example, met [[users]]-blokken om
in te vullen). Vul daarna de echte gebruikers in en start de service:
sudo "$EDITOR" /etc/screentimectl/config.toml # vul [[users]] in, 1 blok per kind
sudo systemctl enable --now screentimectld
Draai je install.sh nogmaals op een machine die al een ingevulde config heeft (bv. om
nieuwe binaries te installeren), dan laat het script die config staan en herstart het de
service automatisch zodat de nieuwe binaries meteen actief zijn. Vereist op de
doelmachine: usermod (shadow-utils, standaard aanwezig), kdialog (voor de popup) en
systemd-logind met D-Bus (standaard op Fedora/KDE) — het script waarschuwt als iets
daarvan ontbreekt.
sudo install -m 755 target/release/screentimectld /usr/local/bin/screentimectld
sudo install -m 755 target/release/screentimectl /usr/local/bin/screentimectl
sudo mkdir -p /etc/screentimectl
sudo cp packaging/config.toml.example /etc/screentimectl/config.toml
sudo "$EDITOR" /etc/screentimectl/config.toml # vul [[users]] in, 1 blok per kind
sudo chmod 600 /etc/screentimectl/config.toml
sudo cp packaging/screentimectld.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now screentimectld
Elk commando werkt op één gebruiker, aangegeven met --user <naam> vóór het
subcommando (moet overeenkomen met een target_user uit [[users]]):
sudo screentimectl --user kind1 add 30 # voeg 30 minuten toe aan het budget van vandaag
sudo screentimectl --user kind1 remove 15 # trek 15 minuten af van het budget van vandaag (alias: subtract)
sudo screentimectl --user kind1 lock # vergrendel scherm + account direct, los van resterende tijd
sudo screentimectl --user kind1 unlock # ontgrendel het account weer (resterende tijd blijft gelijk)
sudo screentimectl --user kind1 status # toon resterende tijd
journalctl -u screentimectld -f