Difference between revisions of "Samba"

From NixOS Wiki
Jump to: navigation, search
m (Add smbpasswd command needed to access shares when setting up the smb server)
m (rollback unauthorized mass edits)
Tag: Rollback
 
(27 intermediate revisions by 20 users not shown)
Line 1: Line 1:
 
This guide will help you on how to use samba on nixos.
 
This guide will help you on how to use samba on nixos.
 +
 +
== Server setup ==
 +
 +
Example setup for creating a public guest share called <code>public</code> and a private share called <code>private</code>.
 +
 +
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 +
services.samba = {
 +
  enable = true;
 +
  securityType = "user";
 +
  openFirewall = true;
 +
  extraConfig = ''
 +
    workgroup = WORKGROUP
 +
    server string = smbnix
 +
    netbios name = smbnix
 +
    security = user
 +
    #use sendfile = yes
 +
    #max protocol = smb2
 +
    # note: localhost is the ipv6 localhost ::1
 +
    hosts allow = 192.168.0. 127.0.0.1 localhost
 +
    hosts deny = 0.0.0.0/0
 +
    guest account = nobody
 +
    map to guest = bad user
 +
  '';
 +
  shares = {
 +
    public = {
 +
      path = "/mnt/Shares/Public";
 +
      browseable = "yes";
 +
      "read only" = "no";
 +
      "guest ok" = "yes";
 +
      "create mask" = "0644";
 +
      "directory mask" = "0755";
 +
      "force user" = "username";
 +
      "force group" = "groupname";
 +
    };
 +
    private = {
 +
      path = "/mnt/Shares/Private";
 +
      browseable = "yes";
 +
      "read only" = "no";
 +
      "guest ok" = "no";
 +
      "create mask" = "0644";
 +
      "directory mask" = "0755";
 +
      "force user" = "username";
 +
      "force group" = "groupname";
 +
    };
 +
  };
 +
};
 +
 +
services.samba-wsdd = {
 +
  enable = true;
 +
  openFirewall = true;
 +
};
 +
 +
networking.firewall.enable = true;
 +
networking.firewall.allowPing = true;
 +
</nowiki>}}
 +
 +
The <code>samba-wsdd</code> service is used to advertise the shares to Windows hosts.
 +
 +
=== User Authentication ===
 +
 +
For a user called <code>my_user</code>to be authenticated on the samba server, you must add their password using
 +
 +
<syntaxhighlight lang="bash">
 +
smbpasswd -a my_user
 +
</syntaxhighlight>
 +
 +
=== Configuration ===
 +
 +
==== Apple Time Machine ====
 +
 +
Example configuration:
 +
 +
<syntaxhighlight lang="nix">
 +
services.samba = {
 +
  shares = {
 +
    tm_share = {
 +
        path = "/mnt/Shares/tm_share";
 +
        "valid users" = "username";
 +
        public = "no";
 +
        writeable = "yes";
 +
        "force user" = "username";
 +
        "fruit:aapl" = "yes";
 +
        "fruit:time machine" = "yes";
 +
        "vfs objects" = "catia fruit streams_xattr";
 +
    };
 +
  };
 +
}
 +
</syntaxhighlight>
 +
 +
==== Printer sharing ====
 +
 +
<syntaxhighlight lang=nix>
 +
services.samba.package = pkgs.sambaFull;
 +
</syntaxhighlight>
 +
 +
A printer share that allows printing to all members in the local network
 +
 +
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 +
services.samba = {
 +
  enable = true;
 +
  package = pkgs.sambaFull;
 +
  openFirewall = true;
 +
  extraConfig = ''
 +
    load printers = yes
 +
    printing = cups
 +
    printcap name = cups
 +
  '';
 +
  shares = {
 +
    printers = {
 +
      comment = "All Printers";
 +
      path = "/var/spool/samba";
 +
      public = "yes";
 +
      browseable = "yes";
 +
      # to allow user 'guest account' to print.
 +
      "guest ok" = "yes";
 +
      writable = "no";
 +
      printable = "yes";
 +
      "create mode" = 0700;
 +
    };
 +
  };
 +
};
 +
