!!! DisklessClient

Im Prinzip geht es hier darum, einen Rechner, der keine eigene
Festplatte hat, über das Netzwerk von einem Fileserver aus booten
zu lassen. Ansonsten soll der Rechner aber wie ein normaler Rechner
installiert sein, d.h. alle Applikationen laufen auf dem Client,
der Server ist nur für die Festplatte zuständig. Wer sich für einen
noch einfacheren Client interessiert, der nur noch
Bildschirmausgaben des Servers macht, findet auf der Seite
LinuxTerminalServer Informationen hierzu (z.B. LTSP). Ein älterer
und etwas allgemeiner gehaltener Artikel zum Thema ist
BootenVomNetzwerk.

Die Tatsache, daß die Preise für [ThinClient]s teilweise höher liegen
als die für billige (aber komplette) PCs und die Tatsache, daß ich
rechenintensive Applikationen benötige, hat mich auf den Gedanken
gebracht, die eigentliche Applikation auf dem Client zu belassen.
Dort benötigen wir dann einen normalen Prozessor (im Gegensatz zu
embedded Prozessoren wie z.B. dem 266 MHz-Geode, die in [ThinClient]s
oft benutzt werden) und mehr Speicher. Der Nachteil ist, daß man
wieder einzelne Systeme hat (wenn auch auf einem Rechner), die
einzeln gewartet werden müssen (wenn man hierfür keine intelligente
Lösung findet, was ich jedoch vorhabe).

Ein Vorteil eines Client-Systems zu einem LTSP-System ist, daß wir
keine besonderen Pakete und Installationen benötigen. Im Grunde
haben wir ja ein ganz normales Standard-Debian-System. Lediglich
ein paar Konfigurationen sind zu ändern. Dazu gehen wir jetzt
zuerst durch die einzelnen Dienste, die wir auf dem Server
aufsetzen müssen und richten danach einen einfachen Client ein, den
der geneigte Leser dann nach belieben anpassen kann. Als letztes
gibt es Änderungen, die man benötigt, um auch mehrere Clients
effektiv verwalten zu können.


!! Einrichtung des Servers

! DHCP-Server

Der DHCP-Server gibt einem Client, der gar nicht weiss, wo er im
Leben steht (weil er keine Festplatte hat, die es ihm sagt), eine
erste Orientierung. Er gibt ihm seine Netzwerkkonfiguration und
Informationen darüber, wie es weitergeht, bzw. wo er ein
Betriebssystem herbekommt.

Man kann die folgende Konfiguration ohne große Probleme in einen im
Netzwerk vorhanden DHCP-Server (z.B. KrefixLinux bzw.
DHCPServerMitDNS) einpflegen, man kann aber auch einen DHCP-Server
auf dem Terminalserver installieren. Es ist ledglich zu beachten,
daß man nicht beides tut (es sollte immer nur einen DHCP-Server in
jedem Netzwerksegment geben).

Auf dem Server folgendes in die __dhcpd.conf__ (z.B. hinten
anfügen):

{{{
group {
  allow bootp;
  server-name "terminalserver.bayen.loc";
  next-server terminalserver.bayen.loc;
  option root-path "192.168.201.2:/var/nfs/sarge";
  filename "pxelinux.0";
  option routers 192.168.201.1;
  option domain-name-servers 192.168.201.1;
  option domain-name "bayen.loc";

  host client1 {
    fixed-address 192.168.201.5;
    hardware ethernet 00:aa:bb:cc:dd:ee;
    option host-name = "client1";
  }

  host qemu {
    fixed-address 192.168.201.5;
    hardware ethernet 00:47:11:47:11:01;
    option host-name = "qemu";
  }
}
}}}

! TFTP-Server

Mittels des tftp-Protokolls holt sich der Client laut den vom
DHCP-Server erhaltenen Daten eine Bootdatei, die er dann ausführt.
Diese Bootdatei soll in unserem Beispiel __pxelinux__ sein (eine
Netzwerk-Variante des Bootloaders __syslinux__).

{{{
  aptitude install tftpd-hpa syslinux
  aptitude install kernel-image-2.6-686
}}}

''(Soll auf dem Terminalserver ein anderer Kernel als auf den
Clients laufen, muss ggf. die GRUB-Konfiguration des Servers
angepasst werden.)''

