Samba: Difference between revisions

From NixOS Wiki
imported>Maximeborges
Add Samba4 AC DC configuration steps
imported>Maximeborges
Fix AD DC instructions
Line 209: Line 209:
==== Active Directory Domain Controller ====
==== Active Directory Domain Controller ====


To set up an AD DC on your installation, first start with a disabled installation of Samba, so we have all the tools to setup the configuration:
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>
<syntaxhighlight lang=nix>
{
{ config, lib, pkgs, ... }:
  services.samba = { enable = false; };
with lib;
}
</syntaxhighlight>
 
{{Evaluate}}
 
Then follow the configuration steps from https://wiki.samba.org/index.php/Setting_up_Samba_as_an_Active_Directory_Domain_Controller
 
If everything works properly, we will now update the previous nix config. Replace it with the following, and update the <code>services.samba.configText</code> field with the content of your freshly set up <code>/etc/samba/smb.conf</code>:
 
<syntaxhighlight lang=nix>
{ config, pkgs, ... }:


let
let
Line 230: Line 220:
   samba = cfg.package;
   samba = cfg.package;
   nssModulesPath = config.system.nssModules.path;
   nssModulesPath = config.system.nssModules.path;
  adDomain = 'samdom.example.com';
  adWorkgroup = 'SAM';
  adNetbiosName = 'SAMDOM';
  staticIp = '10.42.129.160';
in {
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;
    };
  } ) ];
  # Disable default Samba `smbd` service, we will be using the `samba` server binary
   systemd.services.samba-smbd.enable = false;   
   systemd.services.samba-smbd.enable = false;   
   systemd.services.samba = {
   systemd.services.samba = {
Line 248: Line 263:
     unitConfig.RequiresMountsFor = "/var/lib/samba";
     unitConfig.RequiresMountsFor = "/var/lib/samba";
   };
   };
  nixpkgs.overlays = [ (self: super: {
    samba = super.samba.override {
      enableLDAP = true;
      enableMDNS = true;
      enableDomainController = true;
    };
  } ) ];
   services.samba = {
   services.samba = {
     enable = true;
     enable = true;
Line 262: Line 270:
       # Global parameters
       # Global parameters
       [global]
       [global]
           dns forwarder = 10.99.0.1
           dns forwarder = ${staticIp}
           netbios name = SAMDOM
           netbios name = ${adNetbiosName}
           realm = SAMDOM.EXAMPLE.COM
           realm = ${toUpper adDomain}
           server role = active directory domain controller
           server role = active directory domain controller
           workgroup = SAM
           workgroup = ${adWorkgroup}
           idmap_ldb:use rfc2307 = yes
           idmap_ldb:use rfc2307 = yes


Line 274: Line 282:


       [netlogon]
       [netlogon]
           path = /var/lib/samba/sysvol/samdom.example.com/scripts
           path = /var/lib/samba/sysvol/${adDomain}/scripts
           read only = No
           read only = No
     '';
     '';
   };
   };
}
}
</syntaxhighlight>
</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!


==Troubleshooting==
==Troubleshooting==

Revision as of 18:13, 17 October 2021

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

Samba Client

cifs mount

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

{
  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>

Firewall

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'';

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.)

Samba Server

excerpt of /etc/nixos/configuration.nix

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";
    };
  };
};

If your firewall is enabled, or if you consider enabling it:

networking.firewall.enable = true;
networking.firewall.allowPing = true;
networking.firewall.allowedTCPPorts = [ 445 139 ];
networking.firewall.allowedUDPPorts = [ 137 138 ];

Samba should startup afterwards.

If you plan to access a share as a user on the server, you'll need to run smbpasswd -a <user> as root to set the password.

stopping/restarting the services

# systemctl stop samba
# systemctl start samba
# systemctl restart samba

Use Cases

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

The `samba` packages comes without cups support compiled in, however `sambaFull` features printer sharing support. To use it set the `services.samba.package` option:

services.samba.package = pkgs.sambaFull;

A printer share that allows all members in the local network printing could look like this:

{ 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 -"
  ];
}

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;
    };
  } ) ];

  # 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!

Troubleshooting

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]

links