summary refs log tree commit diff
path: root/modules/services/network-filesystems/samba.nix
blob: 177a2f5128e2142110fe4ab325d82885d72c2f09 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
{ config, pkgs, ... }:

with pkgs.lib;

let

  cfg = config.services.samba;
  
  user = "smbguest";
  group = "smbguest";

  logDir = "/var/log/samba";
  privateDir = "/var/samba/private";
 
  inherit (pkgs) samba;

  setupScript =
    ''
      mkdir -p /var/lock

      if ! test -d /home/smbd ; then
        mkdir -p /home/smbd
        chown ${user} /home/smbd
        chmod a+rwx /home/smbd
      fi

      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="$(sed -n 's/^.*smb[ ]\+passwd[ ]\+file[ ]\+=[ ]\+\(.*\)/\1/p' /nix/store/nnmrqalldfv2vkwy6qpg340rv7w34lmp-smb.conf)"
      if [ -n "$passwdFile" ]; then
        echo 'INFO: creating directory containing passwd file'
        mkdir -p "$(dirname "$passwdFile")"
      fi

      mkdir -p ${logDir}
      mkdir -p ${privateDir}

      # The following line is to trigger a restart of the daemons when
      # the configuration changes:
      # ${configFile}
    '';

  configFile = pkgs.writeText "smb.conf"
    ''
      [ global ]
      log file = ${logDir}/log.%m
      private dir = ${privateDir}
      ${optionalString cfg.syncPasswordsByPam "pam password change = true"}

      ${cfg.extraConfig}
    '';

  daemonJob = appName: args:
    { name = "samba-${appName}";
      description = "Samba Service daemon ${appName}";

      startOn = "samba/started";
      stopOn = "samba-control/stop";

      exec = "${samba}/sbin/${appName} ${args}";
    };

in

{

  ###### interface

  options = {

    # !!! clean up the descriptions.
  
    services.samba = {

      enable = mkOption {
        default = false;
        description = "
          Whether to enable the samba server. (to communicate with, and provide windows shares)
          use start / stop samba-control to start/stop all daemons.
          smbd and nmbd are not shutdown correctly yet. so just pkill them and restart those jobs.
        ";
      };

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

            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
        ";
      };
    };

  };
  

  ###### implementation

  config = mkIf config.services.samba.enable {

    users.extraUsers = singleton
      { name = user;
        description = "Samba service user";
        group = group;
      };

    users.extraGroups = singleton
      { name = group;
      };

    # always provide a smb.conf to shut up programs like smbclient and smbspool.
    environment.etc = mkAlways (singleton
      { source =
          if cfg.enable then configFile
          else pkgs.writeText "smb-dummy.conf" "# Samba is disabled.";
        target = "samba/smb.conf";
      });

    # Dummy job to start the real Samba daemons (nmbd, smbd, winbindd).
    jobAttrs.sambaControl =
      { name = "samba";
        description = "Samba server";

        startOn = "network-interfaces/started";
        stopOn = "network-interfaces/stop";

        preStart = setupScript;
      };

    # nmbd says "standard input is not a socket, assuming -D option",
    # but using -i makes it stay in foreground (?)
    jobAttrs.nmbd = daemonJob "nmbd" " -i -F";

    jobAttrs.smbd = daemonJob "smbd" " -i -F";

    jobAttrs.winbindd = daemonJob "winbindd" " -F";

  };
  
}