NAS avec FreeBSD & ZFS

Pour remplacer mes disques USB pouvant me lâcher à tout moment, voici comment j’ai installé un NAS basé sur ZFS (pour les raisons que l’on peut retrouver dans cette présentation).

Choix de la plateforme

Actuellement, ZFS est proposé en natif sur FreeBSD et Solaris (et leurs dérivés). FreeNAS semble assez limité et concernant Solaris, même si OpenIndiana est prometteur, aucune version stable n’est actuellement disponible et maintenue en dehors du Solaris officiel.

Ma machine a donc la configuration suivante :

  • FreeBSD 8.2
  • Installation de l’OS sur une clé USB indépendante des fichiers stockés.
  • ZFS en RAIDZ (équivalent RAID5) pour le stockage des fichiers.

Installation de FreeBSD

L’OS est installé dans sa version minimale, en choisissant la clé USB comme cible. Pour le partitionnement, le / complet peut être monté sur un seul slice (les points de montage /usr et /tmp seront plus tard déplacés sur le pool ZFS) et la partition swap est crée sur la clé.
Lors de  la création des utilisateurs, ne pas oublier d’ajouter le groupe wheel au compte creé pour l’admin, afin de pouvoir utiliser su.

Au premier démarrage, il est possible que le système ne parvienne pas à monter la partition racine, si les périphériques USB ne sont pas encore actifs. Dans ce cas, charger le loader prompt au boot et démarrer avec :

set kern.cam.boot_delay=10000
boot

Une fois le système démarré, fixer la valeur kern.cam.boot_delay=10000 dans la configuration du chargeur de démarrage : /boot/loader.conf.

Mise en place de ZFS

La création du pool ZFS utilisant les quatre disques ad2, ad4, ad6 et ad8 se résume à la commande suivante :

# zpool create data raidz /dev/ad4 /dev/ad6 /dev/ad8 /dev/ad10

Pour la vérification du pool :

# zpool status
  pool: data
 state: ONLINE
 scrub: none requested
config:

    NAME        STATE     READ WRITE CKSUM
    data        ONLINE       0     0     0
      raidz1    ONLINE       0     0     0
        ad4     ONLINE       0     0     0
        ad6     ONLINE       0     0     0
        ad8     ONLINE       0     0     0
        ad10    ONLINE       0     0     0

errors: No known data errors

Il est ensuite préférable de créer des points de montage spécifiques pour faciliter la gestion :

# zfs create data/fichiers

On obtient donc :

# zfs list
NAME                         USED  AVAIL  REFER  MOUNTPOINT
data                        32.9K  2.73T  32.9K  /data
data/fichiers               72.6K  2.73T  72.6K  /data/fichiers

Si la machine sur laquelle est installée FreeBSD dispose de moins de 4 Go de RAM, le mécanisme de prefetch ZFS est désactivé par défaut, ce qui entraîne une diminution des performances en lecture / écriture.
Ma machine dispose de 4032 Mo de RAM ( le reste étant utilisé par le chipset vidéo intégré, impossible à désactiver…), j’ai donc forcé le prefetch en ajoutant le paramètre vfs.zfs.prefetch_disable=0 dans le fichier /boot/loader.conf

Installation des fichiers système sur le pool ZFS

Comme les performances en lecture / écriture d’une clé USB sont pour^W limitées, il est possible pour améliorer la réactivité du système de déplacer les points de montage /usr et /tmp sur le pool :

# zfs create data/tmp
# zfs create data/usr

Puisque ces points de montage n’ont pas à occuper trop d’espace, on y applique des quotas :

# zfs set quota=10G data/usr
# zfs set quota=5G data/tmp

On y copie les fichiers déjà présents sur le / monté sur la clé (avec conservation des droits et du propriétaire) :

# cp -pR /usr/* /data/usr/
# cp -pR /tmp/* /data/tmp/

Puis on active le montage de ces filesystem avec ZFS :

# zfs set mountpoint=/usr data/usr
# zfs set mountpoint=/tmp data/tmp

Pour vérifier ces points de montage :

