{ 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; }; jobAttrs.vsftpd = { description = "vsftpd server"; startOn = "network-interfaces/started"; stopOn = "network-interfaces/stop"; preStart = '' # !!! Why isn't this generated in the normal way? cat > /etc/vsftpd.conf <