Partager un dossier avec Samba dans un module customConfig

Partager un dossier avec le reste du réseau, Windows compris, tient dans un module d'une trentaine de lignes. Encore faut-il choisir les bonnes options, et savoir que Samba tient sa propre base de mots de passe, ce qui surprend tout le monde la première fois. Cet article détaille un partage authentifié, la variante ouverte à tous en lecture, toutes les options que vous pouvez poser, et le montage depuis une autre machine.

:information_source: Remarque
Cet article fait partie d'une série sur les modules à importer dans customConfig. Si vous n'avez jamais édité ces fichiers, lisez d'abord Ajouter vos programmes et Configuration personnalisée.


Ce que vous obtenez

  • un dossier accessible depuis Windows, macOS, Linux, un téléviseur ou un téléphone ;
  • l'accès protégé par un compte et un mot de passe ;
  • la machine visible dans le voisinage réseau, sans avoir à retenir son adresse IP ;
  • le dossier créé automatiquement avec les bons droits.

Le fichier

Créez /etc/nixos/customConfig/samba.nix, en remplaçant nobodyz par votre identifiant :

{ ... }:

{
  services.samba = {
    enable = true;
    openFirewall = true;

    settings = {
      global = {
        "server string" = "GLF OS";
        workgroup = "WORKGROUP";
        security = "user";
        "server min protocol" = "SMB3";
        "map to guest" = "never";
      };

      partage = {
        path = "/srv/partage";
        comment = "Dossier partagé";
        browseable = "yes";
        "read only" = "no";
        "guest ok" = "no";
        "valid users" = "nobodyz";
        "create mask" = "0664";
        "directory mask" = "0775";
      };
    };
  };

  systemd.tmpfiles.rules = [
    "d /srv/partage 0775 nobodyz users -"
  ];
}

Ce que fait chaque ligne

Le nom de la section devient le nom du partage. Ici partage, donc \\GLF-OS\partage depuis Windows et smb://glf-os/partage depuis un gestionnaire de fichiers Linux. Choisissez un nom court, sans espace ni accent, la vie est plus simple.

La section global règle le serveur dans son ensemble. security = "user" demande une authentification, map to guest = "never" refuse les inconnus au lieu de les basculer en invités, et server min protocol = "SMB3" refuse les vieux dialectes du protocole, ceux qui traînent des faiblesses connues.

openFirewall ouvre les ports nécessaires : 139 et 445 en TCP, 137 et 138 en UDP. Sans lui, le service tourne mais personne ne le voit.

systemd.tmpfiles.rules crée le dossier au démarrage s'il n'existe pas, avec le propriétaire et les droits voulus. Sans cette ligne, il faudrait penser au mkdir et au chown à la main sur chaque machine, ce qui va à l'encontre de l'esprit de NixOS. La syntaxe se lit ainsi : d pour dossier, le chemin, les droits, le propriétaire, le groupe, et le tiret qui veut dire « ne rien nettoyer automatiquement ».


Le mot de passe Samba, distinct du mot de passe Linux

C'est la surprise classique, et le message d'erreur ne le dit pas clairement.

Samba tient sa propre base d'utilisateurs. Le compte doit exister sur le système, mais son mot de passe Samba se définit à part :

sudo smbpasswd -a nobodyz

Sans cette commande, la connexion sera refusée même avec le bon mot de passe de session. Vous pouvez d'ailleurs choisir un mot de passe différent, ce qui n'est pas idiot : il ne donne accès qu'aux partages, pas à la machine.

Pour voir qui est déclaré :

sudo pdbedit -L

Activer le module

Dans /etc/nixos/customConfig/default.nix :

