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.
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
.
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.
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.
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.