Installation des Basissystems

Raspberry Pi OS

Als Basissystem verwende ich das aktuelle Raspberry Pi OS (vormals Raspbian). Seit Februar 2022 gibt es neben der bekannten 32-Bit-Variante auch eine 64-Bit-Variante, der ich den Vorzug gebe. Zur Installation verwende ich den offiziellen Raspberry Pi Imager. Unter Windows 10 lässt sich dieser bequem über den Windows Package Manager installieren (winget install RaspberryPiFoundation.RaspberryPiImager), unter Ubuntu mit sudo apt install -y rpi-imager.

Nach der Auswahl der gewünschten Betriebssystem-Variante lädt der Imager alles Notwendige automatisch runter, sodass man sich um fast nichts mehr selbst kümmern muss. Allerdings gibt es ein paar Dinge in der Konfiguration, die man ändern sollte. Dazu gehört das Aktivieren des SSH-Zugangs und das initiale Erstellen eines Benutzer-Accounts (der Default-Login pi/raspberry funktioniert nicht mehr!). Hier in kurzen Stichpunkten was ich ausgewählt habe:

Mit der so präparierten SD-Karte startet der Raspberry Pi auf und ist via SSH erreichbar (Netzwerk mit DHCP vorausgesetzt, sonst wird es jetzt etwas haarig). Die IP-Adresse findet man ggf. per nmap von einem anderen System aus heraus, der Raspberry Pi ist normalerweise gut als solcher erkennbar:

