{ config, lib, pkgs, ... }: with lib; let cfg = config.services.samba; logDir = "/var/log/samba"; privateDir = "/var/samba/private"; inherit (pkgs) samba; setupScript = '' if ! test -d /var/samba ; then mkdir -p /var/samba/locks /var/samba/cores/nmbd /var/samba/cores/smbd /var/samba/cores/winbindd fi passwdFile="$(${pkgs.gnused}/bin/sed -n 's/^.*smb[ ]\+passwd[ ]\+file[ ]\+=[ ]\+\(.*\)/\1/p' ${configFile})" if [ -n "$passwdFile" ]; then echo 'INFO: [samba] creating directory containing passwd file' mkdir -p "$(dirname "$passwdFile")" fi mkdir -p ${logDir} mkdir -p ${privateDir} ''; configFile = pkgs.writeText "smb.conf" (if cfg.configText != null then cfg.configText else '' [ global ] log file = ${logDir}/log.%m private dir = ${privateDir} ${optionalString cfg.syncPasswordsByPam "pam password change = true"} ${cfg.extraConfig} ''); # This may include nss_ldap, needed for samba if it has to use ldap. nssModulesPath = config.system.nssModules.path; daemonService = appName: args: { description = "Samba Service Daemon ${appName}"; requiredBy = [ "samba.target" ]; partOf = [ "samba.target" ]; environment = { LD_LIBRARY_PATH = nssModulesPath; LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; }; serviceConfig = { ExecStart = "${samba}/sbin/${appName} ${args}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; }; restartTriggers = [ configFile ]; }; in { ###### interface options = { # !!! clean up the descriptions. services.samba = { enable = mkOption { default = false; description = " Whether to enable Samba, which provides file and print services to Windows clients through the SMB/CIFS protocol. "; }; syncPasswordsByPam = mkOption { default = false; description = " enabling this will add a line directly after pam_unix.so. Whenever a password is changed the samba password will be updated as well. However you still yave to add the samba password once using smbpasswd -a user If you don't want to maintain an extra pwd database you still can send plain text passwords which is not secure. "; }; extraConfig = mkOption { # !!! Bad default. default = '' # [global] continuing global section here, section is started by nix to set pids etc smb passwd file = /etc/samba/passwd # is this useful ? domain master = auto encrypt passwords = Yes client plaintext auth = No # yes: if you use this you probably also want to enable syncPasswordsByPam # no: You can still use the pam password database. However # passwords will be sent plain text on network (discouraged) workgroup = Users server string = %h comment = Samba log file = /var/log/samba/log.%m log level = 10 max log size = 50000 security = ${cfg.securityType} client lanman auth = Yes dns proxy = no invalid users = root passdb backend = tdbsam passwd program = /usr/bin/passwd %u ''; description = " additional global section and extra section lines go in here. "; }; configFile = mkOption { description = " internal use to pass filepath to samba pam module "; }; configText = mkOption { type = types.nullOr types.lines; default = null; description = " Verbatim contents of smb.conf. If null (default), use the autogenerated file from NixOS instead. "; }; securityType = mkOption { description = "Samba security type"; default = "user"; example = "share"; }; nsswins = mkOption { default = false; type = types.uniq types.bool; description = '' Whether to enable the WINS NSS (Name Service Switch) plug-in. Enabling it allows applications to resolve WINS/NetBIOS names (a.k.a. Windows machine names) by transparently querying the winbindd daemon. ''; }; }; }; ###### implementation config = mkMerge [ { # Always provide a smb.conf to shut up programs like smbclient and smbspool. environment.etc = singleton { source = if cfg.enable then configFile else pkgs.writeText "smb-dummy.conf" "# Samba is disabled."; target = "samba/smb.conf"; }; } (mkIf config.services.samba.enable { system.nssModules = optional cfg.nsswins samba; systemd = { targets.samba = { description = "Samba Server"; requires = [ "samba-setup.service" ]; after = [ "samba-setup.service" "network.target" ]; wantedBy = [ "multi-user.target" ]; }; services = { "samba-nmbd" = daemonService "nmbd" "-F"; "samba-smbd" = daemonService "smbd" "-F"; "samba-winbindd" = daemonService "winbindd" "-F"; "samba-setup" = { description = "Samba Setup Task"; script = setupScript; unitConfig.RequiresMountsFor = "/var/samba /var/log/samba"; }; }; }; security.pam.services.sambda = {}; }) ]; }