Samba: Difference between revisions

imported>Onny
mNo edit summary
User Authentication: add robust automated authentication example that provides full context and aims to give a basic, typical password-protected folder share
(14 intermediate revisions by 11 users not shown)
Line 8: Line 8:
services.samba = {
services.samba = {
   enable = true;
   enable = true;
  securityType = "user";
   openFirewall = true;
   openFirewall = true;
   extraConfig = ''
   settings = {
     workgroup = WORKGROUP
     global = {
    server string = smbnix
      "workgroup" = "WORKGROUP";
    netbios name = smbnix
      "server string" = "smbnix";
    security = user  
      "netbios name" = "smbnix";
    #use sendfile = yes
      "security" = "user";
    #max protocol = smb2
      #"use sendfile" = "yes";
    # note: localhost is the ipv6 localhost ::1
      #"max protocol" = "smb2";
    hosts allow = 192.168.0. 127.0.0.1 localhost
      # note: localhost is the ipv6 localhost ::1
    hosts deny = 0.0.0.0/0
      "hosts allow" = "192.168.0. 127.0.0.1 localhost";
    guest account = nobody
      "hosts deny" = "0.0.0.0/0";
    map to guest = bad user
      "guest account" = "nobody";
  '';
      "map to guest" = "bad user";
  shares = {
    };
     public = {
     "public" = {
       path = "/mnt/Shares/Public";
       "path" = "/mnt/Shares/Public";
       browseable = "yes";
       "browseable" = "yes";
       "read only" = "no";
       "read only" = "no";
       "guest ok" = "yes";
       "guest ok" = "yes";
Line 34: Line 33:
       "force group" = "groupname";
       "force group" = "groupname";
     };
     };
     private = {
     "private" = {
       path = "/mnt/Shares/Private";
       "path" = "/mnt/Shares/Private";
       browseable = "yes";
       "browseable" = "yes";
       "read only" = "no";
       "read only" = "no";
       "guest ok" = "no";
       "guest ok" = "no";
Line 48: Line 47:


services.samba-wsdd = {
services.samba-wsdd = {
  enable = true;
  openFirewall = true;
};
services.avahi = {
  publish.enable = true;
  publish.userServices = true;
  # ^^ Needed to allow samba to automatically register mDNS records (without the need for an `extraServiceFile`
  nssmdns4 = true;
  # ^^ Not one hundred percent sure if this is needed- if it aint broke, don't fix it
   enable = true;
   enable = true;
   openFirewall = true;
   openFirewall = true;
Line 56: Line 65:
</nowiki>}}
</nowiki>}}


The <code>samba-wsdd</code> service is used to advertise the shares to Windows hosts.
The <code>samba-wsdd</code> service and avahi is used to advertise the shares to Windows hosts.


=== User Authentication ===
=== User Authentication ===


For a user called <code>my_user</code>to be authenticated on the samba server, you must add their password using
For a user called <code>my_user</code>to be authenticated on the samba server, you can add a password using:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
smbpasswd -a my_user
sudo smbpasswd -a my_user
</syntaxhighlight>
</syntaxhighlight>
To automate creation of the samba user and the required system user, you can use [https://search.nixos.org/options?show=system.activationScripts system.activationScripts]:
<syntaxhighlight lang="nix">
{
  # Make the samba user "my_user" on the system
  users.users.my_user = {
    description = "Write-access to samba media shares";
    # Add this user to a group with permission to access the expected files
    extraGroups = [ "users" ];
    # Password can be set in clear text with a literal string or from a file.
    # Using sops-nix we can use the same file so that the system user and samba
    # user share the same credential (if desired).
    hashedPasswordFile = config.sops.secrets.samba.path;
    isNormalUser = true;
  };
  # Set "my_user" as a valid samba login
  services.samba = {
    enable = true;
    securityType = "user";
    openFirewall = true;
    settings.my_share_directory = {
      # ...
      "valid users" = "my_user";
    };
  };
  # Activation scripts run every time nixos switches build profiles. So if you're
  # pulling the user/samba password from a file then it will be updated during
  # nixos-rebuild. Again, in this example we're using sops-nix with a "samba" entry
  # to avoid cleartext password, but this could be replaced with a static path.
  system.activationScripts = {
    # The "init_smbpasswd" script name is arbitrary, but a useful label for tracking
    # failed scripts in the build output. An absolute path to smbpasswd is necessary
    # as it is not in $PATH in the activation script's environment. The password
    # is repeated twice with newline characters as smbpasswd requires a password
    # confirmation even in non-interactive mode where input is piped in through stdin.
    init_smbpasswd.text = ''
      /run/current-system/sw/bin/printf "$(/run/current-system/sw/bin/cat ${config.sops.secrets.samba.path})\n$(/run/current-system/sw/bin/cat ${config.sops.secrets.samba.path})\n" | /run/current-system/sw/bin/smbpasswd -sa my_user
    '';
  };
}
</syntaxhighlight>


=== Configuration ===
=== Configuration ===
Line 70: Line 124:
==== Apple Time Machine ====
==== Apple Time Machine ====


Example configuration:
In addition to the example above, add this to your configuration:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
services.samba = {
services.samba = {
   shares = {
   settings = {
     tm_share = {
     "tm_share" = {
         path = "/mnt/Shares/tm_share";
         "path" = "/mnt/Shares/tm_share";
         "valid users" = "username";
         "valid users" = "username";
         public = "no";
         "public" = "no";
         writeable = "yes";
         "writeable" = "yes";
         "force user" = "username";
         "force user" = "username";
        # Below are the most imporant for macOS compatibility
        # Change the above to suit your needs
         "fruit:aapl" = "yes";
         "fruit:aapl" = "yes";
         "fruit:time machine" = "yes";
         "fruit:time machine" = "yes";
Line 86: Line 142:
     };
     };
   };
   };
}
};
 
# Ensure Time Machine can discover the share without `tmutil`
services.avahi = {
  extraServiceFiles = {
    timemachine = ''
      <?xml version="1.0" standalone='no'?>
      <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
      <service-group>
        <name replace-wildcards="yes">%h</name>
        <service>
          <type>_smb._tcp</type>
          <port>445</port>
        </service>
          <service>
          <type>_device-info._tcp</type>
          <port>0</port>
          <txt-record>model=TimeCapsule8,119</txt-record>
        </service>
        <service>
          <type>_adisk._tcp</type>
          <!--
            change tm_share to share name, if you changed it.
          -->
          <txt-record>dk0=adVN=tm_share,adVF=0x82</txt-record>
          <txt-record>sys=waMa=0,adVF=0x100</txt-record>
        </service>
      </service-group>
    '';
  };
};
</syntaxhighlight>
</syntaxhighlight>


Line 102: Line 188:
   package = pkgs.sambaFull;
   package = pkgs.sambaFull;
   openFirewall = true;
   openFirewall = true;
   extraConfig = ''
   settings = {
     load printers = yes
     "global" = {
    printing = cups
      "load printers" = "yes";
    printcap name = cups
      "printing" = "cups";
  '';
      "printcap name" = "cups";
  shares = {
    };
     printers = {
     "printers" = {
       comment = "All Printers";
       "comment" = "All Printers";
       path = "/var/spool/samba";
       "path" = "/var/spool/samba";
       public = "yes";
       "public" = "yes";
       browseable = "yes";
       "browseable" = "yes";
       # to allow user 'guest account' to print.
       # to allow user 'guest account' to print.
       "guest ok" = "yes";
       "guest ok" = "yes";
       writable = "no";
       "writable" = "no";
       printable = "yes";
       "printable" = "yes";
       "create mode" = 0700;
       "create mode" = 0700;
     };
     };
Line 166: Line 252:
       # Set pythonpath manually (bellow with overrideAttrs) as it is not set on 22.11 due to bug
       # Set pythonpath manually (bellow with overrideAttrs) as it is not set on 22.11 due to bug
     }).overrideAttrs (finalAttrs: previousAttrs: {
     }).overrideAttrs (finalAttrs: previousAttrs: {
         pythonPath = with super; [ python3Packages.dnspython tdb ldb talloc ];
         pythonPath = with super; [ python3Packages.dnspython python3Packages.markdown tdb ldb talloc ];
       });
       });
   })];
   })];
