Historie von LTSP #
Nachdem LTSP seit einigen Jahren mehr oder weniger ohne große Änderungen sehr gut und recht stabil lief, hat sich einer der Entwickler einen Ruck gegeben, und das Ganze nochmal neu durchdacht. Dazu kam es sozusagen zu einem Fork des Projektes.
Das ursprüngliche (ganz alte) LTSP war eine Art eigene Distribution, die per Netzwerkserver an Thin Clients ausgeliefert wurde. Diese war etwas besonders und nicht ganz so leicht zu pflegen, aber im Grunde lief das schon immer gut und stabil.
Ein grosser Schritt war das sogenannte Projekt Muecow, das dann in eine neue Version (ich glaube, es war ab LTSP 4) mündete. Hierzu wurden alle Besonderheiten von LTSP in Debian-Pakete gepackt und es ergab sich, das es dann sowohl für den Server als auch für die Client-Systeme (die idealerweise auf dem Server in einem chroot-Verzeichnis "lebten" Debian-Pakete hgabe, die man mit der normalen Debian-Distribution installieren und upgraden konnte.
Die letzte Version aus diesem Entwicklungszweig ist LTSP 5, das auch in Debian 10 Buster enthalten ist.
Danach wurde LTSP von einem der Maintainer völlig neu entwickelt. Ab Debian 11 Bullseye ist nur noch das neue LTSP enthalten, dessen Eindrücke mich dazu gebracht haben, diese Seite hier zu schreiben.
Unterschied altes und neues LTSP #
Der Haupt-Unterschied ist, das die Clients nicht mehr "thin", sondern "fat" sind. Das bedeutet, das die Applikationen der Benutzer nicht mehr auf dem zentralen Server laufen (also von allen Benutzern gleichzeitig auf einem einzigen System), sondern die CPU des Clients wird benutzt und dieser bekommt lediglich sein Dateisystem vom Server geliefert.
Beide Systeme haben meiner Meinung nach Ihre Vor- und Nachteile. Ich denke im Prinzip schon, das man mit heute verfügbaren Client-Rechnern mit dem neuen LTSP meistens besser fährt. Wer dort aber wirklich preiswerte Hardware nutzen möchte, ist mit dem alten LTSP besser und flexibler dran. Inwiefern man das alte System auf Dauer überhaupt noch nutzen kann und ob es jemand pflegt, weiss man allerdings zum jetzigen Zeitpunkt noch nicht (aber das weiss man bei Open Source ja nie).
Ein Problem ist meiner Meinung nach die Namensgebung. Ich hätte dem neuen System ja einen anderen Namen gegeben - aber gut. Nun weiss man nie, wovon man spricht, wenn man "ltsp" sagt oder googelt.
erste Schritte #
erzeugen eines Client-Systems im chroot #
Zuerstmal habe ich auf einem bestehenden Server ein neues chroot Verzeichnis angelegt. Dafür gibt es kein LTSP-Skript mehr, was aber auch Quatsch ist, weil die Debian Bordmittel das bereits hervorragend machen.
Alles in allem habe ich das chroot mit den folgenden Befehlen angelegt. Dabei bin ich von der oben verlinkten Anleitung ausgegangen. Ich habe ein paar eigene Pakete hinzugefügt (aptitude, joe), die ich persönlich mag und ein paar Dinge aus der Ubuntu-Anleitung debianisiert.
mkdir /srv/ltsp cd /srv/ltsp debootstrap --include=locales,aptitude,joe bullseye arbeitsplatz apt install --no-install-recommends linux-generic initramfs-tools echo arbeitsplatz > /etc/hostname passwd dpkg-reconfigure locales apt install software-properties-common apt install ltsp apt install xfce4 apt install linux-image-amd64 exit
Ich habe sodann auf meinem Serversystem die LTSP Kommandos (die sogenannten Applets) hintereinander aufgerufen, um die Konfiguration der Serverdienste zu erzeugen. Dabei habe ich den Eindruck bekommen, das es sich bei diesen Applets um einfache Shell-Skripte handelt, die geeignete Konfigurationsdateien erzeugen, die die eigentlichen Serverdienste konfigurieren, die dann das LTSP-System ausmachen.
vorbereiten der Images, die das Client-System enthalten #
ltsp image
Sollte squashfs-Images erzeugen, die von LTSP benutzt werden können. Allerdings funktioniert ein reines chroot erstmal genausogut und ist flexibler bei Änderungen (am Anfang ändert man ja so einiges). Das Image in eine echte Image-Datei umzuwandeln, ist wahrscheinlich besser für die Performance. Vor allem erlaubt es auch, diese Imagedatei direkt zum Start zum Client zu transferieren. Aber das mache ich erst später. Also braucht man dieses Apllet erstmal gar nicht aufrufen.
ltsp kernel
Hier werden die vorhandenen Images (also die in /srv/ltsp) durchgegangen und es wird jeweils ein Kernel und eine initrd gebaut, die zum booten verwendet werden. Diese initrd- und Kernel-Dateien werden dann in das TFTP-VErzeichnis (/srv/tftp) kopiert, so das sie beim booten dort vom PXE-Lader gefunden und abgeholt werden können.
ltsp initrd
Hiermit wird ein image lts.img erzeugt, das als zusätzliche LTSP-Schicht über das Basisimage drübergelegt wird. Soweit ich das bisher verstanden habe, liegt hier drin der Unterschied zwischen einem nackten Debian System und einem LTSP, das für mich und meine Benutzer eingerichtet ist.
Ich denke, über den Inhalt dieses Images und seine Macht wird noch mehr herauszufinden sein.
vorbereiten der benötigten Serverdienste #
ltsp nfs
Dieses Kommando konfiguriert lediglich den NFS-Server, der ggf. ein chroot-Image freigeben soll. Für eine gute Sicherheit wird übrigens empfohlen, nicht nfs zu benutzen, das bei allem Komfort quasi keine Sicherheitsschicht bietet. Dafür bieten sich vorgefertigte Images für das Basissystem und ssh zum Zugriff auf Arbeitsverzeichnisse (/home) an.
ltsp dnsmasq
Dieses Skript erzeugt eine Datei "/etc/dnsmasq.d/ltsp-dnsmasq.conf", mit der ein lokaler DHCP-Server konfiguriert wird, wenn das Paket dnsmasq installiert ist. In meinem Fall habe ich einen zentralen dnsmasq im Netzwerk. Ich konnte allerdings die interessanten Zeilen aus der Konfiguration herausholen und dann in meine Serverdatei eintragen.
Dummerweise konnte ich meinen eigenen Arbeitsplatz nur per EFI zum Laufen bringen. Das legacy-Booten war nicht dazu zu bekommen, auf einem anderen Rechner als dem DHCP-Server seine Dateien abzuholen und das funktionierte auch nicht richtig. Nach einem längeren Kampf habe ich das erstmal aufgegeben und beschlossen, das das BIOS wohl buggy ist. Mit EFI klappte alles wunderbar.
Die DHCP-Konfiguration sorgt dafür, das zuerst iPXE als flexiblerer Bootloader geladen wird, dieses dann ein Startskript "ltsp/ltsp.ipxe" bekommt und dieses erzeugt dann ggf. ein Menü meiner LTSP-Images (mit ggf. noch anderen Einträge wie ein Memtext oder ähnliches) und startet den Linux-Kernel, den wir vorher konfiguriert hatten.
Damit das booten richtig funktioniert, setzt das neue LTSP auf ipxe. Eigentlich kann man den Linux-Kernel auch direkt booten (also dem PXE-ROM des Arbeitsplatzes direkt den Kernel angeben, damit er den lädt und ausführt. Flexibler ist es jedoch, ipxe einzusetzen. Also habe ich mit
ltsp ipxe
selbiges konfiguriert. Dieser Befehl kopiert die iPXE Binaries in das Verzeichnis des TFTP-Servers (liegt heutzutage alles unter /srv/...) und erzeugt vor allem eine an meine vorhandenen Images angepasste ltsp/ltsp.ipxe.
In meinem Fall war die Besonderheit, das ich von einem anderen als dem DHCP-Server meine Kernel-Images laden möchte. Das scheint dieses Skript von LTSP nicht so hinzubekommen. Ich musste folgende Zeile oben einfügen (und die andere, die die Variable sonst erzeugt, auskommentieren):
set srv 192.168.3.23
Nach Abschluss all dieser Punkte hat mein System dann das erste mal gebootet. :-)
Zusätzliche Konfigurationen #
root-Zugang #
Mit diesem Punkt habe ich tatsächlich eine ganze Weile gekämpft. Ich habe keinen root-Zugang auf dem System bekommen. Dazu kommt, das ich tatsächlich etwas darüber gelernt habe, wie das alles funktioniert. Mein Terminalserver hat nämlich zwei Besonderheiten: Zum einen logge ich mich normalerweise per LDAP ein. Ich habe also weder Benutzer- noch Passworteinträge auf dem Server. Das scheint die LTSP-Konfiguration etwas zu verwirren, was die möglichen Benutzer betrifft (dazu später wohl mehr). Zum anderen ist es wohl so, das zum Login - also zur Überprüfung des Passworts - ein ssh-Login auf dem Terminalserver durchgeführt wird. Da mein Server aber so konfiguriert ist, das man sich als root nicht per ssh mit einem Passwort einloggen kann, geht das dann also folgerichtig auch auf den Clients nicht.
Die Lösung war dann, einen User anzulegen, der auch in der passwd-Datei des Servers verzeichnet ist, diesen (ebenfalls auf dem Terminalserver) in die Gruppe sudo aufzunehmen und im chroot das sudo-Paket zu installieren.
Eine andere Lösung war, im chroot seinerseits openssh zu installieren und sodann einen Public key in /root/.ssh/authorized_keys zu installieren (bitte Zugriffrechte beschneiden, siehe entsprechende Anleitungen). Was ich gleichzeitig noch dazu gelernt habe ist, das LTSP einige System Services auf den Clients abschaltet (Welche genau, sieht man in einer Datei 56-mask-services.sh im Quellcode). Dazu gehört auch ssh. Also habe ich in die globale Konfigurationsdatei /etc/ltsp/ltsp.conf auf dem Server folgendes eingefügt, um den Service wieder zu aktivieren:
KEEP_SYSTEM_SERVICES="ssh"
Die dritte Lösung habe ich dann in der manpage zu ltsp.conf als Beispiel gefunden. Ich benutze eine POST_INIT_... Einstellung, um mittels eines Shell-Befehles (sed) einen Passwort-Hash in /etc/shadow zu setzen. Die Passwörter sind nämlich im LTSP-System alle gelöscht, weil das Login nur über das pamltsp-Modul (bzw. in meinem Fall über LDAP) laufen soll. Mit diesem Trick kann man allerdings nach der Init-Phase des bootens für einen einzelnen Benutzer ein Passwort für Notfälle wie meinen setzen.
Gelernt habe ich also bis hierhin, das die Liste der Benutzer und Gruppen vom Terminalserver kopiert werden. Das geschieht mit "ltsp initrd", was man also nach Änderungen hieran neu ausführen sollte. Auch gelernt habe ich, wie man Services auf den Clients aktiviert (und deaktiviert).
beschreibbarer Client #
Bei aller Liebe zum Detail, mit dem Debian Linux auch für den Einsatz in chroot-Umgebungen entwickelt wurde, gibt es doch ein paar Dinge, die man einfacher (oder überhaupt nur) auf einem echten, lebenden System installieren kann. Deshalb wäre es schön, das chroot read-write in einem solchen mounten zu können. Anleitungen hierzu gibt es unter https://github.com/ltsp/ltsp/wiki/chroots und https://ltsp.org/man/ltsp-image/.
Trick eins hierzu steht auf der manpage von ltsp image und besteht darin, das Images in einem virtuellen KVM-System zu starten.
Trick zwei habe ich davon abgeleitet (und dann später auch im LTSP-Wiki gefunden) und besteht darin, in das Bootmenü in ltsp.ipxe einen weiteren Eintrag einzufügen, der es erlaubt, das System direkt und nicht als LTSP zu booten. Es wird also nur das Image-VErzeichnis read-write gemountet und nicht das per SquashFS verschachtelte Verzeichnis aus dem read-only, Image, der LTSP-initrd-Schicht und einer reads-write RAM-Disk, das einen LTSP-Client ausmacht. Der Code in ltsp.ipxe sieht bei mir dazu so aus:
# -TB- :rw_client set img arbeitsplatz set cmdline_method rw root=/dev/nfs nfsroot=${srv}:/srv/ltsp/${img} set cmdline ${cmdline_method} kernel /ltsp/${img}/vmlinuz initrd=initrd.img ${cmdline} initrd /ltsp/${img}/initrd.img boot || goto failed
Um nicht versehentlich das normale LTSP-Verzeichnis read-write zu mounten, sollte man in /etc/exports nur für den spezifischen Client das VErzeichnis rw freigeben. Es empfiehlt sich aus Gründen der Sicherheit, dieses Eintrag in exports wieder auszukommentieren, wenn man das nicht mehr braucht.
Eine interessante Frage wäre noch, ob man das verewigen kann, so das es beim erneuten Aufruf von "ltsp ipxe" nicht wieder überschrieben wird.