Nun wird im Verzeichnis ''/var/lib/tftpboot'' einiges installiert:

{{{
  cd /var/lib/tftpboot
  cp /usr/lib/syslinux/pxelinux.0 .
  mkdir pxelinux.cfg
  mkdir boot
}}}

Nun muss für jeden Server die hexadezimale IP-Adresse
(__C0A8C98C__ für 192.168.201.140, kann z.B. mit ''gethostip''
festgestellt werden) festgestellt werden und im Verzeichnis
''pxelinux.cfg'' eine Datei dieses Namens angelegt werden. Dort
kommt die Bootkonfiguration für pxelinux hinein:

{{{
  label linux
        kernel boot/linux...
        append vga=normal initrd=boot/initrd.img-2.6... ramdisk_size=9424 root=/dev/nfs nfsroot=192.168.201.2:/var/nfs/sarge ip=dhcp devfs=mount rw  --
}}}

In das boot-Verzeichnis kommen später der Kernel und die initrd
hinein (nach aufsetzen des Systems).

! NFS-Server

Hierzu muss in einem vom NFS-Server (per ''exports''-Datei)
freigegebenen Bereich ein root-Verzeichnis angelegt werden. Dort
wird eine Debian-Installation hineingelegt und diese angepasst:

{{{
  aptitude install nfs-kernel-server
  mkdir -p /var/nfs/sarge
}}}

Dann installiert man ein DeBootstrapBasisSystem in dieses neue
Verzeichnis. Dabei nimmt man folgende besondere Konfigurationen
vor:

{{{
  echo "terminalserver:/var/nfs/testclient / nfs defaults 0 0" >>etc/fstab
  echo "none /proc/bus/usb usbfs defaults 0 0" >>etc/fstab
  cp -a /lib/modules/2.6.8-2-686 lib/modules/     # (ist diese Zeile noch nötig, wenn der Kernel später installiert wird? -- TB)
  aptitude install udev        # Alternativ Devices mit MAKEDEV anlegen oder devfs benutzen
  aptitude install initrd-netboot-tools
  aptitude install kernel-image-2.6-686
}}}

Nun kopiert man dem Kernel und die Initrd nach
''/var/lib/tftpboot/boot'', passt die pxe-Konfiguration auf die
Kernelversion an und der Kernel sollte booten können.

{{{
  cp boot/vmlinuz* /var/lib/tftpboot/boot
  cp boot/initrd* /var/lib/tftpboot/boot
}}}

In __/etc/exports__:

{{{
  /var/nfs/testclient/ 192.168.201.5(rw,no_root_squash,sync)
}}}

! Konfigurieren der initrd / Debugging

