ArchLinuxARM auf dem Raspberry Pi mit read-only Root-Partition und USB-Stick

Häufige Schreibzugriffe auf die SD-Karte eines Raspberry Pi können die Lebenszeit der SD-Karte deutlich verkürzen. Unabhängig davon kann bei einem Stromausfall das Dateisystem auf der SD-Karte beschädigt werden, was zu Datenverlust führen kann. Gleich zwei Gründe, die Root-Partition read-only (“nur lesend”) zu mounten. So finden keine Schreibzugriffe mehr statt und ein Stromausfall macht einem read-only gemounteten Dateisystem auch nichts mehr aus.

Ganz auf das Schreiben wollte ich allerdings nicht verzichten. Ich habe mich daher entschieden einen zusätzlichen USB-Stick an den Raspberry anzuschliessen. Alle Schreibzugriffe werden auf diesen USB-Stick umgeleitet um die Root-Partition auf der SD-Karte read-only mounten zu können. Alternativ könnte die SD-Karte auch in zwei Partitionen repartitioniert werden, dann würden jedoch weiterhin intensiv Schreibzugriffe auf die SD-Karte stattfinden, so dass die Wahrscheinlichkeit eines Ausfalls der SD-Karte weiterhin deutlich erhöht wäre.

Nun müssen die Dienste identifiziert werden, die weiterhin Schreibzugriff benötigen. Bei mir sind dies:

  • OpenHAB (Logdateien, Datenbank)
  • Systemd (Journal, Zeitsynchronisation, Random-Seed-Init)
  • Samba (Status)
  • Man (Datenbank)
  • Logrotate (Logdateien)

Danach heisst es, USB-Stick vorbereiten, einhängen und die schreibbaren Verzeichnisse verschieben. Dafür gibt es drei verschiedene Strategien, welche Abhängig vom Dienst ausgewählt werden können. Wer auf den persistenten Speicher per USB-Stick verzichten kann, findet in diesem Artikel eine einfachere Möglichkeit, das System umzustellen.

Vorbereitung: USB Stick mit ext4 formatieren und einhängen

1
2
3
mke2fs -j /dev/sda1
mkdir -p /mnt/usbstick
mount /dev/sda1 /mnt/usbstick

Dies ist die einfachste Strategie und empfiehlt sich bevorzugt, da die Dienste nicht angepasst werden müssen und keine Dateien verändert werden.

Verzeichnisse auf die weiterhin Schreibzugriff benötigt wird, werden auf den USB-Stick verschoben. Für jedes Verzeichnis /src wird ein entsprechender Symlink auf den USB-Stick /mnt/usbstick/src gesetzt.

Bei meiner Installation war dies für folgende Verzeichnisse notwendig, der Grund ist jeweils in Klammern angegeben.

  • /home/openhab (Home-Verzeichnis der OpenHAB Installation)
  • /var/cache/man (man-db.service)
  • /var/cache/samba (samba.service)
  • /var/lib/samba (samba.service)
  • /var/log (systemd-journald u.a.)

Strategie 2: Verzeichnisse per bind-mount schreibbar machen

Die zweite Strategie eignet sich, wenn die vorherige Strategie Probleme macht, da der Dienst den Symlink ignoriert, z.B. aus Sicherheitsgründen. Wie zuvor werden die Dateien auf den USB-Stick verschoben, anschliessend aber nicht per Symlink referenziert, sondern per bind mount. Bei meiner Installation betrifft dies:

  • /var/lib/systemd (systemd-timesyncd.service)
  • /var/log/journal (systemd-journald.service)

Eine Anpassung von /etc/fstab ist anschliessend erforderlich:

/etc/fstab
1
2
3
4
5
6
7
8
#
# /etc/fstab: static file system information
#
# <file system> <dir> <type> <options> <dump> <pass>
/dev/mmcblk0p5 /boot vfat defaults,ro 0 0
/dev/sda1 /mnt/usbstick ext4 defaults 0 0
/mnt/usbstick/var/lib/systemd /var/lib/systemd auto bind 0 0
/mnt/usbstick/var/log/journal /var/log/journal auto bind 0 0

Strategie 3: Dienste umkonfigurieren

Die dritte Strategie eigenet sich als Alternative zur zweiten Strategie. Hier wird der Dienst so umkonfiguriert, dass er Dateien auf dem USB-Stick ablegt. Ich habe dies für folgende Dienste durchgeführt:

  • logrotate.service (ändert die Datei /var/lib/logrotate.status)
  • systemd-timesyncd.service

Systemd-Dienste können bequem wie folgt verändert werden:

bash
1
systemctl edit sample.service

Dies legt entsprechende /etc/systemd/system/sample.service/override.conf Dateien an, bei mir diese:

bash
1
2
3
4
5
6
7
cat /etc/systemd/system/logrotate.service.d/override.conf
[Service]
ExecStart=/usr/bin/logrotate -s /mnt/usbstick/var/lib/logrotate.status /etc/logrotate.conf

cat /etc/systemd/system/systemd-timesyncd.service.d/override.conf
[Service]
PrivateTmp=no

Systemupdates

Updates können wie folgt in das System eingespielt werden:

bash
1
2
3
4
5
mount -o remount,rw /
mount -o remount,rw /boot
pacman -Syu
mount -o remount,ro /
mount -o remount,ro /boot

Auch andere Veränderungen am Dateisystem können auf die gleiche Weise durchgeführt werden. Anschliessendes read-only setzen des Mounts darf natürlich nicht vergessen werden.