Samba: Difference between revisions
imported>Onny Restructuring page and cleanup |
→User Authentication: add robust automated authentication example that provides full context and aims to give a basic, typical password-protected folder share |
||
| (15 intermediate revisions by 11 users not shown) | |||
| Line 3: | Line 3: | ||
== Server setup == | == Server setup == | ||
Example setup for creating a public guest share called <code>public</code> and a private share called <code>private</code> | 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> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
services.samba = { | services.samba = { | ||
enable = true; | enable = true; | ||
openFirewall = true; | openFirewall = true; | ||
settings = { | |||
workgroup = WORKGROUP | global = { | ||
"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"; | |||
}; | |||
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 55: | Line 64: | ||
networking.firewall.allowPing = true; | networking.firewall.allowPing = true; | ||
</nowiki>}} | </nowiki>}} | ||
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 | 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 68: | Line 124: | ||
==== Apple Time Machine ==== | ==== Apple Time Machine ==== | ||
In addition to the example above, add this to your configuration: | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.samba = { | services.samba = { | ||
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 84: | 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 100: | Line 188: | ||
package = pkgs.sambaFull; | package = pkgs.sambaFull; | ||
openFirewall = true; | openFirewall = true; | ||
settings = { | |||
load printers = yes | "global" = { | ||
"load printers" = "yes"; | |||
"printing" = "cups"; | |||
"printcap name" = "cups"; | |||
}; | |||
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 164: | 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 226: | Line 314: | ||
== Samba Client == | == Samba Client == | ||
=== | === 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 254: | Line 342: | ||
password=<PASSWORD> | password=<PASSWORD> | ||
</syntaxhighlight> | </syntaxhighlight> | ||
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 268: | 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 === | |||
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 281: | 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 292: | 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. | 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 309: | Line 438: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===== 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 338: | 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] | ||
=== NT_STATUS_INVALID_NETWORK_RESPONSE === | === NT_STATUS_INVALID_NETWORK_RESPONSE === | ||
| Line 366: | 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 | ||
=== Permission denied === | === Permission denied === | ||
| Line 405: | 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: | [[Category:Server]] | ||
[[Category:Applications]] | |||