RasPi: Root-Dateisystem read-only mounten

Es gibt viele Gründe, warum es sich anbietet das Root-Dateisystem eines Raspberry Pi read-only einzuhängen. Im Folgenden wird die grundlegende Konfiguration beschrieben.

SD-Karten sind nicht für den Dauerbetrieb in Computern ausgelegt und es kann passieren, dass sie nach relativ kurzer Zeit im RasPi defekt sind. Müssen Daten nicht permanent geschrieben werden, bietet es sich an, dass Dateisystem read-only (nur lesend) einzuhängen. Ein weiterer Vorteil ist, dass das Dateisystem bei einem Stromausfall nicht kaputt gehen kann und dass das System immer in einem klar definierten Zustand bootet.

Hinweis: Alle im Folgenden beschriebenen Schritte sollten als root-Benutzer ausgeführt werden. Es wird dabei von einer Basis-Installation ausgegangen. Wurden bereits Nutzer eingerichtet oder Software installiert, sind teilweise weitere Schritte notwendig.

Bevor mit der eigentlichen Umstellung auf ein nur lesbares Dateisystem begonnen wird, wird der Ordner static im Root Verzeichnis angelegt, in diesem liegen Dateien, die beim Booten kopiert werden und später mit Hilfe von tmpfs auch beschreibbar sind. Was dies genau bedeutet sollte im weiteren Verlauf deutlicher werden.

$ mkdir /static

Anschließend wird die Datei /etc/fstab angepasst und die Verzeichnisse, die später beschreibbar sein müssen, werden als tmpfs eingehängt. Die Datei könnte dann wie folgt aussehen:

/dev/mmcblk0p1  /boot     vfat   defaults,ro                            0 0

tmpfs           /home     tmpfs  noatime,nodiratime,size=16M,mode=1755  0 0
tmpfs           /var/log  tmpfs  noatime,nodiratime,size=8M,mode=1755   0 0

Teilweise müssen Konfigurationsdateien oder ganze Ordnerstrukturen vorhanden sein, da es sonst zu Komplikationen mit Anwendungen kommen kann. Daher wird ein Skript benötigt welches die Dateien aus dem /static Verzeichnis an den richtigen Platz im tmpfs Kopiert. Dafür muss das folgende Unit-File für systemd unter /etc/systemd/system/copy-static@.service abgelegt werden.

[Unit]
Description=Copy static files to mounted tmpfs
Requires=%i.mount

[Service]
Type=oneshot
RemainAfterExit=yes
KillMode=none
ExecStart=/usr/local/bin/copy-static %i

[Install]
WantedBy=local-fs.target

Weiterhin muss noch das folgende Shell-Skript unter /usr/local/bin/copy-static angelegt und ausführbar gemacht werden.

#!/usr/bin/sh

NAME=$1

DST_PATH=/$(/usr/bin/echo $NAME | /usr/bin/sed -e 's/-/\//g')
SRC_PATH=/static/$NAME

[ -d $SRC_PATH ] && /usr/bin/cp -a $SRC_PATH/* $DST_PATH

Das folgende Beispiel zeigt, wie das Kopieren der statischen Dateien während des Bootvorgangs für das Verzeichnis /home und /var/log aktiviert wird.

$ systemctl enable copy-static@home
ln -s '/etc/systemd/system/copy-static@.service' '/etc/systemd/system/local-fs.target.wants/copy-static@home.service'
$ systemctl enable copy-static@var-log
ln -s '/etc/systemd/system/copy-static@.service' '/etc/systemd/system/local-fs.target.wants/copy-static@var-log.service'

In dem Verzeichnis /var/log müssen weitere Unterordner vorhanden sein, damit für Anwendungen wie einen Webserver oder ähnliches keine weiteren Anpassungen nötig sind. Dazu werden die entsprechenden Ordner in ein Verzeichnis unter /static kopiert.

$ mkdir /static/var-log
$ cp -a /var/log/journal /static/var-log/
$ cp -a /var/log/old /static/var-log/
$ rm -rf /static/var-log/journal/*

Das nachfolgende Beispiel zeigt wie ein Nutzer angelegt und dessen Home-Verzeichnisse für das Kopieren vorbereitet wird.

$ useradd -m user
$ passwd user

$ cd /home/
$ ls -l
total 4
drwx------ 2 user user 4096 Mar 28 03:59 user
$ mkdir /static/home
$ mv user /static/home

Damit das root-Dateisystem direkt beim Booten als read-only eingehangen wird, wird die Datei /boot/cmdline.txt angepasst und an die Vorhandene Zeile wird ein "ro" angehängt. Dies könnte wie folgt aussehen.

ipv6.disable=1 avoid_safe_mode=1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p5 rootfstype=ext4 elevator=noop rootwait ro

Wird die IP-Adresse per DHCP bezogen und sind die Nameserver nicht fest vorgegeben, muss die Datei /etc/resolv.conf schreibbar sein. Hierfür wird ein Symlink in das /tmp Verzeichnis angelegt.

$ rm /etc/resolv.conf
$ ln -s /tmp/resolv.conf /etc/resolv.conf

Ist alles soweit vorbereitet, kann das System neu gestartet werden. Nach dem Neustart sollten alle Verzeichnisse bis auf die als tmpfs eingebunden als read-only eingehängt sein. Überprüft werden kann dies zum Beispiel mit dem Befehl mount. Dessen Ausgabe wie folgt aussehen könnte. Zu sehen ist, dass die erste Angabe in den Klammern "ro" ist, was für read-only steht.

$ mount
/dev/mmcblk0p5 on / type ext4 (ro,relatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=51560k,nr_inodes=12890,mode=755)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
[...]
tmpfs on /tmp type tmpfs (rw)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
mqueue on /dev/mqueue type mqueue (rw,relatime)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /var/log type tmpfs (rw,noatime,nodiratime,size=8192k,mode=1755)
tmpfs on /home type tmpfs (rw,noatime,nodiratime,size=16384k,mode=1755)
/dev/mmcblk0p1 on /boot type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=21396k,mode=700)

Soll ein Update des System durchgeführt werden, muss das System wieder schreibbar eingehängt werden, dies kann mit den zwei folgenden Befehlen im laufenden Betrieb erfolgen.

$ mount -o remount,rw /
$ mount -o remount,rw /boot/

Ist das Update oder die Installation abgeschlossen, kann das System wieder als read-only eingehängt werden.

$ mount -o remount,ro /
$ mount -o remount,ro /boot/

Die im vorangegangenen beschriebene Vorgehensweise dient als grobe Richtung für die Konfiguration eines read-only Dateisystems. Es ist auch denkbar Teile des Dateisystems schreibbar einzuhängen, damit dorthin zum Beispiel Bilder einer Überwachungskamera oder Wetterdaten geschrieben werden können. Auch ist es denkbar die Daten aus dem tmpfs beim Herunterfahren wieder auf die SD-Karte zu schreiben.

Hinweis
Da die als tmpfs eingehängten Dateisysteme im RAM liegen sollte darauf geachtet werden, dass sie die Größe des im System vorhandenen RAMs nicht übersteigen. Besonders bei Computern mit relativ wenig Speicher wie dem Raspberry Pi sollte das System beobachtet werden und die Größe der eingehängten Dateisysteme je nach Nutzung optimiert werden.

Verwandte Artikel