$ nmap 192.168.42.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2023-07-01 19:11 CEST
Nmap scan report for filebox (192.168.42.108)
Host is up (0.0099s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE
22/tcp open  ssh

Alternativ kann man alles Weitere auch per Tastatur und externem Monitor erledigen.

Externe Datenträger

Nach dem Setup durch den Imager gibt es noch ein paar Handgriffe, die erst im laufenden System möglich sind. Dazu gehört an erster Stelle das Vorbereiten und Einbinden der externen Festplatte(n). Wenn man mehrere Festplatten anschließt ist mitunter schwer zu sagen, welcher Gerätename zu welcher Festplatte gehört. Ich schließe externe Datenträger daher gerne nacheinander an und prüfe zwischendrin mit dmesg, welcher Gerätename vergeben wurde. Bei Datenträgern unterschiedlicher Größe kann man natürlich auch beim Partitionieren auf die Gesamtgröße achten und daraus auf die jeweilige Festplatte schließen. Allerdings sind die Gerätenamen nicht besonders stabil: das Wechseln der USB-Ports oder das Anschließen weiterer Geräte kann alles durcheinanderbringen.

Bei mir taucht die erste Festplatte als /dev/sda auf. Ich habe sie mit cfdisk als eine große Partition mit Typ "Linux Filesystem" eingerichtet und mit ext4 formatiert:

$ sudo cfdisk
$ sudo mkfs.ext4 /dev/sda1

Es ist übrigens normal, dass die Festplatte nach dem Anlegen der Partition eine Zeit lang vor sich hin rödelt. Es handelt sich um keinen Defekt, sondern die Erstellung des Journals, die im Hintergrund stattfindet und mitunter ein paar Stunden dauern kann. Das jeweilige Dateisystem kann trotzdem bereits verwendet werden. Auch das Runterfahren oder Neustarten des Systems ist kein Problem, der Vorgang wird automatisch fortgesetzt.

Das Dateisystem kann manuell gemountet werden, wobei man Gerätenamen, Zielpfad und ggf. weitere Optionen in der Kommandozeile angeben muss. Alternativ kann man einen Eintrag in der Datei /etc/fstab anlegen, der diese Informationen beinhaltet und im Normalfall dazu führt, dass das Dateisystem beim Booten automatisch gemountet wird. Was praktisch klingt kann auch schlecht sein: schlägt das Mounten fehl, gerät das System in Panik und bleibt stehen bzw. fällt in den Single-User-Modus, aus dem man sich nur mit angeschlossener Tastatur und Bildschirm befreien kann; für ein auf dem Schrank vergrabenes Remote-Setup etwas unpraktisch. Glücklicherweise kann das automatische Mounten mit der Option noauto für jedes Dateisystem individuell abgestellt werden. Um ein solches Dateisystem manuell zu mounten identifiziert man es entweder per Gerätenamen, oder per Zielpfad (Mountpoint) -- und kann sich weiterhin die Angabe aller weiteren Optionen sparen.

Um das Problem der Gerätenamen in den Griff zu bekommen besteht die Möglichkeit, ein Dateisystem per Partition-ID zu identifizieren. Diese findet man am einfachsten mit dem Kommando blkid heraus.

$ sudo blkid
/dev/mmcblk0p1: LABEL_FATBOOT="bootfs" LABEL="bootfs" UUID="0B22-2966" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="daae4a67-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="3ad7386b-e1ae-4032-ae33-0c40f5ecc4ac" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="daae4a67-02"
/dev/sda1: UUID="405db24e-13b5-4f05-979e-b0222bae6e5c" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="2040c944-01"

Ein Eintrag in /etc/fstab um das Dateisystem zu mounten, das hier im Moment als /dev/sda1 bekannt ist, könnte so aussehen:

# device-spec          mount-point   fs-type   options                   dump   pass
PARTUUID=2040c944-01   /mnt/live     ext4      defaults,noatime,noauto   0      2

Um das Dateisystem manuell zu mounten genügt nun der Befehl sudo mount /mnt/live.

Weitere Handgriffe

Beim Raspberry Pi ist der Strom, den alle USB-Geräte zusammengenommen verbrauchen dürfen, auf 600 mA begrenzt. Je nach Typ der Festplatten kann dies zu knapp sein. Glücklicherweise ist dies nur ein Soft-Limit, das leicht auf 1200 mA erhöht werden kann (max_usb_current=1 in /boot/config.txt).

Der Raspberry Pi zwackt einen Teil des Arbeitsspeichers für die Verwendung als Video-RAM ab. Die Menge kann konfiguriert werden und liegt per Default bei 64 Megabyte. Da mein System ohne Monitor laufen wird, reduziere ich die Menge des Video-RAMs auf das Minimum von 16 Megabyte (gpu_mem=16 in /boot/config.txt).

Als letzte Sofortmaßnahme sollte man sich um die Swap-Datei kümmern. Diese liegt per Default auf der SD-Karte unter /var/swap, was weder in Hinblick auf Performanz noch für die Lebenserwartung der Karte sonderlich gut ist. Eine mögliche Abhilfe besteht darin, die Swap-Datei auf einen externen Datenträger zu legen (CONF_SWAPFILE in /etc/dphys-swapfile). Alternativ dazu kann die Swap-Datei auch komplett deaktiviert werden (wovon jedoch vielerorts abgeraten wird):

$ sudo dphys-swapfile uninstall
$ sudo systemctl disable dphys-swapfile.service

Mit der Swap-Datei auf einem externen Datenträger hatte ich verschiedene Probleme beobachtet, u.a. bei der Magnetfestplatte, dass diese nicht nach 30 Minuten in den Stromsparmodus schaltet, sondern durchgehend läuft. Dies hatte ich aus Stromspargründen und wegen des Lärms zum Anlass genommen, komplett auf das Swapping zu verzichten. In meinem erweiterten Setup mit der SSD fällt der Lärm weg und der Aspekt des Stromverbrauchs reduziert sich ebenfalls ein wenig; dennoch bleibe ich vorerst bei dem Ansatz ohne Swapping.

Erste Software-Pakete

Um auf dem System mit Docker arbeiten zu können, müssen noch ein paar Software-Pakete installiert werden. Allerdings sind die Pakete aus dem Debian-Archiv meistens "gut abgehangen"; besser ist man dran, wenn man der Anleitung Install Docker Engine on Debian folgt, was im Kern bedeutet:

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

Das Skript erkennt die Betriebssystem-Version, fügt das passende Docker-Paket-Repository hinzu und installiert anschließend per apt die notwendigen Pakete. Danach muss der nicht-privilegierte Benutzer nur noch zur Gruppe docker hinzugefügt werden und die Installation ist abgeschlossen. Wer möchte kann noch einen Texteditor mit Syntax-Highlighting für YAML-Dateien installieren, um auch direkt auf dem Pi an den Skripten arbeiten zu können. Ich verwende dazu gerne vim.

$ sudo adduser pi docker
$ sudo apt install -y vim

Damit ist man im Prinzip startklar; ich habe meine Experimente mit diesem Setup begonnen. Allerdings bin ich nach den ersten "Fummelstunden" auf den Trichter gekommen, dass man docker-compose.yaml-Dateien eigentlich immer irgendwo einchecken möchte (nicht erst wenn sie "fertig" sind). Jede Änderung, ob vorwärts, rückwärts oder ganz woanders hin, bringt eine Form des Erkenntnisgewinns mit sich, und wenn man (wie ich) seine Bastelei über mehrere Wochenenden verteilt, dann verschwimmt die Erinnerung gerne mal. Deshalb bin ich für die spätere Ausgestaltung auf ein anderes Vorgehen umgeschwenkt.

Ein Minimal-Setup für Git

Wir haben bereits einen Raspberry Pi aufgesetzt, er ist per SSH erreichbar -- das reicht aus, um ihn als Git-Repository zu nutzen. Damit wird auf einen Schlag ein besserer Entwicklungsprozess möglich:

Sollte dann aus irgendeinem Grund der Pi komplett abschmieren, liegen die Erkenntnisse zumindest im lokalen Repository auf der Entwicklungsmaschine vor und können leicht wieder in ein neu aufgesetztes System zurückgespielt werden. Damit ist auch ein kompletter Neuanfang bei einem total verfrickelten System schnell gemacht und verliert seinen Schrecken.

Auf dem Pi wird ein Bare-Repository im Home-Verzeichnis angelegt:

$ git init --bare /home/pi/filebox4.git

Auf der Entwicklungsmaschine (in meinem Fall mein Netbook) wird das Repository geklont:

$ git clone pi@filebox:/home/pi/filebox4.git

Auf der Entwicklungsmaschine kann man sich jetzt austoben und wie gewohnt Dateien erstellen, committen, pushen, usw.
Auf dem Pi schlussendlich schafft man die gesammelten Werke in die Zielumgebung, indem man Folgendes im Home-Verzeichnis von pi ausführt:

$ git clone filebox4.git         # legt eine Arbeitskopie "filebox4" neben dem Bare-Repository an
$ sudo mv filebox4 /mnt/live/    # verschiebt die Arbeitskopie, behält aber Eigentümer und Zugriffsrechte bei

Damit liegt jetzt ein Verzeichnis /mnt/live/filebox4/ vor, in dem der Benutzer pi Schreibrechte hat und die jeweils neueste Version der Konfigurationsdateien und Skripte einfach per git pull holen kann. Zwar muss das Stoppen und Starten der Dienste noch manuell erfolgen, aber man könnte es schon GitOps für Arme nennen.


Zurück zur Hauptseite