nixos/preload: init
[NixPkgs.git] / nixos / modules / services / network-filesystems / samba.nix
blob0b22302c0b6dc1b5d389c8c929a129f64f1e6774
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   smbToString = x: if builtins.typeOf x == "bool"
8                    then boolToString x
9                    else toString x;
11   cfg = config.services.samba;
13   samba = cfg.package;
15   shareConfig = name:
16     let share = getAttr name cfg.shares; in
17     "[${name}]\n " + (smbToString (
18        map
19          (key: "${key} = ${smbToString (getAttr key share)}\n")
20          (attrNames share)
21     ));
23   configFile = pkgs.writeText "smb.conf"
24     (if cfg.configText != null then cfg.configText else
25     ''
26       [global]
27       security = ${cfg.securityType}
28       passwd program = /run/wrappers/bin/passwd %u
29       invalid users = ${smbToString cfg.invalidUsers}
31       ${cfg.extraConfig}
33       ${smbToString (map shareConfig (attrNames cfg.shares))}
34     '');
36   # This may include nss_ldap, needed for samba if it has to use ldap.
37   nssModulesPath = config.system.nssModules.path;
39   daemonService = appName: args:
40     { description = "Samba Service Daemon ${appName}";
42       after = [ (mkIf (cfg.enableNmbd && "${appName}" == "smbd") "samba-nmbd.service") "network.target" ];
43       requiredBy = [ "samba.target" ];
44       partOf = [ "samba.target" ];
46       environment = {
47         LD_LIBRARY_PATH = nssModulesPath;
48         LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
49       };
51       serviceConfig = {
52         ExecStart = "${samba}/sbin/${appName} --foreground --no-process-group ${args}";
53         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
54         LimitNOFILE = 16384;
55         PIDFile = "/run/${appName}.pid";
56         Type = "notify";
57         NotifyAccess = "all"; #may not do anything...
58       };
59       unitConfig.RequiresMountsFor = "/var/lib/samba";
61       restartTriggers = [ configFile ];
62     };
67   imports = [
68     (mkRemovedOptionModule [ "services" "samba" "defaultShare" ] "")
69     (mkRemovedOptionModule [ "services" "samba" "syncPasswordsByPam" ] "This option has been removed by upstream, see https://bugzilla.samba.org/show_bug.cgi?id=10669#c10")
70   ];
72   ###### interface
74   options = {
76     # !!! clean up the descriptions.
78     services.samba = {
80       enable = mkOption {
81         type = types.bool;
82         default = false;
83         description = lib.mdDoc ''
84           Whether to enable Samba, which provides file and print
85           services to Windows clients through the SMB/CIFS protocol.
87           ::: {.note}
88           If you use the firewall consider adding the following:
90               services.samba.openFirewall = true;
91           :::
92         '';
93       };
95       openFirewall = mkOption {
96         type = types.bool;
97         default = false;
98         description = lib.mdDoc ''
99           Whether to automatically open the necessary ports in the firewall.
100         '';
101       };
103       enableNmbd = mkOption {
104         type = types.bool;
105         default = true;
106         description = lib.mdDoc ''
107           Whether to enable Samba's nmbd, which replies to NetBIOS over IP name
108           service requests. It also participates in the browsing protocols
109           which make up the Windows "Network Neighborhood" view.
110         '';
111       };
113       enableWinbindd = mkOption {
114         type = types.bool;
115         default = true;
116         description = lib.mdDoc ''
117           Whether to enable Samba's winbindd, which provides a number of services
118           to the Name Service Switch capability found in most modern C libraries,
119           to arbitrary applications via PAM and ntlm_auth and to Samba itself.
120         '';
121       };
123       package = mkOption {
124         type = types.package;
125         default = pkgs.samba;
126         defaultText = literalExpression "pkgs.samba";
127         example = literalExpression "pkgs.samba4Full";
128         description = lib.mdDoc ''
129           Defines which package should be used for the samba server.
130         '';
131       };
133       invalidUsers = mkOption {
134         type = types.listOf types.str;
135         default = [ "root" ];
136         description = lib.mdDoc ''
137           List of users who are denied to login via Samba.
138         '';
139       };
141       extraConfig = mkOption {
142         type = types.lines;
143         default = "";
144         description = lib.mdDoc ''
145           Additional global section and extra section lines go in here.
146         '';
147         example = ''
148           guest account = nobody
149           map to guest = bad user
150         '';
151       };
153       configText = mkOption {
154         type = types.nullOr types.lines;
155         default = null;
156         description = lib.mdDoc ''
157           Verbatim contents of smb.conf. If null (default), use the
158           autogenerated file from NixOS instead.
159         '';
160       };
162       securityType = mkOption {
163         type = types.str;
164         default = "user";
165         description = lib.mdDoc "Samba security type";
166       };
168       nsswins = mkOption {
169         default = false;
170         type = types.bool;
171         description = lib.mdDoc ''
172           Whether to enable the WINS NSS (Name Service Switch) plug-in.
173           Enabling it allows applications to resolve WINS/NetBIOS names (a.k.a.
174           Windows machine names) by transparently querying the winbindd daemon.
175         '';
176       };
178       shares = mkOption {
179         default = {};
180         description = lib.mdDoc ''
181           A set describing shared resources.
182           See {command}`man smb.conf` for options.
183         '';
184         type = types.attrsOf (types.attrsOf types.unspecified);
185         example = literalExpression ''
186           { public =
187             { path = "/srv/public";
188               "read only" = true;
189               browseable = "yes";
190               "guest ok" = "yes";
191               comment = "Public samba share.";
192             };
193           }
194         '';
195       };
197     };
199   };
202   ###### implementation
204   config = mkMerge
205     [ { assertions =
206           [ { assertion = cfg.nsswins -> cfg.enableWinbindd;
207               message   = "If samba.nsswins is enabled, then samba.enableWinbindd must also be enabled";
208             }
209           ];
210         # Always provide a smb.conf to shut up programs like smbclient and smbspool.
211         environment.etc."samba/smb.conf".source = mkOptionDefault (
212           if cfg.enable then configFile
213           else pkgs.writeText "smb-dummy.conf" "# Samba is disabled."
214         );
215       }
217       (mkIf cfg.enable {
219         system.nssModules = optional cfg.nsswins samba;
220         system.nssDatabases.hosts = optional cfg.nsswins "wins";
222         systemd = {
223           targets.samba = {
224             description = "Samba Server";
225             after = [ "network.target" ];
226             wants = [ "network-online.target" ];
227             wantedBy = [ "multi-user.target" ];
228           };
229           # Refer to https://github.com/samba-team/samba/tree/master/packaging/systemd
230           # for correct use with systemd
231           services = {
232             samba-smbd = daemonService "smbd" "";
233             samba-nmbd = mkIf cfg.enableNmbd (daemonService "nmbd" "");
234             samba-winbindd = mkIf cfg.enableWinbindd (daemonService "winbindd" "");
235           };
236           tmpfiles.rules = [
237             "d /var/lock/samba - - - - -"
238             "d /var/log/samba - - - - -"
239             "d /var/cache/samba - - - - -"
240             "d /var/lib/samba/private - - - - -"
241           ];
242         };
244         security.pam.services.samba = {};
245         environment.systemPackages = [ cfg.package ];
247         networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 139 445 ];
248         networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall [ 137 138 ];
249       })
250     ];