summary refs log tree commit diff
path: root/modules/services/networking/vsftpd.nix
blob: 1b2432401deff16fc609bef894bb71d1db2c8a62 (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
{ config, pkgs, ... }:

with pkgs.lib;

let

  cfg = config.services.vsftpd;

  inherit (pkgs) vsftpd;

  yesNoOption = p : name :
    "${name}=${if p then "YES" else "NO"}";

in

{

  ###### interface

  options = {

    services.vsftpd = {

      enable = mkOption {
        default = false;
        description = "Whether to enable the vsftpd FTP server.";
      };

      anonymousUser = mkOption {
        default = false;
        description = "Whether to enable the anonymous FTP user.";
      };

      anonymousUserHome = mkOption {
        default = "/home/ftp";
        description = "Path to anonymous user data.";
      };

      localUsers = mkOption {
        default = false;
        description = "Whether to enable FTP for local users.";
      };

      writeEnable = mkOption {
        default = false;
        description = "Whether any write activity is permitted to users.";
      };

      anonymousUploadEnable = mkOption {
        default = false;
        description = "Whether any uploads are permitted to anonymous users.";
      };

      anonymousMkdirEnable = mkOption {
        default = false;
        description = "Whether mkdir is permitted to anonymous users.";
      };

      chrootlocalUser = mkOption {
        default = false;
        description = "Whether local users are confined to their home directory.";
      };

      userlistEnable = mkOption {
        default = false;
        description = "Whether users are included.";
      };

      userlistDeny = mkOption {
        default = false;
        description = "Whether users are excluded.";
      };

    };

  };


  ###### implementation

  config = mkIf cfg.enable {

    users.extraUsers =
      [ { name = "vsftpd";
          uid = config.ids.uids.vsftpd;
          description = "VSFTPD user";
          home = "/homeless-shelter";
        }
      ] ++ pkgs.lib.optional cfg.anonymousUser
        { name = "ftp";
          uid = config.ids.uids.ftp;
          group = "ftp";
          description = "Anonymous FTP user";
          home = cfg.anonymousUserHome;
        };

    users.extraGroups = singleton
      { name = "ftp";
        gid = config.ids.gids.ftp;
      };

    jobs.vsftpd =
      { description = "vsftpd server";

        startOn = "started network-interfaces";
        stopOn = "stopping network-interfaces";

        preStart =
          ''
            # !!! Why isn't this generated in the normal way?
            cat > /etc/vsftpd.conf <<EOF
            ${yesNoOption cfg.anonymousUser "anonymous_enable"}
            ${yesNoOption cfg.localUsers "local_enable"}
            ${yesNoOption cfg.writeEnable "write_enable"}
            ${yesNoOption cfg.anonymousUploadEnable "anon_upload_enable"}
            ${yesNoOption cfg.anonymousMkdirEnable "anon_mkdir_write_enable"}
            ${yesNoOption cfg.chrootlocalUser "chroot_local_user"}
            ${yesNoOption cfg.userlistEnable "userlist_enable"}
            ${yesNoOption cfg.userlistDeny "userlist_deny"}
            background=NO
            listen=YES
            nopriv_user=vsftpd
            secure_chroot_dir=/var/empty
            EOF

            ${if cfg.anonymousUser then ''
              mkdir -p -m 555 ${cfg.anonymousUserHome}
              chown -R ftp:ftp ${cfg.anonymousUserHome}
            '' else ""}
          '';

        exec = "${vsftpd}/sbin/vsftpd /etc/vsftpd.conf";
      };

  };

}