Un NAS pour faire des sauvegardes c'est bien, mais avec un système en
logiciel libre et à jour c'est mieux.
D-Link propose des NAS de bonne facture pour des sommes modiques, qu'il est
possible de passer intégralement sous Debian.
EDIT 12/04/2021 : utilisation des commandes btrfs récentes, suppression d'un délai au démarrage (/boot)
EDIT 27/11/2019 : mise à jour pour Debian Stretch puis Buster, cf notes pour la mise à niveau.
EDIT 13/11/2016 : mise à jour pour Debian Jessie, cf notes pour la mise à niveau.
À l'époque (en 2012), j'avais acheté un NAS 2 baies, le DNS-325
pour une centaine d'euros, quelques caractéristiques :
- 2 emplacements pour disques sata 3"5 (non fournis)
- boîtier métal de bonne facture
- 256MiO de RAM
- processeur ARM kirkwood à 1.2GHz
- une mémoire NAND de 128MiO (le firmware dlink initial est stocké sur cette
mémoire)
- Faible consommation électrique
- ~90€ en 2012
Ce modèle, facile à libérer (supporté par GNU/Linux et u-boot sans aucun
patch) ne semble plus produit, plusieurs alternatives s'offrent à vous :
- en acheter un d'occasion pour ~70€
- utiliser un modèle légèrement inférieur mais facilement hackable : DNS-320 ou DNS-323
- utiliser le DNS-327L
qui est le remplaçant du DNS-325, et est
lui aussi hackable quoiqu'un peu plus difficilement.
il se trouve autour de 120€ et dispose du double de RAM (512MiO).
L'avantage de cette gamme est que les modèles sont deux fois moins coûteux que
leurs équivalents chez synology, de bonne facture, et d'une architecture (ARM
kirkwood) bien supportée par Linux. c'est donc hackable à souhait :-). Ce
tutoriel doit fonctionner, à quelques ajustements prêt, pour d'autres modèles de
la gamme.
NOTE 10/4/2017: Ce tutoriel, réalisé pour le DNS-325, semble s'appliquer également pour les DNS-320, cf commentaire de CamilleBC pour les détails.
Objectif
L'objectif de ce guide est d'obtenir :
- un NAS faisant tourner la version complète de Debian (testé avec Jessie et Wheezy)
- Une redondance des disques (RAID1)
- Un système de snapshots efficace en cpu et en espace disque
- un système de secours et une procédure pour démarrer et réparer
même lorsque les disques sont HS.
Techniquement cela donnera :
- Un u-boot à jour pour gérer le démarrage
- le /boot (contenant initramfs et le noyau Linux) stockés sur la NAND
(mémoire interne du NAS) ;
- le reste du système Debian/GNU/linux ainsi que les données stockés sur les
disques ;
- Le système de fichiers btrfs prenant en charge RAID 1, taille dynamique
des partitions et snapshots (évite d'empiler lvm, mtd et ext4).
Notons au passage qu'on obtient une configuration ne faisant plus tourner aucun code
initialement fourni par D-LINK, si les backdoors constructeurs vous préoccupent,
cela peut vous intéresser...
Choix
Plusieurs voies sont possibles pour installer Debian, nous choisissons ici :
- utilisation du port série du NAS
- pas de serveur TFTP ou NFS à configurer
Console série
Il faut commencer par avoir un accès à la console série du NAS, on peut
difficilement s'en sortir sans et en cas de pépin, seule la console série permet
d'intervenir quel que soit l'ampleur des dégâts.
Il vous faudra :
- Un ordinateur avec gnu screen ;
- un tournevis cruciforme ;
- des petits fils ou nappe d'électronique (ça se récupère aisément) ;
- un petit fer à souder ;
- un adaptateur USB<->RS232 sur du 3.3V, j'utilise par exemple le JTAG
multifonction de chez GlobalScale
en mode UART mais il y a largement moins cher.
On y va :
- Éjecter les disque du NAS si besoin,
- retirer les 4 tampons de caoutchouc sur la façade arrière,
- retirer les vis ainsi révélées,
- retirer la façade arrière
- faire glisser gentiment le circuit imprimé en dehors
du boîtier
-
repérer les trous permettant de connecter les fils du port série sur le circuit imprimé (cf photo)
Les connecteurs sont dans l'ordre suivant:
RX (espace) 3.3v Masse TX
-
Souder une nappe ou des fils pour « sortir » les fils du circuit imprimé du
NAS.
-
Connectez-y votre adaptateur série à ces fils.
Pour tester,
- Connecter l'adaptateur USB à votre ordinateur ;
- lancer :
screen /dev/ttyUSB0 115200
;
- démarrer le NAS.
La séquence de boot du NAS devrait défiler à votre écran, c'est gagné :-)
u-boot
Nous allons remplacer u-boot, le chargeur de
démarrage installé de base par Marvell (fabricant de la puce) par une version
récente et non modifiée d'u-boot. Pourquoi ? La version initialement fournie :
- comporte des limitations « de sécurité » pénibles
- ne permet pas d'utiliser
ubifs pour stocker des
fichiers sur la NAND
- ne permet pas d'utiliser un initramfs pour booter (indispensable
pour démarrer sur un disque formatté en autre-chose qu'ext3 et pour
avoir une console de secours en cas de pépin)
- ne supporte pas de deviceTree,
ce qui oblige à utiliser un noyau patché.
Ça vaut le coup non ? C'est parti !
Vous avez le choix entre récupérer
une version déjà compilée
de u-boot pour la bonne architecture ou
la compiler vous-même. dans
tous les cas, on considère qu'on obtient un fichier u-boot-dns-325.kwb.
- Formatter une clef en ext2 et y copier u-boot-dns-325.kwb
- Brancher la clef sur le NAS
- démarrer le NAS (avec la console série branchée et GNU screen lancé)
- appuyer sur espace puis 1 à l'instant ou s'affiche « Hit any key to stop
autoboot »
- charger l'image d'u-boot depuis la clef usb puis l'écrire sur la NAND du NAS
et redémarrer ce dernier :
Marvell>> usb reset ; ext2load usb 0:1 0x1000000 /u-boot-dns-325.kwb
Marvell>> nand erase 0x000000 0xe0000
Marvell>> nand write 0x1000000 0x000000 0xe0000
Marvell>> reset
Le NAS redémarre, interrompre de nouveau le boot en appuyant sur n'importe quelle touche lorsque
proposé, nous voici avec l'u-boot nouveau qui n'indique plus « Marvell>> » mais
« => ».
Fixer l'adresse MAC de la carte réseau (présente sur l'étiquette de votre NAS, ou
peut-être choisi arbitrairement) :
=> setenv ethaddr 00:50:43:xx:xx:xx
Formatter la mémoire interne en 3 partitions (une pour u-boot, une pour sa
configuration et une en ubifs contenant le /boot :
=> setenv mtdparts'mtdparts=orion_nand:896k(u-boot),128k(u-boot-env),-(root)'
Sauvegarder
Préparation des disques
On va préparer les disques sur une autre machine avant de les « transplanter »
dans le NAS.
On branche donc les disques sur un ordinateur avec des câbles SATA. Supposons
qu'ils apparaissent en tant que /dev/sdb et /dev/sdc.
On commence par les formater en btrfs :
mkfs.btrfs -f -d raid1 /dev/sdb /dev/sdc
mount /dev/sdb /mnt/nas
Création d'un rootfs
Le rootfs c'est simplement l'ensemble des fichiers présents sur le système de
fichiers qui constituent notre distribution Debian installée.
Toujours depuis notre machine tierce :
debootstrap --verbose --foreign --arch=armel --variant=minbase\
--include=module-init-tools,locales,udev,dialog,ifupdown,mtd-utils\
procps,iproute,iputils-ping,isc-dhcp-client,nano,wget,netbase,\
btrfs-tools,acl,openssh-server,avahi-daemon,python-minimal,\
u-boot-tools\
buster /mnt/nas http://http.debian.net/debian
Les quelques paquets sélectionnés dans include
installent de quoi configurer le réseau,
un éditeur de texte, un serveur SSH, et de quoi commander le NAS via ansible,
libre à vous de personnaliser cette base.
Nous allons ensuite prendre le contrôle de cette installation basique depuis
notre ordinateur via un chroot. Comme l'architecture de votre PC (x86, amd64…)
et celle du NAS (ARM) sont probablement différentes, il y faut installer de
quoi virtualiser :
apt install qemu-user-static
cp /usr/bin/qemu-arm-static /mnt/nas/usr/bin/
chroot rootfs
Une fois dans le chroot on finit l'installation initiale et on rentre dans le
chroot :
./debootstrap/debootstrap --second-stage
On configure les dépôts :
cat > /etc/apt/sources.list <<EOF
# Mises-à-jour de sécurité
deb http://security.debian.org/ buster/updates main deb
deb http://http.debian.net/debian/ buster-updates main
EOF
On indique les modules nécessaires au démarrage
cat > /etc/modules <<EOF
# Load required modules
gpio-fan kirkwood_thermal btrfs
EOF
On configure le système pour que lorsque un nouveau noyau est installé via APT,
le système prépare une version de ce dernier ainsi qu'une version de l'initramfs
acceptées par u-boot (il ne restera plus qu'à copier ces derniers dans la NAND,
cf plus loin).
cat > /etc/kernel/postinst.d/local-kirkwood <<EOF
#!/bin/sh
set -e # passing the kernel version is required
version="$1"
[ -z "${version}" ] && exit 0
cp /usr/lib/linux-image-${version}/kirkwood-dns325.dtb /boot/kirkwood-dns325.dtb
/usr/bin/mkimage -A arm -O linux -T kernel -C none -n uImage\
-a 0x00008000 -e 0x00008000\
-d /boot/vmlinuz-${version} /boot/uImage-${version}
cp /boot/uImage-${version} /boot/uImage
/usr/bin/mkimage -A arm -O linux -T ramdisk -C gzip -n uInitrd\
-d /boot/initrd.img-${version} /boot/uInitrd-${version}
cp /boot/uInitrd-${version} /boot/uInitrd
echo "`date` copied new image ${version} to nand" \
>> /var/log/local-kirkwood.log
EOF
chmod a+x /etc/kernel/postinst.d/local-kirkwood
On installe un noyau compatible avec le NAS :
apt install linux-image-kirkwood
On prépare /etc/fstab :
cat <<EOF > /etc/fstab
/dev/root / auto defaults 0 0
#/dev/ubi0_0 /boot ubifs noauto,defaults 0 0
EOF
Notez la dernière ligne commentée : malgré le noauto, systemd essaye de monter le le /boot au démarrage, en même temps que les autres systèmes de fichiers (sous Jessie et suivantes, systemd échoue à le faire si
tôt).
On ajoute donc la ligne suivante au /etc/rc.local (avant le exit 0
) pour le
monter à la fin du processus de démarrage :
grep -q ' /boot ' /etc/mtab || mount /dev/ubi0_0 /boot -t ubifs -o rw
Et enfin, on configure les paramètres locaux et on définit un mot de passe root :
dpkg-reconfigure tzdata dpkg-reconfigure locales
pwconv
passwd
On peut ici sortir du chroot, nos disques sont prêts à être transplantés !,
mais il faut les laisser branchés pour copier le /boot.
Créer le /boot
Le /boot, à l'opposé du reste du système de fichiers sera sur la mémoire
NAND du NAS formatée en ubifs et non sur les disques.
On commence par préparer une image ubifs qui contient l'intégralité de notre /boot
apt-get install mtd-utils
On crée l'image
/usr/sbin/mkfs.ubifs -v -r /mnt/nas/boot -m 2048 -e 129024 -c 1016 -x zlib \
-o ubifs.img
On la copie sur notre clef usb formatée en ext2, puis on branche la clef usb sur
le NAS, puis depuis la console u-boot, on la flashe sur la nand :
=> nand erase.part root
=> ubi part root
=> ubi create rootfs
=> ext2load usb 0:2 0x1000000 /ubifs.img
Loading file "/ubifs.img" from usb device 0:1
60512256 bytes read
Des erreurs UHCI (contrôleur USB) peuvent apparaître à la commande ext2load,
tenter de changer de périphérique de stockage utilisé au besoin (après avoir
essayé une clef USB et une carte SD, j'ai fini par y parvenir avec un disque dur
externe)
Notez bien le nombre d'octets écrits (ici 60512256) et convertissez-là en
hexadécimal (ici
ça donne 39B5800), on en a besoin pour la suite :
=> ubi write 0x1000000 rootfs 39B5800
=> ubifsmount ubi:rootfs
=> ubifsls
Cette dernière commande devrait si tout s'est bien passé, nous lister le contenu
du /boot que l'on vient de copier (supposé être le même que dans notre
/mnt/nas/boot).
On configure ensuite u-boot pour démarrer avec les 3 fichiers intéressants de
notre /boot :
- le noyau copié (uImage)
- l'initramfs (uInitrd)
- le deviceTree (kirkwood-dns325.dtb)
On indique également quelle sera la partition racine ; cette information sera
passée à l'initramfs qui se chargera de monter la partition racine (présente sur
les disque durs) puis de lancer le système proprement dit.
setenv load_ubifs 'ubi part root; ubifsmount ubi:rootfs; ubifsload 0x0900000 /kirkwood-dns325.dtb ; ubifsload 0x1000000 /uImage; ubifsload 0x1200000 /uInitrd'
setenv console 'ttyS0,115200'
setenv optargs 'ubi.mtd=2'
setenv root_hdd 'root=/dev/sda rootflags=device=/dev/sda,device=/dev/sdb,defaults,noatime rootfstype=btrfs'
setenv bootcmd 'setenv bootargs console=${console} ${optargs} ${mtdparts} ${root_hdd} ; run load\_ubifs ; bootm 0x1000000 0x1200000 0x0900000'
Pour synthétiser ce qui se passera lors du boot :
- Mise sous tension
- le système charge u-boot depuis la première partition de la NAND
- u-boot monte la 3e partition de la NAND (ubifs)
- u-boot charge noyau, l'initramfs et le devicetree depuis cette partition ubifs
- u-boot démarre et passe la main au système en initramfs
- l'initramfs monte le système de fichiers btrfs présent sur les disques durs
- l'initramfs lance et passe la main au système présent sur ce système de fichiers.
- welcome home :-)
Pourquoi un initramfs ? u-boot ne sait pas gérer directement les systèmes btrfs.
Cet initramfs permet en outre d'avoir un système de secours stocké en dehors des
disques durs pour aller réparer les disques le jour où ceux-ci sont en panne ou
absents du NAS.
Procédures
Quelques procédures testées pour pouvoir agir sans panique, lorsque tout ça sera
un peu loin effacé dans les mémoires :
Un des deux disques est mort ou arraché (procédure à chaud)
Identifier le disque qui défaille (smartctl peut aider), nous considérerons ici
qu'il s'agit de /dev/sdb, le retirer à chaud et le remplacer par un nouveau
disque, on considère que ce dernier est reconnu comme /dev/sdz
# /!\ À tester (en tout cas les précédentes instructions ne fonctionnaient pas)
# Repérer le devid qui est marqué comme « missing » (ndlr: on a retiré le disque fautif)
btrfs filesystem show -d
[…]
# Ça devrait mentionner le devid (un nombre) qui est « missing ». Par exemple 42
btrfs device replace 42 /dev/sdz
Un des deux disques est mort ou arraché (procédure à froid)
Réparation (à froid, depuis le système éteint)
On considère que le disque défaillant a été identifié (smartctl
peut vous aider) et retiré du NAS.
- Brancher le port série et lancer screen
- Retirer le disque défaillant du NAS,
- démarrer avec un seul disque, le boot va échouer, et on se retrouve
sur la console de l'initramfs.
Inspectons :
btrfs filesystem show
Label: none uuid: d12685c2-8800-4270-8eee-cde102506e7f Total devices 2
FS bytes used 409.04MB devid 1 size 2.73TB used 2.03GB path /dev/sda
*** Some devices missing
Insérer (à chaud) le disque flambant neuf, il sera reconnu par exemple comme /dev/sdb
Montons le système de fichiers sans le deuxième disque (option degraded
):
mount /dev/sda -odegraded /root
Remplaçons (ces commandes peuvent prendre un peu de temps) :
# NB: devrait fonctionner avec btrfs replace également
btrfs device add /dev/sdb /root
btrfs device delete missing /root
Vérifions :
(initramfs) btrfs fi sho Label: none uuid:
d12685c2-8800-4270-8eee-cde102506e7f Total devices 3 FS bytes used
409.12MB devid 3 size 1.82TB used 2.03GB path /dev/sdb devid 1 size
2.73TB used 2.05GB path /dev/sda *** Some devices missing
(initramfs) btrfs fi df /root Data, RAID1: total=1.00GB, used=369.41MB
Data: total=8.00MB, used=0.00 System, RAID1: total=32.00MB, used=16.00KB
System: total=4.00MB, used=0.00 Metadata, RAID1: total=1.00GB,
used=39.69MB Metadata: total=8.00MB, used=0.00 : total=16.00MB,
used=0.00
Et rebootons :-)
Booter temporairement le système « normalement »
(à éviter dans la mesure du possible)
Si vous n'avez pas de nouveau disque sous la main mais devez tout de même
démarrer le système.
Btrfs refuse de booter si un des disques du RAID manque, à
moins de lui spécifier une option, pour cela, il faut interrompre le boot (en
connectant le port série et en pressant une touche), puis spécifier l'option
degraded :
=> setenv optargs 'root=/dev/sda rootflags=device=/dev/sda,device=/dev/sdb,defaults,noatime,degraded rootfstype=btrfs'
=> boot
On ne fait volontairement pas de saveenv
pour que le prochain boot n'inclue
pas cette option.
Mise à jour du noyau
Il n'y a rien de particulier à faire : le /boot de notre système est sur la
flash et le script update-initramfs est configuré de telle sorte qu'un nouveau
noyau deviendra le noyau par défaut au démarrage.
Pensez simplement à vérifier qu'il n'y a pas trop de noyaux installés, la flash
ne fait que 126MiO, la commande df -h
permet de s'assurer qu'il reste
suffisamment d'espace.
De même, il est recommandé d'éviter de tester des noyaux en permanence, une
flash n'étant pas censée être écrite fréquemment.
Revenir à un ancien noyau
À chaud
Si le système est démarré, il suffit de régénérer la configuration du noyau que
l'on souhaite booter.
Par exemple, pour revenir au noyau 3.16 :
dpkg-reconfigure linux-image-3.16.0-0.bpo.4-kirkwood
À froid (busybox)
Si le système ne démarre pas (ex: noyau défectueux), il faut connecter la
console série et, depuis la busybox de l'initramfs monter la partition ubifs et
écraser les fichiers de kernel et d'initramfs avec ceux du kernel souhaité (ici
3.16) :
ubiattach /dev/ubi_ctrl -m 2 # plugs /dev/mtd2 as /dev/ubi0
mount /dev/ubi0_0 /boot/
cd /boot
cp uInitrd-3.16.0-0.bpo.4-kirkwood uInitrd
cp uImage-3.16.0-0.bpo.4-kirkwood uImage
reboot
À froid (uboot)
Si le noyau ne démare pas du tout, vous n'aurez pas la busybox. Il reste quand
même possible de démarrer sur un ancien noyau directement de puis uboot, par
exemple pour démarrer sur le kernel 4.19.0-6-marvell :
=> ubifsload 0x1000000 /uImage-4.19.0-6-marvell ; ubifsload 0x1200000 /uInitrd-4.19.0-6-marvell ; bootm 0x1000000 0x1200000 0x0900000
Cela démarrera temporairement sur l'ancien noyau, appliquer ensuite la
procédure à chaud.
Conclusion
Nous avons une vraie machine basse conso au stockage redondant sous Debian.
L'aspect logiciel NAS de la chose est en dehors du champ de
cet article, mais pourrait inclure :
- création de sous-volumes (btrfs)
- gestion des snapshots (btrfs)
- serveur samba
- installation de services avec yunohost
Il est possible que la partie sous-volumes/snapshots fasse l'objet d'un article
ultérieur...
Bonus
Gestion du ventilateur
wget https://github.com/lentinj/dns-nas-utils/raw/master/dns-nas-utils.deb
dpkg -i dns-nas-utils.deb
Lire/écrire les paramètres u-boot depuis le système
Une fois le NAS installé, pour éviter de devoir sortir le câble série à chaque
petite modification dans les paramètres d'u-boot.
Lister les partitions:
# cat /proc/mtd
dev: size erasesize name
mtd0: 000e0000 00020000 "u-boot"
mtd1: 00020000 00020000 "u-boot-env"
mtd2: 07f00000 00020000 "root"
Indiquer la partition de configuration u-boot d'après les paramètres précédents.
/etc/fw_env.config
# dev: Device offset size ereasesize
/dev/mtd1 0x00000 0x20000 0x20000
Lire :
Mettre fooval dans la variable foo :
Notes de mise à niveau Debian
Les mises à niveau se font bien. Je n'ai jamais réinstallé Debian (historique
du NAS : Wheezy, Jessie, Stretch, Buster).
Il y a quelques fois des petits points spécifiques à ce matériel qu'il convient
de prendre en compte auxquels je me suis frotté. J'écris donc ces notes dans
l'espoir de t'éviter de sortir le cable série pour un dépanage dans
l'urgence.
Notes généralistes : passage d'une version de Debian à une autre
Attention à l'espace dans /boot
; celui-ci étant physiquement sur la NAND, sa
capacité est limitée à 114Mio.
Conseil : ne garder que deux noyaux Linux (paquets linux-image-*
) ; donc
faire le ménage avant une mise à niveau pour n'en garder qu'un (l'actuel), la
mise à niveau en installera un nouveau.
Mise à niveau Debian Buster
Lire aussi les notes de version officielles pour Debian
Buster.
L'argument mtdparts
passé par u-boot au noyau a été renommé en
cmdlinepart.mtdparts
(détails dans le bug #831352).
Si on ne s'adapte pas à cette modification, le /boot
ne se monte plus au
démarrage (on peut également constater que le périphérique /dev/ubi0
n'existe
plus).
Pour éviter tout désagrément, juste après la mise à niveau mais avant de redémarrer, penser à faire :
fw_setenv bootcmd 'setenv bootargs console=${console} ${optargs} cmdlinepart.${mtdparts} ${root_hdd} ; run load_ubifs ; bootm 0x1000000 0x1200000 0x0900000'
Si tu as oublié de le faire avant de redémarrer, il faudra aller corriger ça à
l'aide du câble série directement dans la console u-boot:
setenv bootcmd 'setenv bootargs console=${console} ${optargs} cmdlinepart.${mtdparts} ${root_hdd} ; run load_ubifs ; bootm 0x1000000 0x1200000 0x0900000'
saveenv
boot
En modif notable (mais optionelle), il y a le renommage des interfaces réseau…
J'ai choisi de ne pas franchir le pas pour l'instant, attendant la prochaine
Debian (là, ça sera obligatoire).
Mise à niveau Debian Stretch
Lire aussi les notes de version officielles pour Debian Stretch.
-
Le paquet pump
(client DHCP) n'existe plus, donc pense à installer
isc-dhcp-client
en remplacement sous peine de perdre la connectivité IPv4 du
NAS.
-
Les paquets linux-image-kirkwood*
sont renommés/remplacés par
linux-image-marvell
, vérifier qu'un paquet linux-image-marvell
est
installé avant de rebooter.
Mise à niveau Debian Jessie
Lire aussi les notes de version officielles pour Debian Jessie.
Il y a un changement à faire dans le fichier /etc/fstab pour le montage du /boot
.
Références
commentaires