Line 228: Line 314:
== 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 256: Line 342:
password=<PASSWORD>
password=<PASSWORD>
</syntaxhighlight>
</syntaxhighlight>
=== mount as user ===


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


=== Firewall configuration ===


== Firewall ==
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:
Line 283: Line 367:
</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 294: Line 417:


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">
   services.gvfs = {
   services.gvfs = {
     enable = true;
     enable = true;
     package = lib.mkForce pkgs.gnome3.gvfs;
     package = lib.mkForce pkgs.gnome.gvfs;
   };
   };
</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 311: Line 438:
</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 340: Line 467:


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]
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]
=== 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>


=== NT_STATUS_INVALID_NETWORK_RESPONSE ===
=== NT_STATUS_INVALID_NETWORK_RESPONSE ===
Line 368: Line 476:
Note that <code>localhost</code> is the ipv6 localhost <code>::1</code>,
Note that <code>localhost</code> is the ipv6 localhost <code>::1</code>,
and <code>127.0.0.1</code> is the ipv4 localhost
and <code>127.0.0.1</code> is the ipv4 localhost
=== Mount shares ===
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`)


=== Permission denied ===
=== Permission denied ===
Line 407: Line 497:
* [https://wiki.archlinux.org/title/Samba Samba in the Arch Linux Wiki]
* [https://wiki.archlinux.org/title/Samba Samba in the Arch Linux Wiki]


[[Category:Services]]
[[Category:Server]]
[[Category:Applications]]