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.
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.
Links
- Webseite: Arch Linux ARM (englisch)
- Webseite: Raspberry Pi (englisch)