RaspberryPI in Readonly

raspherry

Il sistema operativo del Raspberry PI viene facilmente corrotto con uno spegnimento errato o con un calo di tensione, la soluzione è semplice: utilizzare un filesystem readonly.

In questo modo il sistema viene utilizzato in sola lettura riducendo le possibilità di errori di salvataggio. Eviteremo in questo modo anche il salvataggio dei file di log all’ interno della SD.

13/01/2017: Testato con successo con l’ultima versione di Raspbian 🙂

Esiste un’ottima versione di raspbian-readonly pronta all’ uso chiamata Industrial Perennial Environment che ci permette di lavorare su un’installazione stabile e sicura che non permette alcuna sorta di modifica da parte dei vari software ai file presenti sulla memoria.

Ma ovviamente ci sono PRO e CONTRO: In un sistema puramente readonly i nostri programmi non potranno modificare alcun file restituendo talvolta alcuni errori.
La soluzione?

UnionFS:

Questo programma ci permette infatti di sovrapporre al nostro sistema in sola lettura un filesystem temporaneo salvato in RAM; cioè ad ogni riavvio il nostro Raspberry tornerà automaticamente allo stato di partenza, cancellando ogni modifica ma permettendo ad ogni programma il corretto funzionamento.

Installazione:

Una volta collegati in SSH al nostro Raspberry dobbiamo innanzitutto installare i pacchetti necessari:

apt-get update
apt-get install unionfs-fuse

Dopo di che disabilitiamo lo SWAP:

dphys-swapfile swapoff
dphys-swapfile uninstall
update-rc.d dphys-swapfile disable
systemctl disable systemd-readahead-collect
systemctl disable systemd-random-seed

Creiamo un file che spieghi ad UnionFS come comportarsi:

touch /usr/local/bin/mount_unionfs
chmod +x /usr/local/bin/mount_unionfs
nano /usr/local/bin/mount_unionfs

Ed inseriamoci:

#!/bin/sh
 DIR=$1
 ROOT_MOUNT=$(awk '$2=="/" {print substr($4,1,2)}' < /etc/fstab)
 if [ $ROOT_MOUNT = "rw" ]
 then
   /bin/mount --bind ${DIR}_org ${DIR}
 else
   /bin/mount -t tmpfs ramdisk ${DIR}_rw
   /usr/bin/unionfs-fuse -o cow,allow_other,suid,dev,nonempty ${DIR}_rw=RW:${DIR}_org=RO ${DIR}
 fi

Ora modifichiamo le partizioni di sistema

nano /etc/fstab

ed adattiamole al readonly:

proc /proc proc defaults 0 0
/dev/mmcblk0p5 /boot vfat ro 0 2
/dev/mmcblk0p6 / ext4 ro,noatime 0 1
mount_unionfs   /etc            fuse    defaults          0       0
mount_unionfs   /var            fuse    defaults          0       0
none            /tmp            tmpfs   defaults          0       0

N.B: Aggiungi soltanto le linee che mancano e i flag ‘ro’, è possibile che il nome della SD (mmcblk0p6) presente nell’esempio non coincida con quello la tua installazione, non è un problema lascia quello già presente!
Non è necessario mantenere il file fstab intabellato aggiungendo spazi

Modifichiamo il file cmdline.txt per montare /boot in readonly:

nano /boot/cmdline.txt

Ed aggiungi ‘ro’ dopo il root=/dev.. come in esempio:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 ro rootfstype=ext4 elevator=deadline rootwait fbcon=map:1 fbcon=font:ProFont6x11

Creiamo uno script per uscire dal readonly nel caso dovessimo installare qualcosa e mantenere la modifica anche dopo un riavvio:

touch /usr/local/bin/noreadonly
chmod +x /usr/local/bin/noreadonly
nano /usr/local/bin/noreadonly

Ed incolliamoci:

#!/bin/bash

# remount root rw
mount -o remount,rw /