{
  imports = [ ./samba.nix ];

  environment.systemPackages = [
  # Add your stable apps here (exemple: pkgs.btop)

Puis :

glf-update
sudo smbpasswd -a nobodyz

Les options d'un partage

Option Ce qu'elle fait
path le dossier partagé, seule option vraiment obligatoire
comment la description affichée aux clients
browseable yes pour apparaître dans la liste, no pour un partage que l'on atteint seulement en tapant son nom exact
read only no autorise l'écriture. writable = "yes" dit la même chose à l'envers, choisissez une forme et tenez-vous-y
guest ok yes autorise l'accès sans identifiants
valid users la liste blanche des comptes autorisés. @groupe désigne un groupe entier
write list ceux qui peuvent écrire alors que le partage est en lecture seule pour les autres
force user / force group le propriétaire attribué aux fichiers créés, quel que soit leur auteur
create mask / directory mask les droits des nouveaux fichiers et des nouveaux dossiers
hosts allow / hosts deny un filtre par adresse, par exemple hosts allow = 192.168.1.
veto files des motifs de fichiers rendus invisibles, par exemple /.DS_Store/Thumbs.db/
available no désactive le partage sans supprimer sa déclaration

Et du côté de la section global :

Option Ce qu'elle fait
workgroup le groupe de travail, WORKGROUP sur la plupart des réseaux domestiques
server string le nom affiché dans le voisinage réseau
security user demande une authentification, c'est le réglage normal
map to guest never refuse les inconnus, bad user les bascule en invités
server min protocol SMB3 refuse les vieux dialectes. Descendez à SMB2_10 seulement si un appareil ancien ne se connecte plus
log level 1 par défaut, montez-le le temps d'un diagnostic puis redescendez-le

La variante ouverte à tous, en lecture seule

Pour mettre des fichiers à disposition de tout le réseau local, sans compte ni mot de passe :

{
  services.samba.settings = {
    global = {
      security = "user";
      "map to guest" = "bad user";
    };

    public = {
      path = "/srv/public";
      comment = "Fichiers à disposition";
      browseable = "yes";
      "read only" = "yes";
      "guest ok" = "yes";
      "force user" = "nobody";
    };
  };
}

map to guest = "bad user" est la pièce maîtresse : un client qui se présente avec un nom inconnu est traité comme invité au lieu d'être rejeté.

:stop_sign: Prudence
Un partage invité accessible en écriture signifie que n'importe quel appareil du réseau peut y déposer ou y effacer des fichiers, y compris l'objet connecté dont vous avez oublié l'existence, et y compris la machine de quelqu'un qui aurait rejoint votre réseau. Réservez l'écriture aux partages authentifiés, et ne mettez jamais de données personnelles dans un partage invité.


Être vu sur le réseau

Les autres machines doivent encore vous trouver. Deux mécanismes se complètent :

{
  services.samba-wsdd = {
    enable = true;
    openFirewall = true;
  };

  services.avahi = {
    enable = true;
    nssmdns4 = true;
    publish = {
      enable = true;
      addresses = true;
      workstation = true;
      userServices = true;
    };
  };
}

samba-wsdd répond au protocole de découverte des Windows récents, qui n'utilisent plus l'ancien voisinage réseau. Sans lui, votre machine n'apparaît tout simplement pas dans l'explorateur de fichiers de Windows, même si le partage fonctionne parfaitement quand on tape son adresse.

avahi fait la même chose pour les machines Linux et Apple, et vous offre au passage le nom glf-os.local, qui évite de retenir une adresse IP.


Monter le partage depuis une autre machine GLF OS

Le plus simple est d'utiliser Nix Samba, notre application maison, décrite dans Nix Samba. Elle fait tout cela pour vous, avec une interface.

Si vous préférez le faire à la main, il manque un détail bien caché sur NixOS : l'assistant de montage doit être installé et déclaré comme programme privilégié, sinon vous obtenez un refus de permission même avec sudo.

{ pkgs, ... }:

{
  environment.systemPackages = [ pkgs.cifs-utils ];

  security.wrappers."mount.cifs" = {
    setuid = true;
    owner = "root";
    group = "root";
    source = "${pkgs.cifs-utils}/bin/mount.cifs";
  };
}

Le montage automatique se déclare ensuite comme n'importe quel autre système de fichiers :

{
  fileSystems."/mnt/partage" = {
    device = "//192.168.1.42/partage";
    fsType = "cifs";
    options = [
      "credentials=/etc/samba/credentials"
      "uid=1000"
      "gid=100"
      "x-systemd.automount"
      "noauto"
      "x-systemd.idle-timeout=60"
    ];
  };
}

Les deux options à retenir sont x-systemd.automount et noauto : le partage n'est monté qu'au premier accès, et son absence ne bloque plus le démarrage de la machine quand le serveur est éteint. Sans elles, une machine qui démarre alors que le serveur dort attend, puis échoue, et vous vous retrouvez devant un écran de secours pour un simple partage de fichiers.

Le fichier /etc/samba/credentials contient deux lignes, username= et password=, et doit être en 0600. Plutôt que de l'écrire à la main, c'est le cas d'école du sops.templates décrit dans l'article sur sops :

{
  sops.secrets."samba-mot-de-passe" = { };

  sops.templates."samba-credentials" = {
    content = ''
      username=nobodyz
      password=${config.sops.placeholder."samba-mot-de-passe"}
    '';
    path = "/etc/samba/credentials";
    mode = "0600";
  };
}

Ce bloc utilise config, pensez donc à le déclarer dans l'en-tête du fichier : { config, pkgs, ... }:.


Vérifier que tout va bien

testparm                                # relit la configuration et signale les erreurs
smbclient -L //localhost -U nobodyz     # liste les partages visibles
systemctl status samba-smbd             # état du service principal
sudo smbstatus                          # qui est connecté, et sur quoi

testparm est le premier réflexe : il vous dit immédiatement si une option est mal orthographiée, ce que Nix ne peut pas vérifier pour vous, puisque ces réglages sont recopiés tels quels dans le fichier de configuration de Samba.


Les options que vous pouvez changer

  • Alléger les services. services.samba.nmbd.enable et services.samba.winbindd.enable sont actifs par défaut. Le premier sert l'ancien voisinage réseau, le second l'intégration à un domaine d'entreprise. Sur un réseau domestique moderne, vous pouvez les couper et garder samba-wsdd seul :
    services.samba.nmbd.enable = false;
    services.samba.winbindd.enable = false;
    
  • Une corbeille plutôt qu'une suppression définitive, dans la section du partage :
    "vfs objects" = "recycle";
    "recycle:repository" = ".corbeille";
    "recycle:keeptree" = "yes";
    
  • Partager le dossier personnel de chaque utilisateur, avec la section spéciale homes, que Samba utilise comme modèle : chacun voit le sien et pas celui des autres.
  • Partager une imprimante : voyez load printers et la section printers.
  • Limiter l'accès à votre réseau local, ce qui est une bonne précaution si la machine voyage :
    "hosts allow" = "192.168.1. 127.";
    
  • Gérer le pare-feu ailleurs : mettez openFirewall = false et déclarez vous-même les ports 139 et 445 en TCP, 137 et 138 en UDP.

En cas de problème

  • L'accès est refusé avec le bon mot de passe : vous avez oublié sudo smbpasswd -a <utilisateur>. C'est la cause dans la grande majorité des cas.
  • La machine n'apparaît pas dans l'explorateur Windows : samba-wsdd n'est pas actif, ou son port n'est pas ouvert. Testez d'abord en tapant directement \\192.168.1.42 dans la barre d'adresse : si cela fonctionne, le partage va bien et c'est uniquement la découverte qui manque.
  • Vous voyez le partage mais ne pouvez pas écrire : regardez les droits du dossier sur le disque, pas seulement les options Samba. Les deux doivent autoriser l'écriture, Samba ne peut pas donner plus que ce que le système de fichiers permet.
  • Un vieil appareil ne se connecte plus : il ne parle probablement que SMB1 ou SMB2. Descendez server min protocol à SMB2_10, en sachant que vous abaissez la sécurité de tout le serveur.
  • Le montage échoue avec un refus de permission : le wrapper mount.cifs manque, voyez la section sur le montage.
  • testparm se plaint d'une option inconnue : une faute de frappe. Les noms d'options contiennent des espaces et se recopient à l'identique de la documentation de Samba.

Voir aussi