RaspberryPi & Raspbian en lecture seul (ReadOnly) pour préserver la carte SD
Le Raspberry Pi, est un mini ordinateur qui consomme très peu d’énergie. Il n’y a pas de disque dur mécanique, le système se trouve sur une carte SD. L’avantage c’est que ça consomme moins d’énergie mais la carte SD à l’inconvénient de s’abîmer très rapidement quand il y a beaucoup de lecture/écriture (et sa durée de vie n’en ai que moindre). J’ai donc passé mon Raspberry Pi sous Raspbian (une Debian pré-packagé pour Raspberry) et mis en place un système en lecture seul. Il s’agit ici d’une installation type serveur sans interface graphique.
Installation de Raspbian (sans écran sur le Raspberry) avec connexion Wifi
Vue que je n’ai pas d’écran pour installer mon Raspberry, j’ai mis la carte SD dans mon ordinateur portable pour l’installation. Après le téléchargement de « Raspbien lite » sur le site officiel : http://www.raspbian.org. Il suffit d’utiliser la commande dd pour installer l’image :
david@portabuntu:~/Téléchargements$ unip raspbian_lite_latest.zip david@portabuntu:~/Téléchargements$ sudo dd bs=4M if=2016-05-10-raspbian-jessie-lite.img of=/dev/sdc 330+1 enregistrements lus 330+1 enregistrements écrits 1386217472 octets (1,4 GB) copiés, 86,4596 s, 16,0 MB/s
Attention : remplacer /dev/sdc par le périphérique de votre carte SD ! (/dev/sdb, /dev/mmcblk0… un « sudo fdisk -l » pourra vous en dire plus)
Éjecter la carte SD et remettez là, vous devriez avoir plusieurs partition sur la carte SD :
- #1 : FAT32 (partition de boot)
- #2 : ext3 (système)
Utilisation de gparted pour agrandir l’espace disque de la partition système :
On va maintenant préparer la connexion Wifi pour pouvoir l’attaquer en SSH :
sudo mkdir /mnt/sd-sys sudo mount /dev/sdc2 /mnt/sd-sys # (la partition ext3) sudo vi /mnt/sd-sys/etc/network/interfaces
L’édition de se fichier interface qui gère les cartes réseaux :
< iface wlan0 inet manual < wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf --- > auto wlan0 > iface wlan0 inet static > address 192.168.1.2 > netmask 255.255.255.0 > gateway 192.168.1.1 > wpa-ssid "VOTRE SSID WIFI" > wpa-psk "VOTRE CLEF WAP PSK"
On spécifie le serveur DNS en modifiant le fichier /mnt/sd-sys/etc/network/interfaces
< #name_servers=127.0.0.1 --- > name_servers=192.168.1.1
Bien sûr il faut mette des IP’s de votre réseau…
On éjecte la carte :
david@portabuntu:~$ sudo umount /dev/sdc2 david@portabuntu:~$ sudo eject /dev/sdc
On met la carte SD dans le Raspberry et on l’allume, on partiente que la connexion au Wifi soit faite et on test la connexion ssh :
david@portabuntu:~$ ssh pi@192.168.1.2 The authenticity of host '192.168.1.2 (192.168.1.2)' can't be established. ECDSA key fingerprint is fe:ed:f6:fe:e5:ea:28:bb:ad:6d:0c:2e:8f:b1:2c:5b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.1.2' (ECDSA) to the list of known hosts. pi@192.168.1.2's password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. pi@raspberrypi:~ $
ça fonctionne !!!!
Passage du système en ReadOnly
Je me suis bien aidé des différents sites suivant :
- https://hallard.me/raspberry-pi-read-only/
- http://petr.io/en/blog/2015/11/09/read-only-raspberry-pi-with-jessie/
- https://k3a.me/how-to-make-raspberrypi-truly-read-only-reliable-and-trouble-free/
- https://idmedia.no/general/make-raspbian-read-only/
Le reste des commandes va s’effectuer avec les droits root :
pi@raspberrypi:~ $ sudo -i root@raspberrypi:~#
Il va falloir minimiser les programmes qui écrivent sur le FileSystème. On commence par désactiver la SWAP :
dphys-swapfile swapoff dphys-swapfile uninstall update-rc.d dphys-swapfile disable
Et on fait du ménage :
apt-get remove --purge logrotate dbus dphys-swapfile fake-hwclock
Sauf si vous utilisez le DHCP, dans ce cas il faudra ajouter des choses pour que ça fonctionne en RO (« ln -s /tmp /var/lib/dhcp » par exemple…) sinon on supprime aussi le client DHCP :
aptitude purge isc-dhcp-client dhcpcd5 isc-dhcp-common
On met l’horloge sur le bon fuseau horaire (Europe/Paris pour moi) :
rm /etc/localtime ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime
On remplace le « log manager » rsyslogd par busybox one qui fonctionne en RAM et on en FS :
apt-get install busybox-syslogd; dpkg --purge rsyslog
Pour lire les logs il faut utiliser la commande logread (logread -f correspond à un tail -f sur le syslog)
Encore un peu de ménage au démarrage :
insserv -r bootlogs insserv -r sudo # Si vous n'utilisez pas sudo insserv -r alsa-utils # Si vous n'utilisez pas le son insserv -r console-setup insserv -r fake-hwclock # Certainement déjà absent à ce stade
Pour Debian 9 c’est systemd et non insserv pour les commande de démarrage.
A ce stade je conseil d’installer les petits outils indispensables
On désactive le bash_history soit en supprimant complètement le fichier
history -c rm ~/.bash_history -rf export HISTFILESIZE=0 unset HISTFILE echo "HISTFILESIZE=0" >> ~/.bashrc
Soit en le déplaçant dans /tmp. Il sera remis à 0 à chaque reboot mais fonctionnera en read only.
+ HISTFILE="/tmp/${USER}_bash_history"
Avant de mettre le système en read only on va faire deux alias pour switcher du mode read-only on mode read-write facilement. Ajouter dans bashrc commun : /etc/bash.bashrc :
# Fonction pour connaître le mode en cours fs_mode=$(mount | sed -n -e "s/^.* on \\/ .*(\\(r[w|o]\\).*/\\1/p") # alias ro/rw pour passer de l'un à l'autre alias ro='mount -o remount,ro / ; fs_mode=$(mount | sed -n -e "s/^.* on \\/ .*(\\(r[w|o]\\).*/\\1/p")' alias rw='mount -o remount,rw / ; fs_mode=$(mount | sed -n -e "s/^.* on \\/ .*(\\(r[w|o]\\).*/\\1/p")' # Modification du prompt pour afficher le mode en cours export PS1='\\[\\033[01;32m\\]\\u@\\h${fs_mode:+($fs_mode)}\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '
Aller hop, on passe au chose sérieuse, on modifie le /etc/fstab :
< /dev/mmcblk0p1 /boot vfat defaults 0 2 < /dev/mmcblk0p2 / ext4 defaults,noatime 0 1 --- > /dev/mmcblk0p1 /boot vfat defaults,ro 0 2 > /dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1 > tmpfs /var/log tmpfs nodev,nosuid 0 0 > tmpfs /var/tmp tmpfs nodev,nosuid 0 0 > tmpfs /tmp tmpfs nodev,nosuid 0 0
Puis le fichier /boot/cmdline.txt :
< dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait --- > dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait noswap ro
Après un reboot on peut tester :
root@raspberrypi(ro):~# touch /root/testEcriture touch: cannot touch ‘/root/testEcriture’: Read-only file system root@raspberrypi(ro):~# rw root@raspberrypi(rw):~# touch /root/testEcriture root@raspberrypi(rw):~# rm /root/testEcriture root@raspberrypi(rw):~# ro root@raspberrypi(ro):~#
ça fonctionne !
Le petit plus du chef, un petit script ~/.bash_logout pour ne pas oublier de remettre le FS en read only après avoir travaillé dessus…
#!/bin/bash if [ "$fs_mode" != "ro" ]; then read -p "Le FS est en lecture/écriture, ne voudriez vous pas le basculer en lecture seul ? [O/n] " if [[ ! $REPLY =~ ^[Nn]$ ]] then echo "Bascule en Read/Only" ro else echo "Ok on fait rien tant pi... Mais n'oublie pas que ça use la carte SD :-/" fi fi