1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 smbToString = x: if builtins.typeOf x == "bool" 8 then (if x then "true" else "false") 9 else toString x; 10 11 cfg = config.services.samba; 12 13 samba = cfg.package; 14 15 setupScript = 16 '' 17 mkdir -p /var/lock/samba /var/log/samba /var/cache/samba /var/lib/samba/private 18 ''; 19 20 shareConfig = name: 21 let share = getAttr name cfg.shares; in 22 "[${name}]\n " + (smbToString ( 23 map 24 (key: "${key} = ${smbToString (getAttr key share)}\n") 25 (attrNames share) 26 )); 27 28 configFile = pkgs.writeText "smb.conf" 29 (if cfg.configText != null then cfg.configText else 30 '' 31 [ global ] 32 security = ${cfg.securityType} 33 passwd program = /var/setuid-wrappers/passwd %u 34 pam password change = ${smbToString cfg.syncPasswordsByPam} 35 invalid users = ${smbToString cfg.invalidUsers} 36 37 ${cfg.extraConfig} 38 39 ${smbToString (map shareConfig (attrNames cfg.shares))} 40 ''); 41 42 # This may include nss_ldap, needed for samba if it has to use ldap. 43 nssModulesPath = config.system.nssModules.path; 44 45 daemonService = appName: args: 46 { description = "Samba Service Daemon ${appName}"; 47 48 requiredBy = [ "samba.target" ]; 49 partOf = [ "samba.target" ]; 50 51 environment = { 52 LD_LIBRARY_PATH = nssModulesPath; 53 LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; 54 }; 55 56 serviceConfig = { 57 ExecStart = "${samba}/sbin/${appName} ${args}"; 58 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 59 }; 60 61 restartTriggers = [ configFile ]; 62 }; 63 64in 65 66{ 67 68 ###### interface 69 70 options = { 71 72 # !!! clean up the descriptions. 73 74 services.samba = { 75 76 enable = mkOption { 77 type = types.bool; 78 default = false; 79 description = '' 80 Whether to enable Samba, which provides file and print 81 services to Windows clients through the SMB/CIFS protocol. 82 ''; 83 }; 84 85 package = mkOption { 86 type = types.package; 87 default = pkgs.samba; 88 example = pkgs.samba4; 89 description = '' 90 Defines which package should be used for the samba server. 91 ''; 92 }; 93 94 syncPasswordsByPam = mkOption { 95 type = types.bool; 96 default = false; 97 description = '' 98 Enabling this will add a line directly after pam_unix.so. 99 Whenever a password is changed the samba password will be updated as well. 100 However you still yave to add the samba password once using smbpasswd -a user 101 If you don't want to maintain an extra pwd database you still can send plain text 102 passwords which is not secure. 103 ''; 104 }; 105 106 invalidUsers = mkOption { 107 type = types.listOf types.str; 108 default = [ "root" ]; 109 description = '' 110 List of users who are denied to login via Samba. 111 ''; 112 }; 113 114 extraConfig = mkOption { 115 type = types.lines; 116 default = ""; 117 description = '' 118 Additional global section and extra section lines go in here. 119 ''; 120 }; 121 122 configText = mkOption { 123 type = types.nullOr types.lines; 124 default = null; 125 description = '' 126 Verbatim contents of smb.conf. If null (default), use the 127 autogenerated file from NixOS instead. 128 ''; 129 }; 130 131 securityType = mkOption { 132 type = types.str; 133 default = "user"; 134 example = "share"; 135 description = "Samba security type"; 136 }; 137 138 nsswins = mkOption { 139 default = false; 140 type = types.bool; 141 description = '' 142 Whether to enable the WINS NSS (Name Service Switch) plug-in. 143 Enabling it allows applications to resolve WINS/NetBIOS names (a.k.a. 144 Windows machine names) by transparently querying the winbindd daemon. 145 ''; 146 }; 147 148 shares = mkOption { 149 default = {}; 150 description = '' 151 A set describing shared resources. 152 See <command>man smb.conf</command> for options. 153 ''; 154 type = types.attrsOf (types.attrsOf types.unspecified); 155 example = 156 { srv = 157 { path = "/srv"; 158 "read only" = true; 159 comment = "Public samba share."; 160 }; 161 }; 162 }; 163 164 }; 165 166 }; 167 168 169 ###### implementation 170 171 config = mkMerge 172 [ { # Always provide a smb.conf to shut up programs like smbclient and smbspool. 173 environment.etc = singleton 174 { source = 175 if cfg.enable then configFile 176 else pkgs.writeText "smb-dummy.conf" "# Samba is disabled."; 177 target = "samba/smb.conf"; 178 }; 179 } 180 181 (mkIf config.services.samba.enable { 182 183 system.nssModules = optional cfg.nsswins samba; 184 185 systemd = { 186 targets.samba = { 187 description = "Samba Server"; 188 requires = [ "samba-setup.service" ]; 189 after = [ "samba-setup.service" "network.target" ]; 190 wantedBy = [ "multi-user.target" ]; 191 }; 192 193 services = { 194 "samba-nmbd" = daemonService "nmbd" "-F"; 195 "samba-smbd" = daemonService "smbd" "-F"; 196 "samba-winbindd" = daemonService "winbindd" "-F"; 197 "samba-setup" = { 198 description = "Samba Setup Task"; 199 script = setupScript; 200 unitConfig.RequiresMountsFor = "/var/lib/samba"; 201 }; 202 }; 203 }; 204 205 security.pam.services.sambda = {}; 206 207 }) 208 ]; 209 210}