de en

Debian headless installation

Posted on Mo 28 Januar 2019 in Computer & Electronics

TLDR: Eine schön verpackte Version gibt es im github repo: github.com/philpagel/debian-headless

Nachdem mein alter Android Media-Server gestorben war habe ich mich nach einem Ersatz umgesehen. Mit der Android Lösung war ich nicht besonders glücklich, denn eigentlich wollte ich eh nur Kodi verwenden und es im Wesentlichen vom Handy steuern – einen Bildschirm hatte ich nie dauerhaft angeschlossen. Zudem bekommen Android-Geräte ja bekanntermaßen nur sehr begrenzte Zeit Updates, so dass man irgendwann mit einer potentiell unsicheren Uralt-Version dasteht.

Also lieber ein LINUX drauf machen. Debian natürlich. Zunächst mal habe ich mir geeignete Hardware gesucht und bin bei einem Lenovo ThinkCentre m600 tiny gelandet. Ist ein Auslaufmodell und war online günstig zu haben. Sieht sogar ganz hübsch aus und hat alles was der Mensch so braucht: 128GB SSD, 4GB RAM, eine Tastatur mit französischem Layout, die ich schon entsorgt habe und keinen Monitor. Und natürlich auch kein CD-Laufwerk – sowas braucht doch heute kein Mensch mehr.

Also ein Debian-netinst image runterladen, auf einen USB Stick spielen und los geht's. Theoretisch. Denn ich habe ja weder Tastatur, noch Monitor angeschlossen und stur wie ich nunmal bin will ich die Installation diesmal komplett headless über ssh durchziehen. Der Debian installer hat dafür ein nettes Feature namens 'network-console'. Das hat aber einen Pferdefuß: Nach dem Start vom Installationsmedium muss man zunächst interaktiv locale und keymap auswählen, das Netzwerk interface konfigurieren und den hostname festlegen, bevor man die network console aktivieren kann. Das führt die remote installation irgendwie ad absurdum.

Nun hat der Debian installer aber einen sehr praktischen Mechanismus namens preseeding. d.h. man kann ihm die Antworten auf alle oder einige der Konfigurationsfragen in einem File übergeben und diese werden dann nicht mehr gestellt. Im Extremfall kann man so die komplette Installation/Konfiguration automatisieren. Mir geht es aber nur darum, alles bis zum Start der network console zu automatisieren, damit ich dann interaktiv per ssh weitermachen kann.

Soweit so gut. Aber wie präsentiere ich dem installer nun dieses File? Eigentlich ganz einfach: es muss halt aufs Installationsmedium. Das ist aber leider ein ISO File und muss erstmal entpackt werden. Dann kann man das preseed File einfügen, alles wieder zusammenpacken – dabei darauf achten, dass das so erzeugte ISO Image auch bootfähig ist und los geht's.

Im Netz fand ich viele kluge Anleitungen, wie man sowas macht (die beste hier), aber in jeder davon fehlte irgendeinein Aspekt, den ich für mein Vorhaben brauchte – entweder wollte das Ganze dann nicht von USB-Stick booten, oder es blieb in Boot-Menü hängen oder das Preseeding war unvollständig etc. etc. Grumpf! Habe dann lange rumprobiert und Versatzstücke aus den unterschiedlichen Tutorials ausprobiert bis ich schließlich alles am laufen hatte.

Werkzeugkasten

Bevor es los geht stellen wir sicher, dass alle notwendigen tools auch installiert sind:

sudo apt-get install bsdtar syslinux syslinux-utils cpio genisoimage coreutils

Auspacken

Das Entpacken des ISO images geht relativ leicht:

# make a tmp folder
mkdir isofiles
# unpack the iso
bsdtar -C isofiles -xf debian-9.5.0-amd64-netinst.iso
# Set write permissions
chmod -R +w isofiles

Nun liegt alles schön im isofiles/ folder und dort können wir unser Installationsmedium nun nach Herzenslust modifizieren.

Boot loader config

Als erstes müssen wir das config File für den bootloader erstellen. Im Originalzustand wartet dieser nämlich bis zum Sanktnimmerleinstag auf die manuelle Auswahl der gewünschten Boot-Option: Also Install, Graphical install, Advanced options etc. Zu diesem Zeitpunkt ist aber noch keine remote-Kontrolle möglich. D.h. wir müssen sicherstellen, dass wir automatisch im Installer landen und brauchen die übrigen Optionen nicht.

Also erstmal cd isofiles und dort das File isolinux/isolinux.cfg löschen und ein Neues mit diesem Inhalt erzeugen:

DEFAULT install
    SAY Now booting the debian installer
LABEL install
    kernel /install.amd/vmlinuz
    append vga=788 initrd=/install.amd/initrd.gz --- quiet

Preseeding

Als nächstes brauchen wir ein preseeding File (preseed.cfg). Ein typisches für eine deutschsprachige Installation sieht so aus:

#### Contents of the preconfiguration file (for stretch)
d-i debian-installer/locale select de_DE
d-i console-keymaps-at/keymap select de
d-i keyboard-configuration/xkb-keymap select de