# zfs list
NAME                         USED  AVAIL  REFER  MOUNTPOINT
data                        32.9K  2.73T  32.9K  /data
data/fichiers               72.6K  2.73T  72.6K  /data/fichiers
data/tmp                    65.1K  5.00G  65.1K  /tmp
data/usr                    2.05G  7.95G  2.05G  /usr

Pour que ces points de montage soient utilisables par le système, il faut activer ZFS au boot en ajoutant zfs_enable="yes" dans le fichier /etc/rc.conf.

Une fois qu’un redémarrage a été effectué, il peut être nécessaire de reconfigurer les droits du /tmp :

# chmod 1777 /tmp

On obtient ainsi un système complet sur la clé, mais dont les points de montage les plus sollicités se situent sur le pool ZFS. En cas de défaillance du pool ou d’oubli du zfs_enable="yes", les binaires situés dans /usr sont toujours présents dans le point de montage / et donc disponibles.

Gestion des ports et installation de Samba

Si ce n’est pas déjà fait, commencer par mettre à jour l’arbre des ports :

# portsnap fetch && portsnap extract

Puis installer Samba :

# cd /usr/ports/net/samba35
# make && make install

Configuration de Samba

Ici c’est relativement simple, on active le démarrage du démon dans le /etc/rc.conf avec : samba_enable="YES", puis dans le fichier de configuration de samba (/usr/local/etc/smb.conf), on ajoute le partage correspondant :

[fichiers]
comment = Fichiers
path = /data/fichiers
valid users = your_unix_username
public = no
writable = yes
printable = no

Par défaut, Samba n’est pas case-sensitive, mais il est possible d’activer cette fonction en ajoutant dans la définition du partage les paramètres suivants :

   case sensitive = yes
   default case = lower
   preserve case = yes
   short preserve case = yes

Reste ensuite a créer un mot de passe Samba (avec smbpasswd ou pdbedit) pour le user et à démarrer le démon :

# smbpasswd -a your_unix_username
# /usr/local/etc/rc.d/samba onestart

Les autorisations attribuées via samba sont les mêmes que celles attribuées au compte unix, il faut donc vérifier les droits sur le répertoire partagé (et les attribuer via le groupe wheel par exemple).
Enfin, il est nécessaire d’affecter un hostname à la machine et de fournir un DNS dans /etc/resolv.conf, sinon des erreurs de connexion ou timeout peuvent apparaitre pour les clients.

Le NAS est maintenant utilisable, mais certains points peuvent encore être améliorés.

Partage temporaire via http

Il est possible, afin de faciliter la gestion des partages, d’autoriser temporairement la lecture d’un répertoire via http, pour un visiteur par exemple. Pour cela, se placer dans le répertoire à partager et lancer le serveur http léger distribué avec python :

$ cd /data/fichiers/path/to/share
$ python -m SimpleHTTPServer 8080

Opérations additionnelles pour un pool ZFS

  • La vérification/correction des données présentes sur le pool est possible avec la commande :
    # zpool scrub pool_name

    Cette opération peut être longue et diminue les performances du pool pendant son exécution. Un scrub peut être interrompu à tout moment avec la commande zpool scrub -s pool_name et son avancement est visible dans zpool status.

  • Lorsque des snapshots ont été pris, les fichiers correspondants sont accessibles directement dans le répertoire .zfs/snapshot/ contenu à la racine du point de montage ZFS.
  • Il est toujours plus prudent de sauvegarder la configuration ZFS, qui est stockée dans le fichier /boot/zfs/zpool.cache et peut être affichée sous forme de texte via la commande zdb.
  • En cas de réinstallation du système, l’ensemble du pool ZFS peut être réimporté très facilement. On liste d’abord les pools détectés sur la machine :
     # zpool import

    Puis on importe celui voulu :

    # zpool import pool_name

    Les différents paramètres du pool seront également attachés, comme le montage automatique du /usr et /tmp qu’il faudra désactiver s’ils ne sont pas nécessaires.

Pour le reste, la documentation officielle est assez bien faite.