systemd.tmpfiles.rules = [
 +
  "d /var/spool/samba 1777 root root -"
 +
];
 +
</nowiki>}}
 +
 +
The `samba` packages comes without [[Printing|CUPS printing]] support compiled in, however `sambaFull` features printer sharing support.
 +
 +
==== Active Directory Domain Controller ====
 +
 +
We will setup an AD DC just like the the [https://wiki.samba.org/index.php/Setting_up_Samba_as_an_Active_Directory_Domain_Controller Samba Wiki].
 +
Let's add the following nix config, updating the <code>adDomain</code>, <code>adWorkgroup</code>, <code>adNetbiosName</code> and <code>staticIp</code> according to your needs.
 +
 +
<syntaxhighlight lang=nix>
 +
{ config, lib, pkgs, ... }:
 +
with lib;
 +
 +
let
 +
  cfg = config.services.samba;
 +
  samba = cfg.package;
 +
  nssModulesPath = config.system.nssModules.path;
 +
  adDomain = "samdom.example.com";
 +
  adWorkgroup = "SAM";
 +
  adNetbiosName = "SAMDOM";
 +
  staticIp = "10.42.129.160";
 +
in {
 +
  # Disable resolveconf, we're using Samba internal DNS backend
 +
  systemd.services.resolvconf.enable = false;
 +
  environment.etc = {
 +
    resolvconf = {
 +
      text = ''
 +
        search ${adDomain}
 +
        nameserver ${staticIp}
 +
      '';
 +
    };
 +
  };
 +
 +
  # Rebuild Samba with LDAP, MDNS and Domain Controller support
 +
  nixpkgs.overlays = [ (self: super: {
 +
    samba = (super.samba.override {
 +
      enableLDAP = true;
 +
      enableMDNS = true;
 +
      enableDomainController = true;
 +
      enableProfiling = true; # Optional for logging
 +
      # Set pythonpath manually (bellow with overrideAttrs) as it is not set on 22.11 due to bug
 +
    }).overrideAttrs (finalAttrs: previousAttrs: {
 +
        pythonPath = with super; [ python3Packages.dnspython tdb ldb talloc ];
 +
      });
 +
  })];
 +
 +
  # Disable default Samba `smbd` service, we will be using the `samba` server binary
 +
  systemd.services.samba-smbd.enable = false; 
 +
  systemd.services.samba = {
 +
    description = "Samba Service Daemon";
 +
 +
    requiredBy = [ "samba.target" ];
 +
    partOf = [ "samba.target" ];
 +
 +
    serviceConfig = {
 +
      ExecStart = "${samba}/sbin/samba --foreground --no-process-group";
 +
      ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
 +
      LimitNOFILE = 16384;
 +
      PIDFile = "/run/samba.pid";
 +
      Type = "notify";
 +
      NotifyAccess = "all"; #may not do anything...
 +
    };
 +
    unitConfig.RequiresMountsFor = "/var/lib/samba";
 +
  };
 +
  services.samba = {
 +
    enable = true;
 +
    enableNmbd = false;
 +
    enableWinbindd = false;
 +
    configText = ''
 +
      # Global parameters
 +
      [global]
 +
          dns forwarder = ${staticIp}
 +
          netbios name = ${adNetbiosName}
 +
          realm = ${toUpper adDomain}
 +
          server role = active directory domain controller
 +
          workgroup = ${adWorkgroup}
 +
          idmap_ldb:use rfc2307 = yes
 +
 +
      [sysvol]
 +
          path = /var/lib/samba/sysvol
 +
          read only = No
 +
 +
      [netlogon]
 +
          path = /var/lib/samba/sysvol/${adDomain}/scripts
 +
          read only = No
 +
    '';
 +
  }; 
 +
}
 +
</syntaxhighlight>
 +
 +
{{Evaluate}}
 +
 +
After evaluating, you should see that the Samba service crashed because we haven't setup the database yet.
 +
 +
To do that, let's run the following command, updated with your own configuration:
 +
 +
<code>
 +
samba-tool domain provision --server-role=dc --use-rfc2307 --dns-backend=SAMBA_INTERNAL --realm=SAMDOM.EXAMPLE.COM --domain=SAMDOM --adminpass=Passw0rd
 +
</code>
 +
 +
Then restart the samba service with <code>sudo systemctl restart samba</code>, and you're ready to go!
  
 
== Samba Client ==
 
== Samba Client ==
=== cifs mount ===
+
 
 +
=== CIFS mount configuration ===
  
 
The following snippets shows how to mount a CIFS (Windows) share in NixOS.
 
The following snippets shows how to mount a CIFS (Windows) share in NixOS.
Line 9: Line 235:
 
<syntaxhighlight lang="nix">
 
<syntaxhighlight lang="nix">
 
{
 
{
 +
  # For mount.cifs, required unless domain name resolution is not needed.
 +
  environment.systemPackages = [ pkgs.cifs-utils ];
 
   fileSystems."/mnt/share" = {
 
   fileSystems."/mnt/share" = {
      device = "//<IP_OR_HOST>/path/to/share";
+
    device = "//<IP_OR_HOST>/path/to/share";
      fsType = "cifs";
+
    fsType = "cifs";
      options = let
+
    options = let
        # this line prevents hanging on network split
+
      # this line prevents hanging on network split
        automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
+
      automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
  
      in ["${automount_opts},credentials=/etc/nixos/smb-secrets"];
+
    in ["${automount_opts},credentials=/etc/nixos/smb-secrets"];
 
   };
 
   };
 
}
 
}
Line 29: Line 257:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Firewall ==
+
By default, CIFS shares are mounted as root. If mounting as user is desirable, `uid`, `gid` and usergroup arguments can be provided as part of the filesystem options:
 +
<syntaxhighlight lang="nix">
 +
{
 +
  fileSystems."/mnt/share" = {
 +
    # ... rest of the filesystem config omitted
 +
    options = let
 +
      automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s,user,users";
 +
 
 +
      in ["${automount_opts},credentials=/etc/nixos/smb-secrets,uid=1000,gid=100"];
 +
    # or if you have specified `uid` and `gid` explicitly through NixOS configuration,
 +
    # you can refer to them rather than hard-coding the values:
 +
    # in ["${automount_opts},credentials=/etc/nixos/smb-secrets,${config.users.users.<username>.uid},gid=${config.users.groups.<group>.gid}"];
 +
  };
 +
}
 +
</syntaxhighlight>
 +
 
 +
=== Firewall configuration ===
 +
 
 
Samba discovery of machines and shares may need the firewall to be tuned ([https://wiki.archlinux.org/index.php/Samba#.22Browsing.22_network_fails_with_.22Failed_to_retrieve_share_list_from_server.22 source]):
 
Samba discovery of machines and shares may need the firewall to be tuned ([https://wiki.archlinux.org/index.php/Samba#.22Browsing.22_network_fails_with_.22Failed_to_retrieve_share_list_from_server.22 source]):
 
in <code>/etc/nixos/configuration.nix</code>, add:
 
in <code>/etc/nixos/configuration.nix</code>, add:
 
<syntaxhighlight lang="nix">
 
<syntaxhighlight lang="nix">
networking.firewall.extraCommands = ''iptables -t raw -A OUTPUT -p udp -m udp --dport 137 -j CT --helper netbios-ns";
+
networking.firewall.extraCommands = ''iptables -t raw -A OUTPUT -p udp -m udp --dport 137 -j CT --helper netbios-ns'';
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Browsing samba shares with GVFS ==
+
=== Command line ===
 +
 
 +
List shares
 +
 
 +
<pre>
 +
smbclient --list localhost
 +
</pre>
 +
 
 +
This should print
 +
 
 +
<pre>
 +
$ smbclient --list localhost
 +
Password for [WORKGROUP\user]:
 +
 
 +
Sharename      Type      Comment
 +
---------      ----      -------
 +
public          Disk     
 +
IPC$            IPC      IPC Service (smbnix)
 +
SMB1 disabled -- no workgroup available
 +
</pre>
 +
 
 +
Mount as guest. <code>public</code> is your share name
 +
 
 +
<pre>
 +
nix-shell -p cifs-utils
 +
mkdir mnt
 +
sudo mount.cifs -o sec=none //localhost/public mnt
 +
</pre>
 +
 
 +
mount as user. <code>user</code> is your username
 +
 
 +
<pre>
 +
sudo mount.cifs -o sec=ntlmssp,username=user //localhost/public mnt
 +
</pre>
 +
 
 +
<code>sec=ntlmssp</code> should work.
 +
for more values, see `man mount.cifs` (search for `sec=arg`)
 +
 
 +
=== Browsing samba shares with GVFS ===
 +
 
 
Many GTK-based file managers like Nautilus, Thunar, and PCManFM can browse samba shares thanks to GVFS.
 
Many GTK-based file managers like Nautilus, Thunar, and PCManFM can browse samba shares thanks to GVFS.
 
GVFS is a dbus daemon which must be running for this to work.
 
GVFS is a dbus daemon which must be running for this to work.
Line 47: Line 331:
  
 
There are however some special cases.
 
There are however some special cases.
 +
 
===== XFCE =====
 
===== XFCE =====
 +
 
[[Xfce]] comes with a slimmed-down version of GVFS by default which comes with samba support compiled out. To have smb:// support in Thunar, we will use GNOME's full-featured version of GVFS:
 
[[Xfce]] comes with a slimmed-down version of GVFS by default which comes with samba support compiled out. To have smb:// support in Thunar, we will use GNOME's full-featured version of GVFS:
 
<syntaxhighlight lang="nix">
 
<syntaxhighlight lang="nix">
Line 55: Line 341:
 
   };
 
   };
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
===== No desktop environment =====
 
===== No desktop environment =====
 +
 
GVFS relies on polkit to gain privileges for some operations. Polkit needs an authentication agent to ask for credentials.
 
GVFS relies on polkit to gain privileges for some operations. Polkit needs an authentication agent to ask for credentials.
 
Desktop environments usually provide one but if you have no desktop environment, you may have to install one yourself:
 
Desktop environments usually provide one but if you have no desktop environment, you may have to install one yourself:
Line 64: Line 352:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
===== DBUS =====
  
===== DBUS =====
 
 
Furthermore, if you happen to start your Window Manager directly, via <code>.xinitrc</code>, or directly invoke a Wayland compositor such as Sway, you should ensure that you launch dbus at startup in your session and export its environment. If you do not have a dbus session in your environment, you will see errors such as "Operation not supported" when attempting to browse the network.
 
Furthermore, if you happen to start your Window Manager directly, via <code>.xinitrc</code>, or directly invoke a Wayland compositor such as Sway, you should ensure that you launch dbus at startup in your session and export its environment. If you do not have a dbus session in your environment, you will see errors such as "Operation not supported" when attempting to browse the network.
  
Line 82: Line 370:
 
(Because <code>dbus-run-session</code> exits when the child process exits, it is only appropriate to use <code>dbus-run-session</code> with a process that will be running during the entire session. This is the case for Wayland compositors, but is not necessarily true for all configurations of X11 window managers.)
 
(Because <code>dbus-run-session</code> exits when the child process exits, it is only appropriate to use <code>dbus-run-session</code> with a process that will be running during the entire session. This is the case for Wayland compositors, but is not necessarily true for all configurations of X11 window managers.)
  
== Samba Server ==
+
== Troubleshooting ==
=== excerpt of /etc/nixos/configuration.nix ===
 
  
<syntaxhighlight lang="nix">
+
=== Server log ===
services.samba = {
 
  enable = true;
 
  securityType = "user";
 
  extraConfig = ''
 
    workgroup = WORKGROUP
 
    server string = smbnix
 
    netbios name = smbnix
 
    security = user
 
    #use sendfile = yes
 
    #max protocol = smb2
 
    hosts allow = 192.168.0  localhost
 
    hosts deny = 0.0.0.0/0
 
    guest account = nobody
 
    map to guest = bad user
 
  '';
 
  shares = {
 
    public = {
 
      path = "/mnt/Shares/Public";
 
      browseable = "yes";
 
      "read only" = "no";
 
      "guest ok" = "yes";
 
      "create mask" = "0644";
 
      "directory mask" = "0755";
 
      "force user" = "username";
 
      "force group" = "groupname";
 
    };
 
    private = {
 
      path = "/mnt/Shares/Private";
 
      browseable = "yes";
 
      "read only" = "no";
 
      "guest ok" = "no";
 
      "create mask" = "0644";
 
      "directory mask" = "0755";
 
      "force user" = "username";
 
      "force group" = "groupname";
 
    };
 
  };
 
};
 
</syntaxhighlight>
 
  
If your firewall is enabled, or if you consider enabling it:
+
<pre>
<syntaxhighlight lang="nix">
+
sudo journalctl -u samba-smbd.service -f
networking.firewall.enable = true;
+
</pre>
networking.firewall.allowPing = true;
 
networking.firewall.allowedTCPPorts = [ 445 139 ];
 
networking.firewall.allowedUDPPorts = [ 137 138 ];
 
</syntaxhighlight>
 
  
{{Evaluate}}
+
=== Stale file handle ===
  
Samba should startup afterwards.
+
Trying to read the contents of a remote file leads to the following error message: "Stale file handle". If you have mounted a share via the method described in "cfis mount", adding the option <code>noserverino</code> might fix this problem. [https://askubuntu.com/questions/1265164/stale-file-handler-when-mounting-cifs-smb-network-drive-from-fritz-router]
  
If you plan to access a share as a user on the server, you'll need to run <code>smbpasswd -a <user></code> as root to set the password.
+
=== NT_STATUS_INVALID_NETWORK_RESPONSE ===
  
=== stopping/restarting the services ===
+
The error
<syntaxhighlight lang="console">
+
<code>protocol negotiation failed: NT_STATUS_INVALID_NETWORK_RESPONSE</code>
# systemctl stop samba
+
means "access denied".
# systemctl start samba
+
Probably you must fix your server's <code>hosts allow</code> section.
# systemctl restart samba
+
Note that <code>localhost</code> is the ipv6 localhost <code>::1</code>,
</syntaxhighlight>
+
and <code>127.0.0.1</code> is the ipv4 localhost
  
=== Use Cases ===
+
=== Permission denied ===
==== Apple Time Machine ====
 
nixpkgs includes Samba4.8-git, which adds support for using shares for Time Machine backups on macOS 10.12+.
 
Example configuration:
 
<syntaxhighlight lang="nix">
 
services.samba = {
 
  package = pkgs.sambaMaster;
 
  shares = {
 
    tm_share = {
 
        path = "/mnt/Shares/tm_share";
 
        "valid users" = "username";
 
        public = "no";
 
        writeable = "yes";
 
        "force user" = "username";
 
        "fruit:aapl" = "yes";
 
        "fruit:time machine" = "yes";
 
        "vfs objects" = "catia fruit streams_xattr";
 
    };
 
  };
 
}
 
</syntaxhighlight>
 
  
==== Printer sharing ====
+
Maybe check the <code>guest account</code> setting in your server config.
 +
The default value is <code>nobody</code>,
 +
but the user <code>nobody</code> has no access to <code>/home/user</code>:
  
The `samba` packages comes without cups support compiled in, however `sambaFull` features printer sharing support.
+
<pre>
To use it set the `services.samba.package` option:
+
$ sudo -u nobody ls /home/user
 +
[sudo] password for user:  
 +
ls: cannot open directory '/home/user': Permission denied
 +
</pre>
  
<syntaxhighlight lang=nix>
+
As workaround, set <code>guest account = user</code>,
services.samba.package = pkgs.sambaFull;
+
where <code>user</code> is your username
</syntaxhighlight>
 
  
A printer share that allows all members in the local network printing could look like this:
+
== See also ==
 
 
<syntaxhighlight lang=nix>
 
{ pkgs, ... }: {
 
  services.samba = {
 
    enable = true;
 
    package = pkgs.sambaFull;
 
    extraConfig = ''
 
      load printers = yes
 
      printing = cups
 
      printcap name = cups
 
    '';
 
    shares = {
 
      printers = {
 
        comment = "All Printers";
 
        path = "/var/spool/samba";
 
        public = "yes";
 
        browseable = "yes";
 
        # to allow user 'guest account' to print.
 
        "guest ok" = "yes";
 
        writable = "no";
 
        printable = "yes";
 
        "create mode" = 0700;
 
      };
 
  };
 
  systemd.tmpfiles.rules = [
 
    "d /var/spool/samba 1777 root root -"
 
  ];
 
}
 
</syntaxhighlight>
 
  
== links ==
+
* [https://search.nixos.org/options?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=services.samba Samba Options in NixOS on unstable]
* [https://search.nixos.org/options/?query=services.samba Samba Options in NixOS]
+
* [https://wiki.archlinux.org/title/Samba Samba in the Arch Linux Wiki]
  
 
[[Category:Services]]
 
[[Category:Services]]

Latest revision as of 10:53, 6 April 2024

This guide will help you on how to use samba on nixos.

Server setup

Example setup for creating a public guest share called public and a private share called private.

Breeze-text-x-plain.png
/etc/nixos/configuration.nix
services.samba = {
  enable = true;
  securityType = "user";
  openFirewall = true;
  extraConfig = ''
    workgroup = WORKGROUP
    server string = smbnix
    netbios name = smbnix
    security = user 
    #use sendfile = yes
    #max protocol = smb2
    # note: localhost is the ipv6 localhost ::1
    hosts allow = 192.168.0. 127.0.0.1 localhost
    hosts deny = 0.0.0.0/0
    guest account = nobody
    map to guest = bad user
  '';
  shares = {
    public = {
      path = "/mnt/Shares/Public";
      browseable = "yes";
      "read only" = "no";
      "guest ok" = "yes";
      "create mask" = "0644";
      "directory mask" = "0755";
      "force user" = "username";
      "force group" = "groupname";
    };
    private = {
      path = "/mnt/Shares/Private";
      browseable = "yes";
      "read only" = "no";
      "guest ok" = "no";
      "create mask" = "0644";
      "directory mask" = "0755";
      "force user" = "username";
      "force group" = "groupname";
    };
  };
};

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

networking.firewall.enable = true;
networking.firewall.allowPing = true;


The samba-wsdd service is used to advertise the shares to Windows hosts.

User Authentication

For a user called my_userto be authenticated on the samba server, you must add their password using

smbpasswd -a my_user

Configuration

Apple Time Machine

Example configuration:

services.samba = {
  shares = {
    tm_share = {
        path = "/mnt/Shares/tm_share";
        "valid users" = "username";
        public = "no";
        writeable = "yes";
        "force user" = "username";
        "fruit:aapl" = "yes";
        "fruit:time machine" = "yes";
        "vfs objects" = "catia fruit streams_xattr";
    };
  };
}

Printer sharing

services.samba.package = pkgs.sambaFull;

A printer share that allows printing to all members in the local network

Breeze-text-x-plain.png
/etc/nixos/configuration.nix
services.samba = {
  enable = true;
  package = pkgs.sambaFull;
  openFirewall = true;
  extraConfig = ''
    load printers = yes
    printing = cups
    printcap name = cups
  '';
  shares = {
    printers = {
      comment = "All Printers";
      path = "/var/spool/samba";
      public = "yes";
      browseable = "yes";
      # to allow user 'guest account' to print.
      "guest ok" = "yes";
      writable = "no";
      printable = "yes";
      "create mode" = 0700;
    };
  };
};
systemd.tmpfiles.rules = [
  "d /var/spool/samba 1777 root root -"
];


The `samba` packages comes without CUPS printing support compiled in, however `sambaFull` features printer sharing support.

Active Directory Domain Controller

We will setup an AD DC just like the the Samba Wiki. Let's add the following nix config, updating the adDomain, adWorkgroup, adNetbiosName and staticIp according to your needs.

{ config, lib, pkgs, ... }:
with lib;

let
  cfg = config.services.samba;
  samba = cfg.package;
  nssModulesPath = config.system.nssModules.path;
  adDomain = "samdom.example.com";
  adWorkgroup = "SAM";
  adNetbiosName = "SAMDOM";
  staticIp = "10.42.129.160";
in {
  # Disable resolveconf, we're using Samba internal DNS backend
  systemd.services.resolvconf.enable = false;
  environment.etc = {
    resolvconf = {
      text = ''
        search ${adDomain}
        nameserver ${staticIp}
      '';
    };
  };

  # Rebuild Samba with LDAP, MDNS and Domain Controller support
  nixpkgs.overlays = [ (self: super: {
    samba = (super.samba.override {
      enableLDAP = true;
      enableMDNS = true;
      enableDomainController = true;
      enableProfiling = true; # Optional for logging
       # Set pythonpath manually (bellow with overrideAttrs) as it is not set on 22.11 due to bug
    }).overrideAttrs (finalAttrs: previousAttrs: {
        pythonPath = with super; [ python3Packages.dnspython tdb ldb talloc ];
      });
  })];

  # Disable default Samba `smbd` service, we will be using the `samba` server binary
  systemd.services.samba-smbd.enable = false;  
  systemd.services.samba = {
    description = "Samba Service Daemon";

    requiredBy = [ "samba.target" ];
    partOf = [ "samba.target" ];

    serviceConfig = {
      ExecStart = "${samba}/sbin/samba --foreground --no-process-group";
      ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
      LimitNOFILE = 16384;
      PIDFile = "/run/samba.pid";
      Type = "notify";
      NotifyAccess = "all"; #may not do anything...
    };
    unitConfig.RequiresMountsFor = "/var/lib/samba";
  };
  services.samba = {
    enable = true;
    enableNmbd = false;
    enableWinbindd = false;
    configText = ''
      # Global parameters
      [global]
          dns forwarder = ${staticIp}
          netbios name = ${adNetbiosName}
          realm = ${toUpper adDomain}
          server role = active directory domain controller
          workgroup = ${adWorkgroup}
          idmap_ldb:use rfc2307 = yes

      [sysvol]
          path = /var/lib/samba/sysvol
          read only = No

      [netlogon]
          path = /var/lib/samba/sysvol/${adDomain}/scripts
          read only = No
    '';
  };  
}

After evaluating, you should see that the Samba service crashed because we haven't setup the database yet.

To do that, let's run the following command, updated with your own configuration:

samba-tool domain provision --server-role=dc --use-rfc2307 --dns-backend=SAMBA_INTERNAL --realm=SAMDOM.EXAMPLE.COM --domain=SAMDOM --adminpass=Passw0rd

Then restart the samba service with sudo systemctl restart samba, and you're ready to go!

Samba Client

CIFS mount configuration

The following snippets shows how to mount a CIFS (Windows) share in NixOS. Replace all <FIELDS> with concrete values:

{
  # For mount.cifs, required unless domain name resolution is not needed.
  environment.systemPackages = [ pkgs.cifs-utils ];
  fileSystems."/mnt/share" = {
    device = "//<IP_OR_HOST>/path/to/share";
    fsType = "cifs";
    options = let
      # this line prevents hanging on network split
      automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";

    in ["${automount_opts},credentials=/etc/nixos/smb-secrets"];
  };
}

Also create /etc/nixos/smb-secrets with the following content (domain= can be optional)

username=<USERNAME>
domain=<DOMAIN>
password=<PASSWORD>

By default, CIFS shares are mounted as root. If mounting as user is desirable, `uid`, `gid` and usergroup arguments can be provided as part of the filesystem options:

{
  fileSystems."/mnt/share" = {
    # ... rest of the filesystem config omitted
    options = let
      automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s,user,users";

      in ["${automount_opts},credentials=/etc/nixos/smb-secrets,uid=1000,gid=100"];
    # or if you have specified `uid` and `gid` explicitly through NixOS configuration,
    # you can refer to them rather than hard-coding the values:
    # in ["${automount_opts},credentials=/etc/nixos/smb-secrets,${config.users.users.<username>.uid},gid=${config.users.groups.<group>.gid}"];
  };
}

Firewall configuration

Samba discovery of machines and shares may need the firewall to be tuned (source): in /etc/nixos/configuration.nix, add:

networking.firewall.extraCommands = ''iptables -t raw -A OUTPUT -p udp -m udp --dport 137 -j CT --helper netbios-ns'';

Command line

List shares

smbclient --list localhost

This should print

$ smbclient --list localhost 
Password for [WORKGROUP\user]:

	Sharename       Type      Comment
	---------       ----      -------
	public          Disk      
	IPC$            IPC       IPC Service (smbnix)
SMB1 disabled -- no workgroup available

Mount as guest. public is your share name

nix-shell -p cifs-utils
mkdir mnt
sudo mount.cifs -o sec=none //localhost/public mnt

mount as user. user is your username

sudo mount.cifs -o sec=ntlmssp,username=user //localhost/public mnt

sec=ntlmssp should work. for more values, see `man mount.cifs` (search for `sec=arg`)

Browsing samba shares with GVFS

Many GTK-based file managers like Nautilus, Thunar, and PCManFM can browse samba shares thanks to GVFS. GVFS is a dbus daemon which must be running for this to work. If you use Gnome, you have nothing to do as the module already enables it for you, but in less full-featured desktop environments, some further configuration options are needed.

The generic way of enabling GVFS is to add this in /etc/nixos/configuration.nix:

services.gvfs.enable = true;

There are however some special cases.

XFCE

Xfce comes with a slimmed-down version of GVFS by default which comes with samba support compiled out. To have smb:// support in Thunar, we will use GNOME's full-featured version of GVFS:

  services.gvfs = {
    enable = true;
    package = lib.mkForce pkgs.gnome3.gvfs;
  };
No desktop environment

GVFS relies on polkit to gain privileges for some operations. Polkit needs an authentication agent to ask for credentials. Desktop environments usually provide one but if you have no desktop environment, you may have to install one yourself:

Excerpt of /etc/nixos/configuration.nix:

environment.systemPackages = with pkgs; [ lxqt.lxqt-policykit ]; # provides a default authentification client for policykit
DBUS

Furthermore, if you happen to start your Window Manager directly, via .xinitrc, or directly invoke a Wayland compositor such as Sway, you should ensure that you launch dbus at startup in your session and export its environment. If you do not have a dbus session in your environment, you will see errors such as "Operation not supported" when attempting to browse the network.

For example, if you are using .xinitrc, you could invoke dbus-launch:

export `dbus-launch` # starts dbus and exports its address
exec xterm # your prefered Window Manager

(You need to restart your Window Manager to have the changes in .xinitrc to take place.)

If you are using a Wayland compositor like Sway, you can run it under dbus-run-session for the same effect:

dbus-run-session sway

(Because dbus-run-session exits when the child process exits, it is only appropriate to use dbus-run-session with a process that will be running during the entire session. This is the case for Wayland compositors, but is not necessarily true for all configurations of X11 window managers.)

Troubleshooting

Server log

sudo journalctl -u samba-smbd.service -f

Stale file handle

Trying to read the contents of a remote file leads to the following error message: "Stale file handle". If you have mounted a share via the method described in "cfis mount", adding the option noserverino might fix this problem. [1]

NT_STATUS_INVALID_NETWORK_RESPONSE

The error protocol negotiation failed: NT_STATUS_INVALID_NETWORK_RESPONSE means "access denied". Probably you must fix your server's hosts allow section. Note that localhost is the ipv6 localhost ::1, and 127.0.0.1 is the ipv4 localhost

Permission denied

Maybe check the guest account setting in your server config. The default value is nobody, but the user nobody has no access to /home/user:

$ sudo -u nobody ls /home/user
[sudo] password for user: 
ls: cannot open directory '/home/user': Permission denied

As workaround, set guest account = user, where user is your username

See also