Installation de zéro¶
Version
Page écrite pour pupitre 0.1.35-1.
Cette page mène d'une machine vide à une salle servie : la VM, le réseau, le paquet (tout fait ou construit depuis les sources), la configuration, le premier boîtier, les comptes élèves, la console et la vérification. Elle renvoie aux pages de Fonctionnement interne et aux notes d'installation du dépôt, en anglais, pour le détail, au lieu de les recopier. Les fonctions récentes portent la mention « (depuis 0.1.N) » : si votre paquet est plus ancien, voyez Versions et fonctionnalités.
Prérequis¶
| Quoi | Exigence | Pourquoi |
|---|---|---|
| Système | Debian 13 (trixie), et lui seul | Le paquet dépend de systemd (>= 254) : l'unité de siège utilise RestartSteps= et RestartMaxDelaySec=, absents de Debian 12. |
| Hyperviseur | KVM avec libvirt | Celui que décrit cette page. Un autre hyperviseur doit offrir une carte en pont sur le VLAN des boîtiers. |
| Réseau | Une carte de la VM en pont, sur le même VLAN que les boîtiers | Voir plus bas : ni NAT, ni routage. |
| Commutateur | Gigabit | Un siège en vidéo atteint environ 6 Mio/s ; treize sièges en vidéo à la fois font environ 660 Mbit/s. |
| Boîtiers | Dell Wyse 1010, adresse par DHCP | pupitre ne sert pas de DHCP : celui du VLAN donne leur adresse aux boîtiers. |
Le détail du réseau, des débits et du dimensionnement est sur la page Architecture et réseau.
Créer la VM¶
Ressources¶
Tableau indicatif, le même que dans Architecture et réseau, où se trouve la règle de calcul :
| Sièges | vCPU | Mémoire | Disque | Débit maximal vers le serveur |
|---|---|---|---|---|
| 5 | 2 | 8 Go | 30 Go | ≈ 255 Mbit/s |
| 10 | 4 | 16 Go | 40 Go | ≈ 510 Mbit/s |
| 15 | 6 | 32 Go | 50 Go | ≈ 765 Mbit/s |
| 20 | 8 | 32 Go | 60 Go | ≈ 1 020 Mbit/s, au-delà d'un lien à 1 Gbit/s |
Le débit maximal est celui où tous les postes lisent une vidéo en même temps ; en bureautique,
comptez environ 2,3 Mbit/s par poste. Le démonstrateur (tools/demo-vm.sh) se contente de 2 vCPU,
4 Go et 20 Go. Au-delà de 15 sièges, le nombre par défaut depuis 0.1.35, réglez seats dans
/etc/pupitre/pupitre.conf (seats = 0 lève la limite).
La mémoire se dimensionne sur le navigateur, pas sur le bureau : un bureau au repos coûte de 128 à 162 Mio de plus par siège, mais Firefox ouvert sur une seule page en ajoute environ 590 Mio.
Compression mémoire zram¶
zram compresse en mémoire les pages froides des sièges (environ 5 pour 1 pour un bureau au repos) et permet de tenir avec moins de mémoire que le tableau. Rien n'est posé par le paquet :
sudo apt install systemd-zram-generator. Ce paquet seul change déjà l'échange de la machine : Debian livre une section[zram0]nue, qui crée tout de suite un périphérique zram de la moitié de la mémoire, compressé enlz4.- Copiez les deux fichiers livrés par pupitre, qui passent à
zstdet à une taille par siège :/usr/share/pupitre/zram-generator.confvers/etc/systemd/zram-generator.conf, et/usr/share/pupitre/99-pupitre-zram.confvers/etc/sysctl.d/. Ajustezzram-sizeà environ 500 Mio par siège, sans dépasser la moitié de la mémoire. - Posez
PUPITRE_MEMOIRE=1dans un drop-in depupitre-seat@.service(voir Les sièges) : chaque siège reçoit une limite soupleMemoryHighde (mémoire moins 2048 Mio) divisée parPUPITRE_SEATS(15 par défaut), jamais moins de 512 Mio. Un nombre à la place de 1 fixe la limite à la main, en Mio. Il n'y a volontairement pas deMemoryMax, qui tuerait le navigateur d'un élève.
Pourquoi une carte en pont, jamais de NAT¶
Le boîtier trouve le serveur par une diffusion UDP sur le port 52330, et fast_tcp2 lui parle
en TCP brut sur une socket AF_PACKET, adressée à la MAC du boîtier. Une diffusion ne traverse ni
un NAT ni un routeur : la carte de la VM doit être dans le même domaine de diffusion que les
boîtiers. Le Wi-Fi ne se ponte pas. Le protocole n'a ni authentification ni chiffrement : un VLAN
réservé aux boîtiers et au serveur est préférable.
Installer Debian 13¶
Installez Debian 13 sans bureau (tâches « utilitaires usuels du système » et « serveur SSH »).
Ce choix compte : la brique dns-recherche-sure, allumée par défaut (depuis 0.1.33), suppose un
/etc/resolv.conf écrit par dhcpcd, ce que donne une installation sans bureau (ifupdown et
dhcpcd). Avec NetworkManager, elle refuse de s'allumer, l'installation continue et le dit.
La commande suivante reprend celle du démonstrateur (tools/demo-vm.sh), sans son fichier de
préréponses : l'installateur pose donc ses questions sur la console série. Ajustez le nom, la
mémoire, les vCPU et le disque à votre salle (voir la documentation de virt-install).
virt-install --connect qemu:///system --name pupitre --memory 4096 --vcpus 2 \
--disk size=20 --osinfo detect=on,require=off \
--location https://deb.debian.org/debian/dists/trixie/main/installer-amd64/ \
--extra-args "console=ttyS0,115200n8" \
--network network=default,model=virtio \
--graphics none
La carte en pont s'ajoute ensuite. La démo utilise macvtap en mode pont sur l'interface filaire de
l'hôte (ici enp1s0, à remplacer), décrite dans un fichier nic.xml :
<interface type='direct'>
<source dev='enp1s0' mode='bridge'/>
<model type='virtio'/>
</interface>
virsh -c qemu:///system attach-device pupitre nic.xml --persistent
Dans la VM, cette nouvelle carte prend une adresse par DHCP (une entrée iface ... inet dhcp dans
/etc/network/interfaces). Avec macvtap, l'hôte lui-même ne joint pas la VM par cette carte :
c'est pourquoi la démo garde aussi la carte NAT de libvirt, pour ssh et apt. Un pont Linux (br0)
sur l'hyperviseur convient aussi : voir la documentation de libvirt.
Le raccourci de démonstration
Depuis une copie du dépôt, tools/demo-vm.sh <interface filaire> :
- fait tout d'un coup : construit le paquet s'il n'y en a pas, installe Debian 13 sans question, ajoute la carte macvtap, installe pupitre et pointe sa configuration sur la bonne carte ;
- dure 20 à 40 minutes ;
- jamais pour une salle : il crée le compte
demo, mot de passepupitre, avec sudo sans mot de passe, connu de tous ; - prend le paquet le plus récemment modifié parmi
../pupitre_*_amd64.deb: vérifiez lequel.
Détails : A demo server in a virtual machine.
Chemin A : le paquet tout fait¶
Le paquet vient de l'artefact deb de l'intégration continue du dépôt (gardé un mois), ou d'une
construction locale (chemin B). Aucun dépôt APT n'est publié à ce jour. Le dossier dist/ du dépôt
ne contient qu'un ancien paquet 0.1.0-1 : ne vous en servez pas.
sudo apt install ./pupitre_0.1.35-1_amd64.deb
Le ./ dit à apt qu'il s'agit d'un fichier. Le paquet tire Xvfb, Xfce, LibreOffice et Firefox ESR
avec leurs menus en français, PulseAudio, nftables, FUSE, Unbound, et recommande LightDM et son
écran de connexion : n'installez pas avec --no-install-recommends, vous perdriez le mode élèves.
Ce que fait l'installation :
- crée l'utilisateur système
pupitre,/var/lib/pupitre/homeet/var/log/pupitre; - crée
/home/eleves, parent des répertoires des élèves ; - donne à
/usr/lib/pupitre/fast_tcp2les capacitéscap_net_rawetcap_sys_nice: socket brute et priorité temps réel, sans être root ; - allume
dns-recherche-sureà la première installation, ou une seule fois en venant d'une version antérieure à 0.1.33 ; un échec ne bloque pas l'installation ; - active
user_allow_otherdans/etc/fuse.conf, pour la clé USB ; - active et démarre
pupitre-nft,pupitre-manageretpupitre-web.
Les sièges (pupitre-seat@N) ne démarrent jamais seuls au boot : c'est le gestionnaire qui les
lance quand un boîtier s'annonce.
Chemin B : depuis les sources¶
Sur une Debian 13, depuis une copie du dépôt :
sudo apt install build-essential devscripts equivs dpkg-dev
sudo mk-build-deps -i -r debian/control
PATH=/usr/bin:/bin dpkg-buildpackage -us -uc -b
mk-build-deps installe les dépendances de construction déclarées dans debian/control
(debhelper, dh-python, pybuild, numpy, Pillow, pytest, libfuse3-dev, pkg-config). -us -uc : pas
de signature ; -b : paquet binaire seulement.
Pourquoi PATH=/usr/bin:/bin. Un python3 qui n'est pas celui du système en tête du PATH
(un virtualenv, pyenv, l'interpréteur d'un outil comme PlatformIO) casse pybuild avec
No module named build. L'intégration continue impose la même forme.
La construction compile fast_tcp2 et wyse_cle_fuse, puis lance les tests : les programmes de
test en C (make check) et pytest -m "not e2e". Un paquet qui se construit est donc un paquet
dont les tests passent ; DEB_BUILD_OPTIONS=nocheck les saute. Les tests seuls, sans construire :
PATH=/usr/bin:/bin python3 -m pytest -q tests -m "not e2e"
Les tests e2e demandent un vrai boîtier ou un navigateur piloté ; ils ne tournent ni à la
construction ni dans l'intégration continue.
Le paquet est déposé dans le répertoire parent du dépôt, ../pupitre_0.1.35-1_amd64.deb.
Copiez-le sur la VM et reprenez le chemin A.
Configuration¶
Le gestionnaire : /etc/pupitre/pupitre.conf¶
Un seul réglage est indispensable : interface, qui doit désigner la carte en pont.
[server]
interface = enp7s0
sudo systemctl restart pupitre-manager
| Clé | Défaut | Rôle |
|---|---|---|
[server] interface |
eth0 |
la carte sur le VLAN des boîtiers |
[server] ip |
vide : lue sur l'interface au démarrage | adresse du serveur |
[server] seats |
15 (depuis 0.1.35 ; 0 : sans limite) | nombre de sièges |
[server] enroll |
yes |
inscription automatique d'un boîtier inconnu |
[paths] seats_file |
/var/lib/pupitre/seats.json |
table MAC vers siège |
[web] listen, port |
127.0.0.1, 8080 |
console web |
[web] password_file |
vide | mot de passe de la console (depuis 0.1.14) |
Un siège déjà lancé garde l'interface et l'adresse avec lesquelles il a démarré. Après un
changement de l'une ou de l'autre, arrêtez puis redémarrez le gestionnaire (systemctl stop
arrête tous les sièges), ou redémarrez les sièges. Voir
Installing Pupitre, Configure et Gestionnaire.
Les sièges : variables PUPITRE_*¶
Le gestionnaire n'écrit dans /run/pupitre/seat-N.env que l'identité du siège (numéro, MAC et
adresse du boîtier, adresse du serveur, interface). Tout autre réglage d'un siège passe par un
drop-in systemd de son unité, jamais par pupitre.conf :
Pour le seul siège 3, le fichier est
/etc/systemd/system/pupitre-seat@3.service.d/reglages.conf :
[Service]
Environment=PUPITRE_CONNEXION=eleves
Environment=PUPITRE_FERMETURE=900
sudo systemctl daemon-reload && sudo systemctl restart pupitre-seat@3
Un drop-in du gabarit, dans /etc/systemd/system/pupitre-seat@.service.d/reglages.conf, vaut pour
tous les sièges (exemple : zram). Un drop-in
dans /etc/systemd/system appartient à l'administrateur : il survit aux mises à jour.
Les réglages usuels, avec leur défaut dans 0.1.35-1 :
| Variable | Défaut | Effet |
|---|---|---|
PUPITRE_CONNEXION |
fixe |
eleves : écran de connexion par siège (depuis 0.1.27) |
PUPITRE_FERMETURE |
600 s (0 : jusqu'à PUPITRE_GRACE) |
ferme la session d'un élève dont le boîtier reste éteint (depuis 0.1.27) |
PUPITRE_GRACE |
600 s (0 : jamais) | durée pendant laquelle le bureau est gardé sans boîtier (depuis 0.1.13) |
PUPITRE_LAYOUT |
fr |
disposition du clavier |
PUPITRE_QUIET_KEYS |
1 | journaux sans frappe ; jamais 0 sur le siège d'un élève |
Les autres variables sont posées par le lanceur ; ne les changez pas sans raison. La liste complète est dans Versions et fonctionnalités et Siège ; ce qui se personnalise (apparence, Firefox, briques) est sur la page Couches personnalisables.
Premier boîtier et enrôlement¶
Branchez un boîtier sur le VLAN et allumez-le :
- il diffuse son annonce sur UDP 52330, par salves espacées d'environ 10 s ;
- le gestionnaire cherche sa MAC dans
/var/lib/pupitre/seats.json; - inconnue et avec
enroll = yes, elle reçoit aussitôt le plus petit numéro de siège libre ; - le gestionnaire écrit
/run/pupitre/seat-N.envet démarrepupitre-seat@N; - le bureau, ou l'écran de connexion en mode élèves, paraît sur l'écran du boîtier.
Le bureau paraît en une dizaine de secondes. Le lanceur fait jusqu'à cinq essais d'ouverture du
lien (PUPITRE_ATTEMPTS) ; un siège qui n'y parvient pas peut attendre une dizaine de minutes avant
d'être relancé : le bouton Restart de la console va plus vite.
Une fois tous les boîtiers de la salle inscrits, passez enroll = no : un boîtier égaré restera
inactif, listé dans la console sous « Stations without a seat », où le bouton Assign lui donne un
siège. Sur un siège en session, le bouton Identify affiche « Seat N » en grand sur l'écran du
boîtier pendant 5 s, pratique pour étiqueter la salle. Voir
Gestionnaire, Enrolment.
Mode élèves et comptes (depuis 0.1.27)¶
Par défaut (fixe), un siège ouvre directement un bureau, sous l'utilisateur système
pupitre-seat-N, le même pour tous ceux qui s'assoient devant. En mode eleves, LightDM montre un
écran de connexion sur le siège, chaque élève ouvre une session sous son propre compte, et une
déconnexion ramène l'écran de connexion en une seconde environ, sans couper le lien avec le boîtier.
-
Créer les comptes. Aucun outil de pupitre ne le fait dans 0.1.35-1 : ce sont des comptes locaux, authentifiés par PAM. Il n'y a pas d'annuaire (AD ou LDAP).
sudo useradd -M -d /home/eleves/lea.cm1 -s /bin/bash lea.cm1 sudo passwd lea.cm1Le répertoire
/home/eleves/<compte>est créé en 0700 à la première connexion, depuis/etc/skel. Un nom de compte ne contient que lettres, chiffres,.,_et-. pupitre ne traite comme élève qu'un compte d'uid 1000 ou plus (UID_MIN), ni root, ni membre desudoou deadm: à la déconnexion, rien de ce que l'élève a lancé ne survit, et un adulte qui essaie un siège avec son propre compte ne perd que la session de ce siège. -
Redémarrer LightDM une fois, après la première installation du paquet. LightDM ne lit sa configuration qu'au démarrage, et le redémarrer ferme toutes les sessions ouvertes : c'est pour cela que le paquet ne le fait pas. Tant que ce n'est pas fait, les élèves ne peuvent pas se connecter et le siège journalise
LightDM started before pupitre's configuration. Hors temps de classe :sudo systemctl restart lightdm -
Activer le mode, siège par siège, par le drop-in
Environment=PUPITRE_CONNEXION=eleves(voir Les sièges), puisdaemon-reloadet redémarrage du siège.
Délai de fermeture. PUPITRE_FERMETURE (600 s) ferme la session d'un élève dont le boîtier
reste éteint ; le retour du boîtier annule le compte à rebours. PUPITRE_GRACE la borne : quand
PUPITRE_GRACE n'est pas 0, le délai effectif est le plus petit des deux, et
PUPITRE_FERMETURE=0 veut dire « jusqu'à PUPITRE_GRACE ».
La déconnexion ne relance ni Xvfb ni le lien avec le boîtier. Le détail est dans Siège, section Pupils' logins.
Console web et son mot de passe¶
La console montre l'écran de chaque siège en direct et pilote chaque boîtier. Elle écoute par
défaut sur 127.0.0.1:8080, sans mot de passe : seul quelqu'un qui a déjà un compte sur le
serveur l'atteint. Depuis votre poste :
ssh -L 8080:127.0.0.1:8080 admin@serveur
puis ouvrez http://127.0.0.1:8080.
Sur le réseau, un mot de passe est obligatoire (depuis 0.1.14). La console refuse de démarrer sur une adresse non locale sans mot de passe.
sudo pupitre-web --mot-de-passe /etc/pupitre/console-password
La commande le demande deux fois, sans écho, et écrit son empreinte (PBKDF2) en mode 600. Il n'y a
volontairement aucune option pour le passer en argument : il finirait dans ps et dans
l'historique du shell. Puis, dans /etc/pupitre/pupitre.conf :
[web]
listen = 192.0.2.10
password_file = /etc/pupitre/console-password
sudo systemctl restart pupitre-web
Ce que la console ne donne pas : pas de chiffrement (HTTP en clair), un seul mot de passe partagé, pas de comptes, pas de trace de qui a fait quoi. Gardez-la sur un réseau d'administration, ou derrière le tunnel ssh. Voir Console web, Security.

Vérification¶
systemctl is-active pupitre-nft pupitre-manager pupitre-web
systemctl status 'pupitre-seat@*'
journalctl -u pupitre-manager
Les trois services doivent répondre active. Dans la console, le siège passe à « In session », ce
qui veut dire que le lien avec le boîtier est prêt, pas qu'un élève est connecté. La preuve
finale reste l'écran du boîtier : bureau ou écran de connexion, clavier et souris qui répondent.
Mise à jour¶
sudo apt install ./pupitre_<nouvelle version>_amd64.deb
Depuis 0.1.27, une mise à jour ne coupe plus le lien des sièges : la règle nftables est rechargée en place, en une seule transaction. Le gestionnaire et la console redémarrent, les sièges continuent. Depuis 0.1.26, les répertoires des sièges restent à leur propriétaire.
Une mise à jour n'allume ni n'éteint aucune brique de contrôle, sauf dns-recherche-sure une seule
fois en venant d'une version antérieure à 0.1.33. En revanche, le contenu d'une brique déjà active
n'est pas rafraîchi : relancez sudo pupitre-controle activer <brique> pour chaque brique active
(voir Couches personnalisables).
Dépannage¶
Quand un poste ne répond pas, du geste le plus doux au plus fort :
| Geste | Ce qu'il fait | L'élève |
|---|---|---|
| Logs (console) | montre la fin d'un journal du siège, choisi dans une liste fermée : session, encodeur, bureau, Xvfb, entrées, curseur, clé (depuis 0.1.14) | ne perd rien |
| Relink (console) | refait le lien avec le boîtier sans toucher au bureau, en 15 à 60 s (depuis 0.1.14) | garde son bureau |
| Restart (console) | redémarre le siège ; le boîtier reste noir 30 à 90 s | perd sa session |
| Cycle d'alimentation | débrancher puis rebrancher le boîtier | perd sa session |
Un boîtier figé ne revient que par un cycle d'alimentation, et peut rester injoignable près d'une demi-heure après un figeage.
En ligne de commande :
journalctl -u pupitre-manageretjournalctl -u pupitre-seat@N(avec-fpour suivre) ;/var/log/pupitre/seat-N/:session.log,xvfb.log,desktop.log,input.log,encoder.log, et selon les fonctionscurseur.log,cle.log;- le journal du client
fast_tcp2, dans le même répertoire, lisible par root seul, les dix plus récents gardés (depuis 0.1.31) ; son chemin figure sur la lignefast_tcp2 stderr ->desession.log. Il contient des octets nuls : lisez-le avecgrep -a. La console ne le sert jamais.
RGPD. Aucun journal ne capture frappe, mouvement de souris, contenu d'écran ou de fichier par
défaut. Le client masque les rapports d'entrée sans aucun réglage (depuis 0.1.31). Ne mettez
PUPITRE_QUIET_KEYS=0 que sur une machine d'essai, jamais sur le siège d'un élève.
Deux comportements à connaître :
- un clavier ou une souris branchés après l'allumage du boîtier ne sont pas pris de façon fiable, et le boîtier peut redémarrer. Branchez-les boîtier éteint ; sinon, éteignez et rallumez le boîtier : le bureau reste ;
- un siège ne passe en
Failedque sur un échec rapide (fichier d'environnement manquant, affichage qui ne s'ouvre pas) ; un boîtier qui n'atteint jamais le flux laisse son siège enStarting.
Les limites connues sont listées dans Installing Pupitre, Known limits.
Préconisations¶
- Une VM dédiée, Debian 13 sans bureau, une carte en pont sur un VLAN réservé aux boîtiers et au serveur, un commutateur gigabit.
- Le paquet plutôt que la copie de travail. Le chemin B sert à construire le paquet, pas à faire tourner une salle : le paquet pose les capacités, la règle nftables et les unités systemd.
- Construire avec
PATH=/usr/bin:/bin, toujours, sansnocheck: les tests font partie de la construction. enroll = nodès que la salle est inscrite, et une étiquette sur chaque boîtier (Identify).- La console sur la boucle locale, jointe par ssh. Si elle doit être sur le réseau : mot de passe, et réseau d'administration.
- Les réglages de siège dans des drop-ins, jamais dans les fichiers du paquet : ils survivent aux mises à jour.
- Les mises à jour hors temps de classe. Elles ne coupent plus le lien depuis 0.1.27, mais elles redémarrent le gestionnaire et la console.
- Dimensionner la mémoire sur Firefox (590 Mio par élève), et envisager zram, dont la
configuration est livrée dans
/usr/share/pupitremais n'est jamais posée toute seule. - Commencer petit. Montez la salle par paliers et regardez la charge du serveur avant d'ajouter des boîtiers.