{{tag>tutoriel Noble zfs chiffrement raid}}
===== Introduction  =====
ZFS est un   [[:systeme_de_fichiers#systemes_de_fichiers_zfs|système de fichiers]] [[https://fr.wikipedia.org/wiki/Open_source|open source ]]pour la gestion de "[[https://fr.wikipedia.org/wiki/ZFS|très haute capacité de stockage]]". \\
ZFS est  utilisable sous Ubuntu, sous [[https://openzfsonosx.org/wiki/Downloads#2.2.2|mac]]  et sous [[https://github.com/openzfsonwindows/openzfs/releases/tag/zfswin-2.2.3rc5|windows]] \\
Ce document traite de l'utilisation de ZFS à partir de la version 24.04 de ubuntu pour stocker les données des utilisateurs. \\
Pour toute version  antérieure, se référer à [[:utilisateurs/bcag2/zfs|ce document.]]
===== Pré-requis =====
Soit disposer d'une version ubuntu ZFS  **24.04** chiffrée[[https://doc.ubuntu-fr.org/_media/tutoriel/installer_ubuntu_avec_subiquity/41.png?w=600&tok=1d4597|installée]] dans la totalité d'un disque dur pouvant être externe. \\
Soit disposer d'une version ubuntu **24.04**  installée de façon classique dans une partition  EXT4 ou BTRFS. \\
Lors de  l'installation de la version standard 24.04.1, il  est nécessaire d'ajouter le  paquet **[[apt>zfs-zed|zfs-zed]]** 
===== Création de l'enveloppe de stockage =====
Ce tuto montre un cas d'utilisation en structure sécurisée nécessitant au moins deux partitions avec des données chiffrées.\\
Bien entendu, il est possible de ne pas choisir l'option de chiffrement et de ne pas utiliser la redondance. \\
==== Sélection de l'espace disque. ====
Grâce à l'application [[https://doc.ubuntu-fr.org/gparted|gparted]], fabriquer deux partitions de tailles identiques. de préférence dans deux disques différents. \\
Si les partitions utilisées sont déjà formatées ZFS, il est nécessaire de les reformater (en EXT4 par exemple) car la création sera refusée. Sinon, les partitions peuvent être déclarées non-formatées.
==== Mise  disposition de cet espace disque ====
La mise à disposition pour  l'utilisateur de cet espace prévu, se fait obligatoirement en ligne de commande.\\ L'auto-documentation (man zpool create) n'est pas mauvaise mais elle dispose de peu d'exemples pratiques.  \\ Voici la commande à exécuter.
sudo zpool create -f -m   /media/ZFS -O encryption=on -O keyformat=passphrase -O keylocation=prompt  -o feature@lz4_compress=enabled MesDonneesPersonnelles raidz /dev/sda18 /dev/sdb11
Enter new passphrase:
cannot create 'MesDonneesPersonnelles': Passphrase too short (min 8). \\
  * ''-f'' indique de forcer le montage. 
  * ''-m'' indique le point de montage à utiliser. J'ai choisis **media** à cause des applications snap.
  * ''-O encryption=on'' indique Option de chiffrement activée.
  * ''-O keyformat=passphrase'' Indique Option  de format de la phrase de chiffrement au format lisible.
  * ''-O keylocation=prompt'' indique Option  de saisie de la phrase au clavier d'où le choix du format lisible.
  * ''-o feature@lz4_compress=enabled'' indique option  de compression **LZ4** activée. La littérature semble conseiller cette option.
  * ''[[https://www.recuperation-donnees-raid.com/raid-z|raidz]]'' Indique que l'accès aux partitions se fait dans ce format équivalent au format [[https://doc.ubuntu-fr.org/raid_logiciel|raids5]]. On pouvait ne rien mettre ou mettre **mirror**  équivalent du RAID1.
A l'issue de cette commande réussie, le point de montage ''/media/ZFS'' est automatiquement créé et accessible en écriture.
Si l'une des partitions est stockée dans un disque externe, n'utiliser le nommage **/dev/sdXn** qui  peut évoluer en fonction des montages, mais le nom réel de la partition **/dev/disk/by-id/xxxxxxxxxx** 
===== Réutilisation de cet espace disque lors d'un nouveau démarrage =====
Le logiciel ZFS étant actuellement en phase expérimentale, il n'est pas facile de savoir si l'**oubli** de rendre disponible auprès de l'utilisateur ces données **__chiffrées__**, est définitif ou sera réparé. \\ Voici trois palliatifs.
==== Solution manuelle ====
Lorsque l'utilisateur se connecte, il doit penser à monter la structure zfs s'il souhaite l'utiliser. La seule solution est la ligne de commande. C'est simplement:
sudo zfs mount -vl MesDonneesPersonnelles
Le mot de déchiffrement sera demandé  à l'écran de l'utilisateur.
==== Solution standard====
Un service **utilisateur** demande la valeur  de la clé de chiffrement au moment de la connexion de l'utilisateur.
=== Le script de montage ===
cat<<'EOF'>$HOME/ZFS.sh
#!/bin/bash
Data=MesDonneesPersonnelles
Statut=$(zpool list  $Data |tail -1 )
if [[ !  $Statut =~  "$Data"  ]] ; then 
   echo  Importation des données par  le service USER de ZFS  
   sudo zpool export  $Data ### Pour se prémunir des noms de partitions des disques externes susceptible de changer de valeur si besoin
   sudo zpool import -f $Data
fi
sudo zfs set mountpoint=/media/$Data $Data
for (( i=1; i < 9; i++ ));  do 
    echo  itération-$i dans le service USER de ZFS  
    Statut=$(zfs get mounted  $Data |tail -1 )
    if [[  $Statut =~  "no"  ]] ; then 
       ret=`DISPLAY=:1 zenity --entry --title="Montage de la partition $Data ($i/8)." --text "veuillez fournir la phrase de déchiffrement de $Data." `
       sleep 2
       sudo zfs mount -l $Data <<<$ret
    else i=10    
    fi   
done
if  [[ ! $Statut =~  "yes"  ]] ; then
    DISPLAY=:1 zenity --error --text "La partition $Data n'est pas disponible; veuillez investiguer!"
fi
EOF
sleep 1
chmod +x /$HOME/ZFS.sh
cat $HOME/ZFS.sh
$HOME/ZFS.sh
=== Le script d'automatisation ===
mkdir -pv $HOME/.config/systemd/user
cat <<'EOF'>$HOME/.config/systemd/user/ZFS.service
[Unit]
Description=Montage de la partition de données personnelles.
DefaultDependencies=no
[Service]
Type=simple
ExecStartPre=echo  Montage de la partition de données personnelles ZFS. 
ExecStart=/home/%u/ZFS.sh
ExecStopPost=echo Le ontage de la partition de données personnelles ZFS  est terminé.
StandardOutput=journal+console
[Install]
WantedBy=default.target
EOF
sleep 1
systemctl  --user stop ZFS.service ; systemctl --user  disable ZFS.service ; systemctl --user daemon-reload; 
systemctl --user enable ZFS.service ; systemctl --user start ZFS.service 
systemctl --user --no-pager -l status ZFS.service 
==== Solution automatique alternative====
**La valeur de la clé de déchiffrement doit être dans un fichier**. Il  existe trois solutions: 
  - Le logiciel  est déjà chiffré. Dans ce cas  la valeur de la clé de chiffrement  peut être dans un fichier stocké sous** /root**. Solution aisément installable.
  - Le logiciel n'est pas chiffré, La clé de chiffrement  peut être dans une clé usb que l'utilisateur branche au moment de se connecter et enlève aussitôt la connexion réalisée. C'est la solution privilégiée par les concepteurs. Solution aisément installable avec un risque de  perdre la clé ou qu'elle soit lue par une  personne non-habilitée.
  - Un service **système** demande à l'utilisateur la valeur  de la clé de chiffrement, la stocke dans un fichier, ouvre la structure chiffrée et détruit le contenu du fichier. Cela ne laisse que quelques instants cette valeur disponible à la vue de tout le monde.... C'est un développement personnel susceptible d'être amélioré par qui connaît mieux. \\ Il est basé sur  les services de [[:/systemd|systemd]] qui  semblent destinés à se passer d'utilisateur. Le dialogue à l'écran étant inconnu.
S'affranchir de la contrainte des mots de passe si cela n'a pas déjà été fait:
echo $USER  ALL = '(ALL)' NOPASSWD: /usr/sbin/zpool, /usr/sbin/zfs |sudo tee /etc/sudoers.d/zfsbis
Devenir administrateur en frappant **sudo -i** pour définir la nouvelle commande de création de l'espace à utiliser. 
echo -n LeBonMotDeDéchiffrement | tee /root/ZFS.pwd
wc /root/ZFS.pwd ; cat /root/ZFS.pwd
zpool create -f -m   /media/ZFS -O encryption=on -O keyformat=passphrase -O keylocation=file:///root/ZFS.pwd -o feature@lz4_compress=enabled MesDonneesPersonnelles raidz /dev/sda18 /dev/sdc11
shred  /root/ZFS.pwd
Penser à personnaliser la première ligne  et le nom retenu pour la désignation de l'espace de stockage.
=== Le script de montage ===
cat<<'EOF'>/root/ZFS.sh
#!/bin/bash
Data=MesDonneesPersonnelles
echo  Entrée dans le service USER de ZFS  | tee -a  /dev/kmsg
for (( i=1; i < 300; i++ ));  do
MOI=$(loginctl list-users | head -2 | tail -1)
IDn=$(echo $MOI | cut -d" " -f1) ; IDx=$(echo $MOI | cut -d" " -f2) ;
if [[  $IDn -gt  999   ]] ; then
   i=300
else   
   sleep 1
   echo  itération-1-$i dans le module USER de ZFS  | tee -a  /dev/kmsg
fi 
done
for (( i=1; i < 9; i++ ));  do 
    echo  itération-2-1-$i dans le service USER de ZFS  | tee -a  /dev/kmsg
    Statut=$(zfs get mounted  $Data |tail -1 )
    if [[  $Statut =~  "no"  ]] ; then 
       ret=`sudo -u $IDx DISPLAY=:1 zenity --entry --title="Montage de la partition $Data ($i/8)." --text "veuillez fournir la phrase de déchiffrement de $Data." `
       echo $ret  > /root/ZFS.pwd
       sleep 1
       zfs mount -vl $Data       
       shred -n 0 -z  /root/ZFS.pwd 
    else i=10    
    fi   
done
if  [[ ! $Statut =~  "yes"  ]] ; then
   sudo -u $IDx DISPLAY=:1 zenity --error --text "La partition $Data n'est pas disponible; veuillez investiguer!"
fi
EOF
sleep 1
chmod +x /root/ZFS.sh
cat /roo/ZFS.sh
/root/ZFS.sh
Penser à personnaliser la troisième ligne. Cela ne coute rien de l'essayer.
=== Le script d'automatisation ===
cat <<'EOF'>/etc/systemd/system/ZFS.service
[Unit] 
Description=Montage de la partition de données personnelles.
DefaultDependencies=no
[Service]
Type=simple
TimeoutSec=5minutes
ExecStartPre=echo  Montage de la partition de données personnelles ZFS. |  tee -a  /dev/kmsg
ExecStartPre=sleep 60
# Temps approximatif pour l'arrivée de l'écran d'accueil
ExecStartPre=echo  Montage de la partition de données personnelles ZFS ( Fin de sommeil ) |  tee -a  /dev/kmsg
ExecStart=/root/ZFS.sh
ExecStopPost=echo Montage de la partition de données personnelles ZFS  est terminé  |  tee -a  /dev/kmsg
StandardOutput=journal+console
StandardError=journal+console
[Install]
WantedBy=multi-user.target
EOF
sleep 1
##### Essais.
systemctl  stop ZFS.service ; systemctl  disable ZFS.service ; systemctl --user daemon-reload; 
systemctl enable ZFS.service ; systemctl start ZFS.service 
systemctl  --no-pager -l status ZFS.service  
exit
===== Quelques essais =====
==== Une utilisation classique pour sauvegarder les données personnelles ====
=== Création du répertoire ===
sudo mkdir /media/ZFS/$USER
sudo chown -Rv $USER  /media/ZFS/$USER 
sudo chmod 775 /media/ZFS/$USER 
=== Déplacement des répertoires ===
mv -v Documents Images Modèles Musique Public Téléchargements Vidéos    /media/ZFS/$USER 
=== Création les liens ===
ln -s  /media/ZFS/$USER/Documents ; ln -s  /media/ZFS/$USER/Images ; ln -s   /media/ZFS/$USER/Modèles   ; ln -s   /media/ZFS/$USER/Musique ; ln -s  /media/ZFS/$USER/Public ; ln -s  /media/ZFS/$USER/Téléchargements ; ln -s   /media/ZFS/$USER/Vidéos
mv -v Bureau /media/ZFS/$USER && ln -s /media/ZFS/$USER/Bureau 
=== Figer le changement ===
cp -v /etc/xdg/user-dirs.conf $HOME/.config && sed -i 's/True/False/' $HOME/.config/user-dirs.conf 
==== Une utilisation possible avec utilisation de quotas. ====
Cela passe par la création des sous-ensembles (équivalents aux sous-répertoires). \\
Il n'est pas obligatoire de limiter. \\  On  constate que la limite  du  remplissage semble bien fixée à  80% de l'espace prévu.
sudo zfs create -o quota=15G  MesDonneesPersonnelles/sports
sudo zfs create -o quota=5G  MesDonneesPersonnelles/sports/Foot
rsync -av --stats /media/$USER/Commun/Football/* /media/ZFS/sports/Foot/a 
sending incremental file list
Finale4.mp4
Finale5.mp4
rsync: [receiver] write failed on "/media/ZFS/sports/Foot/a/Finale5.mp4": Disk quota exceeded (122)
rsync error: error in file IO (code 11) at receiver.c(380) [receiver=3.2.7]
rsync: [sender] write error: Broken pipe (32)
df -htzfs | grep -E "Taille|Mes"
Sys. de fichiers                                 Taille Utilisé Dispo Uti% Monté sur
MesDonneesPersonnelles                              43G    240M   42G   1% /media/ZFS
MesDonneesPersonnelles/sports                       11G    256K   11G   1% /media/ZFS/sports
MesDonneesPersonnelles/sports/Foot                 5,0G    4,1G  982M  81% /media/ZFS/sports/Foot
==== Sauvegarder des O.S. ====
Sauvegarder un UBUNTU
sudo mkdir /media/ZFS/Ubuntu
time sudo rsync -avx / /media/ZFS/Ubuntu
sent 7.823.372.276 bytes  received 3.206.862 bytes  10.484.365,89 bytes/se
real	12m26,492s
Sauvegarder un Windows
sudo partclone.ntfs -c -d -s /dev/sda4 -o /media/ZFS/Windows.sda4.pcl
Current block:   18174668, Total block:   18175999, Complete: 100.00%           
Durée totale : 00:16:54, Ave. Rate:   2,77GB/min, 100.00% completed!
===== Quelques commandes utiles =====
==== Connaitre la place disque utilisée ====
 df -htzfs | grep -E "Taille|Mes" && zfs get all MesDonneesPersonnelles | grep ratio
Sys. de fichiers                                 Taille Utilisé Dispo Uti% Monté sur
MesDonneesPersonnelles                              43G     32G   12G  74% /media/ZFS
MesDonneesPersonnelles/sports                       11G    256K   11G   1% /media/ZFS/sports
MesDonneesPersonnelles/sports/Foot                 5,0G    4,1G  982M  81% /media/ZFS/sports/Foot
MesDonneesPersonnelles  compressratio         1.53x                    -
MesDonneesPersonnelles  refcompressratio      1.60x   
==== Agrandir l'espace disque ====
Pas d'autre choix que l'ajout de deux partitions  de même taille mais pas obligatoirement  la même que les deux premières partitions.
sudo zpool add -f  MesDonneesPersonnelles raidz /dev/sdc12 /dev/sdc13
zpool status MesDonneesPersonnelles
  pool: MesDonneesPersonnelles
 state: ONLINE
config:
	NAME                    STATE     READ WRITE CKSUM
	MesDonneesPersonnelles  ONLINE       0     0     0
	  raidz1-0              ONLINE       0     0     0
	    sda18               ONLINE       0     0     0
	    sdc11               ONLINE       0     0     0
	  raidz1-1              ONLINE       0     0     0
	    sdc12               ONLINE       0     0     0
	    sdc13               ONLINE       0     0     0
La commande suivante aurait pu fonctionner. [[https://bugs.launchpad.net/ubuntu/+source/subiquity/+bug/2069343|Mais...]].
 sudo zpool attach -f  MesDonneesPersonnelles raidz1-0 /dev/sdc12
cannot attach /dev/sdc12 to raidz1-0: can only attach to mirrors and top-level disks 
==== Remplacer un disque ====
time sudo zpool replace -fw MesDonneesPersonnelles  /dev/sdc13 /dev/sda10
real	33m6,724s
user	0m0,007s
sys	0m0,012s
zpool status MesDonneesPersonnelles 
  pool: MesDonneesPersonnelles
 state: ONLINE
  scan: resilvered 36.1G in 00:33:01 with 0 errors on Fri Jun 14 17:36:18 2024
config:
	NAME                    STATE     READ WRITE CKSUM
	MesDonneesPersonnelles  ONLINE       0     0     0
	  raidz1-0              ONLINE       0     0     0
	    sda18               ONLINE       0     0     0
	    sdc11               ONLINE       0     0     0
	  raidz1-1              ONLINE       0     0     0
	    sdc12               ONLINE       0     0     0
	    sda10               ONLINE       0     0     0
errors: No known data errors
===== Partage réseau =====
Avant de pouvoir autoriser le partage réseau, pour éviter l'erreur **NFS share creation failed
**, il est nécessaire  d'installer la couche Réseau:  Voir le paragraphe  [[:nfs#installation|3.1]]. \\  L'autorsation ZFS se fait alors facilement. \\ Exemple pour un niveau intermédiaire:
zfs get sharenfs MesDonneesPersonnelles/sports
NAME                           PROPERTY  VALUE     SOURCE
MesDonneesPersonnelles/sports  sharenfs  off       local
 
sudo zfs set  sharenfs=on MesDonneesPersonnelles/sports
zfs get sharenfs MesDonneesPersonnelles/sports
NAME                           PROPERTY  VALUE     SOURCE
MesDonneesPersonnelles/sports  sharenfs  on        local
Il reste alors à régler la configuration du NFS telle que décrite dans le paragraphe [[:/nfs#configuration|3.2]]
===== Traitement de quelques incidents ======
==== Incident inhérent  la conception  de zfs ====
La fabrication d'un espace de stockage ZFS se fait en utilisant les noms courts des partitions. Par exemple SDC11. \\
Le premier risque est que la lettre de la partition change. Spécialement le cas si la partition est stockée dans un disque externe. \\
Le second risque est que le numéro de partition change. Dans un environnement UBUNTU, il faut lancer  une commande spécifique (sgdisk). Mais si le disque côtoie windows et que son gestionnaire de partition est lancé, cette renumérotation est systématique.\\
Dans les deux cas, au final, l'espace est dégradé.
zpool status MesDonneesPersonnelles
  pool: MesDonneesPersonnelles
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
	invalid.  Sufficient replicas exist for the pool to continue
	functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-4J
  scan: scrub repaired 0B in 00:04:11 with 0 errors on Sat Jun 15 19:25:40 2024
config:
	NAME                      STATE     READ WRITE CKSUM
	MesDonneesPersonnelles    DEGRADED     0     0     0
	  raidz1-0                DEGRADED     0     0     0
	    sda18                 ONLINE       0     0     0
	    17089491904315129872  UNAVAIL      0     0     0  was /dev/sdc11
	  raidz1-1                DEGRADED     0     0     0
	    9901095314787895760   UNAVAIL      0     0     0  was /dev/sdc12
	    sda10                 ONLINE       0     0     0  block size: 512B configured, 4096B native
errors: No known data errors
Après quelques tâtonnements dont l'un empêchait l'utilisateur de se connecter après un reboot inutile, la bonne réparation (faite en mode root dans ce contexte) est  d'exporter et de réimporter la structure sans vouloir lancer des réparations.
sudo zpool export MesDonneesPersonnelles
sudo zpool import MesDonneesPersonnelles
Il était probablement inutile de bricoler pour retrouver la lettre C et les numéros 11 et 12.
==== Importation dans une version 22.04 ====
sudo apt install zfs-zed --simulate 
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances... Fait
Lecture des informations d'état... Fait      
zfs-zed est déjà la version la plus récente (2.1.5-1ubuntu6~22.04.4).
zfs-zed passé en « installé manuellement ».
0 mis à jour, 0 nouvellement installés, 0 à enlever et 3 non mis à jour.
sudo zpool import -f Commun
This pool uses the following feature(s) not supported by this system:
	com.klarasystems:vdev_zaps_v2
cannot import 'Commun': unsupported version or feature
Comme une fonctionnalité activée ne peut pas s'invalider, il aurait fallu créer l'espace en indiquant de ne pas utiliser la fonctionnalité!
===== Annexes =====
  * [[https://www.recuperation-donnees-raid.com/raid-z|Présentation rapide du RAIDZ]]
  * [[https://www.raidz-calculator.com/raidz-types-reference.aspx|Detailled presentation of RAIDZ]]