Damit der Kernel nun auch wirklich das root-Dateisystem vom NFS
holt, sind u.U. noch einige Anpassungen in der initrd nötig. Die
Grundlagen hierzu werden bereits vom Paket
'''initrd-netboot-tools'' gelegt, allerdings läuft das nicht immer
von ganz alleine. Bei Debugging hat es sich als günstig erwiesen,
die initrd öfters neu zu erstellen, um Bootskripten anpassen zu
können. Hierzu geht man in das chroot-Jail (wo auch die o.a. Pakete
installiert wurden, ändert die Konfigurations-Dateien und aktiviert
dann den Kernel mit

{{{
  dpkg-reconfigure kernel-image-2.6.8-2-686
}}}

innerhalb des chroot-Jail und

{{{
  cp /var/nfs/testclient/boot/initrd.img-2.6.8-2-686 /var/lib/tftpboot/boot/
}}}

außerhalb desselben (also direkt auf dem Terminalserver). Danach steht einem Reboot des Clients nichts im Wege.

Sinnvoll kann z.B. sein, in der Datei ''/etc/lessdisks/mkinitrd/install_scripts/90_mount_nfs_root'' ganz
unten das mounten von ''devfs'' auszukommentieren, wenn man das
neuere ''udev'' nutzen will.

!! Einrichtung des Clients

Wenn wir eine Netzwerkkarte habe, die ein Bootrom hat oder ein
Motherboard mit integrierter Netzwerkkarte, kann man normalerweise
im BIOS das LAN als Bootdevice angeben. Bei einem älteren Rechner
oder einer zusätzlich eingebauten Netzwerkkarte kann man mit Hilfe
von [Etherboot|http://etherboot.sourceforge.net] eine Bootdiskette
oder Boot-CD erzeugen. Den so vorbereiteten Client schaltet man nu
ein und los gehts. Beim ersten Mal wird das Booten ggf. noch nicht
klappen, weil der DHCP-Server die Mac-Adresse noch nicht kennt.
Diese sollte dann bei dem (gescheiterten) Bootversuch angezeigt
werden und kann daraufhin von Hand in der DHCP-Konfiguration
eingefügt werden.

!! Besonderheiten für bestimmte Softwarepakete

Wer __udev__ nutzen will, sollte wie oben beschrieben das Mounten
von ''devfs'' verhindern (ob es läuft, sieht man am sichersten in
''"/proc/mounts"''), dann das System booten und dort folgendes
machen:

{{{
  aptitude install udev
  cd /dev
  MAKEDEV update
  reboot
}}}

Um einen __X-Server__ starten zu können, empfiehlt sich ''udev''.
Wenn man das __psmouse__-Modul lädt, sollte das Device
''/dev/input/mice'' auftauchen. Dann kann man den X-Server
installieren:

{{{
  aptitude install x-window-system
}}}

Leider wird die Konfiguration so nicht laufen. Hier gibt es einen
Bug im Debian-X-Server Konfigurationstool, der bei NFS-Laufwerken
auftritt. Man muss in der Datei ''/usr/bin/dexconf'' ganz unten
eine Zeile vor der ''rm ...''-Zeile einfügen:

{{{
  exec 4>/dev/null
}}}

Dann den X-Server neu konfigurieren mit:

{{{
  dpkg-reconfigure xserver-xfree86
}}}

Um ein vernünftiges Desktop-System mit __KDE__ zu installieren, macht man am besten folgendes:

{{{
  aptitude install xserver-xfree86
  aptitude install kde kde-i18n-de
}}}

Um KDE per __kdm__ zu starten, muss in der Datei ''/etc/kde3/kdm/kdmrc'' {{{RandomDevice=/dev/urandom}}} gesetzt werden. (siehe [KDE Bug-Report|http://bugs.donarmstrong.com/cgi-bin/bugreport.cgi?bug=298254]).

! QEMU-Client mit netboot

Auf http://rom-o-matic.net/ einen Treiber für eine ne-Karte
(ns8390) z.B. als .liso-Image herunterladen und dann qemu starten
mit

{{{
  /usr/local/bin/qemu -m 128 -macaddr 00:47:11:12:00:01 -boot d -cdrom ~/qemu/etherboot-5.4.1-ns8390.iso
}}}

Fertig! :-)



! Ubuntu (?)

Leider habe ich nes nicht hinbekommen, ein Ubuntu-System
netboot-fähig zu machen. Der X-Server war nicht zu konfigurieren.
:-( Dennoch hier meine Notizen zum Thema, da ich dieses sicherlich
nochmal aufgreifen werde...

Ob es überhaupt sinnvoll ist, Ubuntu per Netboot zu installieren,
bedarf auch noch einer Erörterung. Der Hautpvorteil von Ubuntu
liegt in der einfachen und automatischen Konfiguration. Ebendiese
wollen wir allerdings dem Benutzer eigentlich abnehmen und sie
zentral auf dem Server belassen. Man müsste bei Ubuntu evtl. einige
Dinge herausnehmen (alles, was Root-Zugriff erfordert), um den
Benutzer nicht zu verwirren...

Eine gute Anleitung zum Thema gibts auf der Seite
https://wiki.ubuntu.com/Installation/OnNFSDrive. Natürlich wird
auch auf dieser Seite wieder um den heissen Brei herumgetanzt, wenn
es um den Kernel (ggf. die intird) und den Bootvorgang geht. Da wir
diese Probleme jedoch gerade (oben für Debian) gelöst haben,
hindert uns keiner daran, beide Erkenntnisse zusammenzufassen. Dazu
erzeugen wir zuerst ein neues Verzeichnis, z.B.
'''/var/nfs/ubuntu''' für die Installation. Die eigentliche Arbeit
macht '''debootstrap''', da es sich bei Ubuntu ja technisch gesehen
um eine (besondere) Debian-Distribution handelt. Allerdings
benötigt dieses nicht nur einfach den Paket-Mirror, sondern auch
ein angepasstes Installations-Skript. Damit dieses für die
Ubuntu-Distributionen dabei ist, installieren wir erstmal von Hand
das debootstrap-Paket von Ubuntu (Link auf o.g. Seite, jedoch nicht
*tar.gz, sondern *.deb). Danach starten wir das Programm mit
entsprechenden Parametern. Das ist dann auch schon die Hauptarbeit

{{{
  cd /var/nfs
  dpkg -i /root/debootstrap_0.3.3.0ubuntu1_all.deb
  debootstrap breezy ubuntu/ http://archive.ubuntulinux.org/ubuntu
  chroot ubuntu
}}}

hostname, hosts und fstab erstellen wie auf
https://wiki.ubuntu.com/Installation/FromAnotherDistro beschrieben.
In __/etc/mkinitramfs/initramfs.conf__ eintragen: __BOOT=nfs__
und __NETOPTS="-o udp"__.

Kernel installieren:
{{{
  aptitude install linux-image-686
  exit
  cp /var/nfs/ubuntu/boot/vmlinuz-2.6.12-9-686 /var/lib/tftpboot/boot/
  cp /var/nfs/ubuntu/boot/initrd.img-2.6.12-9-686 /var/lib/tftpboot/boot/
  (dann entweder Link auf Kernel-Image neu setzen oder Eintrag in pxelinux.cfg entsprechend anpassen)
}}}

Am besten noch den nfs-Server restarten und dann kann's losgehen!

Die Textkonsole unseres Netboot-Ubuntu läuft nun. Dann als nächstes vielleicht(?)

{{{
  aptitude --without-recommends install ubuntu-standard ubuntu-desktop
}}}

!! Synergien für mehrere Clients

Meine Überlegung: Bisher haben wir genau einen Client, der in genau
einem Verzeichnis "residiert". Wollen wir einen zweiten haben,
müssten wir dieses Verzeichnis komplett kopieren. Sinnvoll wäre,
wenn man den Root-Baum readonly an mehrere Clients geben kann und
die beschreibbaren Teile (''/var'' und ''/home'', evtl. ''/etc'')
gesondert mounten würde. Diese könnten dann für jedes System
angepasst sein. Auf der anderen Seite müsste ein Multitaskingsystem
theoretisch an vielen Stellen auch damit fertig werden, wenn
mehrere Clients gleichzeitig das gleiche Verzeichnis read-write
mounten.

Um die Abgrenzung vorzunehmen, sollte man den
[Filesystem Hierarchy Standard|http://www.pathname.com/fhs/]
beachten. Einen deutschen (etwas älteren) Artikel zum Thema gibts im
[Linux Magazin|http://www.linux-magazin.de/Artikel/ausgabe/1996/10/Standard/standard.html]

Man kann nun die o.g. Verzeichnisse gesondert exportieren und beim
Bootvorgang des Clients über das normale Root-Verzeichnis (das nur
read-only ist) mounten. Hierbei entsteht das Problem, daß man für
jeden Client eine komplette Kopie von ''/etc'' benötigt.
Installiert man nun auf dem Hauptsystem ein neues Paket (oder ein
Update), so müssen die Kopien auch irgendwie geupdatet werden. Dies
könnte man vielleicht mit sowas wie ''rsync'' oder ein paar
Skripten, die die Änderungsdaten auswerten, machen. Eine
Alternative ist, UnionFS zu benutzen, um das gesamte
Read-Only-System "beschreibbar" zu machen.

Eine sehr gute Lösung, um dieses Problem anzugehen, scheint der [Copy-on-Write NFS-Server|http://www.russross.com/CoWNFS.html] zu sein. Hiermit kann man mehrere NFS-Freigaben quasi "übereinanderlegen".


!! Links zum Thema:

* http://www.ks.uni-freiburg.de/download/studienarbeit/SS05/07-05-DebDiskless-PMichels/07-PMichels-DebDiskless.pdf
* [http://zeewier.blub.net/~jdv/pxe-debian.html]
* http://www.debian.org/releases/stable/i386/ch04s06.html.de
* https://wiki.ubuntu.com/Installation/OnNFSDrive
* http://etherboot.sourceforge.net/

[{Tag ThinClient}]