at 16.09-beta 6.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 /* minimal secure setup: 8 9 enable = true; 10 forceLocalLoginsSSL = true; 11 forceLocalDataSSL = true; 12 userlistDeny = false; 13 localUsers = true; 14 userlist = ["non-root-user" "other-non-root-user"]; 15 rsaCertFile = "/var/vsftpd/vsftpd.pem"; 16 17 */ 18 19 cfg = config.services.vsftpd; 20 21 inherit (pkgs) vsftpd; 22 23 yesNoOption = nixosName: vsftpdName: default: description: { 24 cfgText = "${vsftpdName}=${if getAttr nixosName cfg then "YES" else "NO"}"; 25 26 nixosOption = { 27 type = types.bool; 28 name = nixosName; 29 value = mkOption { 30 inherit description default; 31 type = types.bool; 32 }; 33 }; 34 }; 35 36 optionDescription = [ 37 (yesNoOption "anonymousUser" "anonymous_enable" false '' 38 Whether to enable the anonymous FTP user. 39 '') 40 (yesNoOption "localUsers" "local_enable" false '' 41 Whether to enable FTP for local users. 42 '') 43 (yesNoOption "writeEnable" "write_enable" false '' 44 Whether any write activity is permitted to users. 45 '') 46 (yesNoOption "anonymousUploadEnable" "anon_upload_enable" false '' 47 Whether any uploads are permitted to anonymous users. 48 '') 49 (yesNoOption "anonymousMkdirEnable" "anon_mkdir_write_enable" false '' 50 Whether any uploads are permitted to anonymous users. 51 '') 52 (yesNoOption "chrootlocalUser" "chroot_local_user" false '' 53 Whether local users are confined to their home directory. 54 '') 55 (yesNoOption "userlistEnable" "userlist_enable" false '' 56 Whether users are included. 57 '') 58 (yesNoOption "userlistDeny" "userlist_deny" false '' 59 Specifies whether <option>userlistFile</option> is a list of user 60 names to allow or deny access. 61 The default <literal>false</literal> means whitelist/allow. 62 '') 63 (yesNoOption "forceLocalLoginsSSL" "force_local_logins_ssl" false '' 64 Only applies if <option>sslEnable</option> is true. Non anonymous (local) users 65 must use a secure SSL connection to send a password. 66 '') 67 (yesNoOption "forceLocalDataSSL" "force_local_data_ssl" false '' 68 Only applies if <option>sslEnable</option> is true. Non anonymous (local) users 69 must use a secure SSL connection for sending/receiving data on data connection. 70 '') 71 (yesNoOption "portPromiscuous" "port_promiscuous" false '' 72 Set to YES if you want to disable the PORT security check that ensures that 73 outgoing data connections can only connect to the client. Only enable if you 74 know what you are doing! 75 '') 76 (yesNoOption "ssl_tlsv1" "ssl_tlsv1" true '' '') 77 (yesNoOption "ssl_sslv2" "ssl_sslv2" false '' '') 78 (yesNoOption "ssl_sslv3" "ssl_sslv3" false '' '') 79 ]; 80 81 configFile = pkgs.writeText "vsftpd.conf" 82 '' 83 ${concatMapStrings (x: "${x.cfgText}\n") optionDescription} 84 ${optionalString (cfg.rsaCertFile != null) '' 85 ssl_enable=YES 86 rsa_cert_file=${cfg.rsaCertFile} 87 ''} 88 ${optionalString (cfg.rsaKeyFile != null) '' 89 rsa_private_key_file=${cfg.rsaKeyFile} 90 ''} 91 ${optionalString (cfg.userlistFile != null) '' 92 userlist_file=${cfg.userlistFile} 93 ''} 94 background=YES 95 listen=YES 96 nopriv_user=vsftpd 97 secure_chroot_dir=/var/empty 98 syslog_enable=YES 99 ${optionalString (pkgs.stdenv.system == "x86_64-linux") '' 100 seccomp_sandbox=NO 101 ''} 102 anon_umask=${cfg.anonymousUmask} 103 ''; 104 105in 106 107{ 108 109 ###### interface 110 111 options = { 112 113 services.vsftpd = { 114 115 enable = mkOption { 116 default = false; 117 description = "Whether to enable the vsftpd FTP server."; 118 }; 119 120 userlist = mkOption { 121 default = []; 122 description = "See <option>userlistFile</option>."; 123 }; 124 125 userlistFile = mkOption { 126 type = types.path; 127 default = pkgs.writeText "userlist" (concatMapStrings (x: "${x}\n") cfg.userlist); 128 defaultText = "pkgs.writeText \"userlist\" (concatMapStrings (x: \"\${x}\n\") cfg.userlist)"; 129 description = '' 130 Newline separated list of names to be allowed/denied if <option>userlistEnable</option> 131 is <literal>true</literal>. Meaning see <option>userlistDeny</option>. 132 133 The default is a file containing the users from <option>userlist</option>. 134 135 If explicitely set to null userlist_file will not be set in vsftpd's config file. 136 ''; 137 }; 138 139 anonymousUserHome = mkOption { 140 type = types.path; 141 default = "/home/ftp/"; 142 description = '' 143 Directory to consider the HOME of the anonymous user. 144 ''; 145 }; 146 147 rsaCertFile = mkOption { 148 type = types.nullOr types.path; 149 default = null; 150 description = "RSA certificate file."; 151 }; 152 153 rsaKeyFile = mkOption { 154 type = types.nullOr types.path; 155 default = null; 156 description = "RSA private key file."; 157 }; 158 159 anonymousUmask = mkOption { 160 type = types.string; 161 default = "077"; 162 example = "002"; 163 description = "Anonymous write umask."; 164 }; 165 166 } // (listToAttrs (catAttrs "nixosOption" optionDescription)); 167 168 }; 169 170 171 ###### implementation 172 173 config = mkIf cfg.enable { 174 175 assertions = singleton 176 { assertion = 177 (cfg.forceLocalLoginsSSL -> cfg.rsaCertFile != null) 178 && (cfg.forceLocalDataSSL -> cfg.rsaCertFile != null); 179 message = "vsftpd: If forceLocalLoginsSSL or forceLocalDataSSL is true then a rsaCertFile must be provided!"; 180 }; 181 182 users.extraUsers = 183 [ { name = "vsftpd"; 184 uid = config.ids.uids.vsftpd; 185 description = "VSFTPD user"; 186 home = "/homeless-shelter"; 187 } 188 ] ++ optional cfg.anonymousUser 189 { name = "ftp"; 190 uid = config.ids.uids.ftp; 191 group = "ftp"; 192 description = "Anonymous FTP user"; 193 home = cfg.anonymousUserHome; 194 }; 195 196 users.extraGroups.ftp.gid = config.ids.gids.ftp; 197 198 # If you really have to access root via FTP use mkOverride or userlistDeny 199 # = false and whitelist root 200 services.vsftpd.userlist = if cfg.userlistDeny then ["root"] else []; 201 202 systemd.services.vsftpd = 203 { description = "Vsftpd Server"; 204 205 wantedBy = [ "multi-user.target" ]; 206 207 preStart = 208 optionalString cfg.anonymousUser 209 '' 210 mkdir -p -m 555 ${cfg.anonymousUserHome} 211 chown -R ftp:ftp ${cfg.anonymousUserHome} 212 ''; 213 214 serviceConfig.ExecStart = "@${vsftpd}/sbin/vsftpd vsftpd ${configFile}"; 215 serviceConfig.Restart = "always"; 216 serviceConfig.Type = "forking"; 217 }; 218 219 }; 220 221}