d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string wintermute 
d-i netcfg/get_domain string local
d-i netcfg/hostname string wintermute

d-i hw-detect/load_firmware boolean true

d-i network-console/password password install
d-i network-console/password-again password install
d-i network-console/start select continue

Man beachte, dass dieses File nur das Allernötigste enthält, um bis zum Start der remote console zu kommen. Man kann grundsätzlich viel mehr konfigurieren – in der oben verlinkten Debian Seite ist das wunderbar erklärt.

Nun müssen wir das preseeding File noch installieren – und das ist ein bisschen tricky, denn der Installer muss ja sehr früh Zugriff darauf haben. Mit anderen Worten, wir müssen es irgendwie in die init RAM-Disk bekommen. Und das geht so:

# initrd auspacken
gunzip install.amd/initrd.gz
# preseed file rein
echo ../preseed.cfg | cpio -H newc -o -A -F install.amd/initrd
# und wieder einpacken
gzip install.amd/initrd

MD5 sums aktualisieren

Und damit der Installer nicht meckert müssen wir nun die MD5 sums auf den neusten Stand bringen:

    find ./ -type f -exec md5sum {} \; > md5sum.txt

Fertig – unser Installationsmedium ist inhaltlich präpariert.

Darf ich Ihnen das einpacken?

Ja gerne, sonst kann ich ja nicht booten. Also nun ein bootfähiges ISO erstellen. Aber erstmal wieder raus aus dem Folder cd ... Im Netz fand ich viele Vorschläge, wie man das ISO baut, dieser hier funktioniert bei mir tatsächlich:

# create iso
genisoimage -V Debian-headless \
        -r -J -b isolinux/isolinux.bin -c isolinux/boot.cat \
        -no-emul-boot -boot-load-size 4 -boot-info-table \
        -o debian-9.6.0-amd64-netinst-headless.iso isofiles
# fix MBR
isohybrid debian-9.6.0-amd64-netinst-headless.iso

Der letzte Schritt ist wichtig, damit das ISO auch bootfähig ist.

Auf den Stick damit

Nun sollten wir ein bootfähiges ISO Image haben, das nun nur noch auf einen USB-Stick geschrieben werden muss. Dazu erstmal herausfinden, welches Device dem USB-Stick entspricht. Meist hilft lsblk um das herauszufinden, oder ein Blick in den Output von dmesg direkt nach dem einstecken des Sticks. Achtung! Bei mir ist /dev/sdc das device des USB-Sticks – bei Euch kann es ganz was anderes sein. Das falsch zu machen ist eine super Gelegenheit sich die Festplatte komplett zu zerschießen – also Augen auf bei der Device Wahl! Und so schreiben wir das dann:

sudo dd if=debian-9.6.0-amd64-netinst-headless.iso of=/dev/sdc bs=4k

Und sicherheitshalber noch ein sync hinterher.

Wenn ihr zu feige seid, das mit dd zu machen könnt Ihr auch ein Tool wie etcher nehmen, um Katastrophen zu verhindern...

Auf geht's

Nun kommt der große Moment: USB Stick in den Server stecken, power on und eine Weile warten. Nun müsst Ihr noch rausfinden, welche IP-Adresse der neue Rechner bekommen hat. Das weiß der DHCP-Server, z.B. in eurem Router. Solltet Ihr kein DHCP verwenden, müsst Ihr das preseed.cfg file entsprechend anpassen und eine statische Adresse konfigurieren.

Nehmen wir mal an, der Rechner hat die Adresse 192.168.5.56 bekommen, dann nehmt Ihr so Kontakt auf:

ssh installer@192.168.5.56

In preseed.cfg hatten wir das Passwort install konfiguriert – aber Ihr könnt und solltet dort natürlich auch ein anderes einstellen. Nun kann man die komplette Installation in Ruhe über ssh durchführen. Zum Server muss man erst wieder anlässlich des Reboots, denn sonst kann es gut sein, dass er einfach wieder in den Installer bootet, anstatt das frisch installierte Linux zu starten.

Fazit

Das waren jetzt viele Schritte und ich kann mir sowas nie merken. Deswegen habe ich mir die Mühe gemacht, den kompletten Vorgang in einem Makefile zusammenzufassen. Wer sich dafür interessiert findet es hier:

github.com/philpagel/debian-headless

Der Vollständigkeit halber sei noch angemerkt, dass das alles nur für den "klassischen" Bootvorgang funktioniert. D.h. im BIOS muss der 'legacy boot' eingestellt sein – mit UEFI boot klappt das so nicht.

Viel Spaß beim Installieren.

Update 2022-03-26

Der Post ist nach wie vor korrekt, aber in der Zwischenzeit habe ich einige Dinge am Prozess verbessert und v.a. Support für UEFI hinzugefügt. All das ist in die schön verpackte Version im Github repository eingeflossen. Also bitte verwendet diese, wenn Ihr das in der echten Welt nutzen möchtet.

github.com/philpagel/debian-headless