# prapare target paths
mkdir -p /chroot
mkdir -p /chroot/{bin,boot,dev,etc,home,lib,opt,proc,root,run,sbin,sys,tmp,usr,var}

# mount special filesystems
mount -t proc proc /chroot/proc
mount --rbind /sys /chroot/sys
mount --rbind /dev /chroot/dev

# bind rw directories
for f in {etc,var}; do mount --rbind /${f}_org /chroot/$f; done

# bind remaining directories
for f in {bin,boot,home,lib,opt,root,run,sbin,tmp,usr}; do mount --rbind /$f /chroot/$f; done

# chroot
echo "Note: /boot is still mounted read-only, remount to read-write if needed."
echo -e "\e[33mYou are now in read-write chroot. Use CTRL+D when done to exit chroot and mount read-only again.\e[39m"
chroot /chroot /usr/bin/env PS1="(rw) \[email protected]\h:\w\$ " /bin/bash --noprofile -l

# unmount mounts
for f in /chroot/{bin,boot,dev,etc,home,lib,opt,proc,root,run,sbin,sys,tmp,usr,var}; do
umount -l $f
done

sleep 1

# remount read-only again
echo -e "\e[32mChroot left, re-mounting read-only again.\e[39m"
mount -o remount,ro /

 

Abbiamo quasi finito, a questo punto prepariamo le nuove directory:

rm -rf /var/lib/dhcp/
ln -s /tmp /var/lib/dhcp

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

cp -al /etc /etc_org
mv /var /var_org
mkdir /etc_rw
mkdir /var /var_rw
reboot

Il nostro sistema dovrebbe finalmente essere in readonly, Prova a creare un file e riavviare e le modifiche dovrebbero sparire!

Per modificare in modo definitivo qualcosa scriviamo nel terminale ‘noreadonly‘ e dovrebbe apparire una shell le cui modifiche rimarranno anche dopo un riavvivo

 

Problemi con il Desktop in Readonly?

X11 non va tanto d’accordo con la cartella /home in readonly, nel caso non partisse si può utilizzare un piccolo trucco:

mkdir /var_org/home
mv /home/pi /var_org/home/pi
chmod -R 777 /var_org/home/pi
cd /home
ln -s /var/home/pi
reboot

Il comando startx dovrebbe ora funzionare senza problemi

[Tradotto e riadattato]

6 commenti

  1. Buongiorno Andrea, ho provato a seguire tutti i passi della guida (a parte i comandi systemctl perchè mi dice che non è installato) con l’immagine Raspberry del 5-5-2015.
    Ho provato le impostazioni per lanciare il desktop, ma mi compare solo uno schermo nero…..

    1. Accidenti, ho visto solo ora il commento!
      Sei riuscito a saltarci fuori?
      A me dava lo stesso errore finché non ho spostato la cartella home con il “link” in una parte del sistema read/write

  2. Hi Andrea, I installed recent version of Raspbian Jessie. My pi was booting to default startx. But after this read-only modification it won’t boot up to startx. Is there any workaround for this? (I tried your solution with “mkdir /var/home…” but it did not help)

    1. Hi, I solved moving the /home/pi dir to a r/w part of the filesystem as u noticed.
      After the workaround is /home/pi writable?
      Do you have some log of the error?

  3. Ciao!
    Are you 100% sure that, after running “noreadonly.sh”, it is possible to install the packages using “apt-get”?
    In my case, most package cannot install correctly due to “chroot”.
    For example, I tried to install Samba, or other packages, after your guide, but they don’t work properly.
    On opposite, if I install the packages before performing the steps of your guide, everything works fine.
    I am using Raspberry Pi 3 with latest Raspbian Jessie (January 2017).

    1. Ciao Davide, verso metà gennaio ho giocato un un Raspberry2 installando Chromium e Node dalla modalità ‘noreadonly’ ricopiando gli stessi passaggi citati sopra. Il post è frutto di vari copy n’ paste, lo script non fa altro che montare le cartelle /var ed /etc originali e per me ha funzionato anche con l’ultima versione di Raspbian (Jan 2017)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *