From 10e31f6de73536ff545e1799ae72c9f2ab423202 Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Thu, 7 Nov 2013 16:14:59 +0100
Subject: [PATCH] Clean up the vsftpd module a bit

---
 nixos/modules/services/networking/vsftpd.nix | 117 ++++++++-----------
 pkgs/servers/ftp/vsftpd/default.nix          |  27 +++--
 2 files changed, 64 insertions(+), 80 deletions(-)

diff --git a/nixos/modules/services/networking/vsftpd.nix b/nixos/modules/services/networking/vsftpd.nix
index 0a6355e6ff17..e398230e1681 100644
--- a/nixos/modules/services/networking/vsftpd.nix
+++ b/nixos/modules/services/networking/vsftpd.nix
@@ -24,6 +24,7 @@ let
     cfgText = "${vsftpdName}=${if getAttr nixosName cfg then "YES" else "NO"}";
 
     nixosOption = {
+      type = types.bool;
       name = nixosName;
       value = mkOption {
         inherit description default;
@@ -33,27 +34,26 @@ let
   };
 
   optionDescription = [
-
     (yesNoOption "anonymousUser" "anonymous_enable" false ''
-     Whether to enable the anonymous FTP user.
+      Whether to enable the anonymous FTP user.
     '')
     (yesNoOption "localUsers" "local_enable" false ''
-     Whether to enable FTP for local users.
+      Whether to enable FTP for local users.
     '')
     (yesNoOption "writeEnable" "write_enable" false ''
-    Whether any write activity is permitted to users.
+      Whether any write activity is permitted to users.
     '')
     (yesNoOption "anonymousUploadEnable" "anon_upload_enable" false ''
-    Whether any uploads are permitted to anonymous users.
+      Whether any uploads are permitted to anonymous users.
     '')
     (yesNoOption "anonymousMkdirEnable" "anon_mkdir_write_enable" false ''
-    Whether any uploads are permitted to anonymous users.
+      Whether any uploads are permitted to anonymous users.
     '')
     (yesNoOption "chrootlocalUser" "chroot_local_user" false ''
-    Whether local users are confined to their home directory.
+      Whether local users are confined to their home directory.
     '')
     (yesNoOption "userlistEnable" "userlist_enable" false ''
-    Whether users are included.
+      Whether users are included.
     '')
     (yesNoOption "userlistDeny" "userlist_deny" false ''
       Specifies whether <option>userlistFile</option> is a list of user
@@ -61,35 +61,33 @@ let
       The default <literal>false</literal> means whitelist/allow.
     '')
     (yesNoOption "forceLocalLoginsSSL" "force_local_logins_ssl" false ''
-    Only applies if <option>sslEnable</option> is true. Non anonymous (local) users
-    must use a secure SSL connection to send a password.
+      Only applies if <option>sslEnable</option> is true. Non anonymous (local) users
+      must use a secure SSL connection to send a password.
     '')
     (yesNoOption "forceLocalDataSSL" "force_local_data_ssl" false ''
-    Only applies if <option>sslEnable</option> is true. Non anonymous (local) users
-    must use a secure SSL connection for sending/receiving data on data connection.
+      Only applies if <option>sslEnable</option> is true. Non anonymous (local) users
+      must use a secure SSL connection for sending/receiving data on data connection.
     '')
     (yesNoOption "ssl_tlsv1" "ssl_tlsv1" true  '' '')
     (yesNoOption "ssl_sslv2" "ssl_sslv2" false '' '')
     (yesNoOption "ssl_sslv3" "ssl_sslv3" false '' '')
+  ];
 
-    {
-      cfgText = if cfg.rsaCertFile == null then ""
-        else ''
+  configFile = pkgs.writeText "vsftpd.conf"
+    ''
+      ${concatMapStrings (x: "${x.cfgText}\n") optionDescription}
+      ${optionalString (cfg.rsaCertFile != null) ''
         ssl_enable=YES
         rsa_cert_file=${cfg.rsaCertFile}
-      '';
-
-      nixosOption = {
-        name = "rsaCertFile";
-        value = mkOption {
-          default = null;
-          description = ''
-            rsa certificate file.
-          '';
-        };
-      };
-    }
-    ];
+      ''}
+      ${optionalString (cfg.userlistFile != null) ''
+        userlist_file=${cfg.userlistFile}
+      ''}
+      background=NO
+      listen=YES
+      nopriv_user=vsftpd
+      secure_chroot_dir=/var/empty
+    '';
 
 in
 
@@ -108,10 +106,7 @@ in
 
       userlist = mkOption {
         default = [];
-
-        description = ''
-          See <option>userlistFile</option>.
-        '';
+        description = "See <option>userlistFile</option>.";
       };
 
       userlistFile = mkOption {
@@ -127,13 +122,20 @@ in
       };
 
       anonymousUserHome = mkOption {
+        type = types.path;
         default = "/home/ftp/";
-	description = ''
-	  Directory to consider the HOME of the anonymous user.
-	'';
+        description = ''
+          Directory to consider the HOME of the anonymous user.
+        '';
       };
 
-    } // (listToAttrs (catAttrs "nixosOption" optionDescription)) ;
+      rsaCertFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = "RSA certificate file.";
+      };
+
+    } // (listToAttrs (catAttrs "nixosOption" optionDescription));
 
   };
 
@@ -142,14 +144,12 @@ in
 
   config = mkIf cfg.enable {
 
-    assertions = [
-      {
-        assertion =
+    assertions = singleton
+      { assertion =
               (cfg.forceLocalLoginsSSL -> cfg.rsaCertFile != null)
           &&  (cfg.forceLocalDataSSL -> cfg.rsaCertFile != null);
         message = "vsftpd: If forceLocalLoginsSSL or forceLocalDataSSL is true then a rsaCertFile must be provided!";
-      }
-    ];
+      };
 
     users.extraUsers =
       [ { name = "vsftpd";
@@ -157,7 +157,7 @@ in
           description = "VSFTPD user";
           home = "/homeless-shelter";
         }
-      ] ++ pkgs.lib.optional cfg.anonymousUser
+      ] ++ optional cfg.anonymousUser
         { name = "ftp";
           uid = config.ids.uids.ftp;
           group = "ftp";
@@ -165,41 +165,26 @@ in
           home = cfg.anonymousUserHome;
         };
 
-    users.extraGroups = singleton
-      { name = "ftp";
-        gid = config.ids.gids.ftp;
-      };
+    users.extraGroups.ftp.gid = config.ids.gids.ftp;
 
     # If you really have to access root via FTP use mkOverride or userlistDeny
     # = false and whitelist root
     services.vsftpd.userlist = if cfg.userlistDeny then ["root"] else [];
 
-    environment.etc."vsftpd.conf".text =
-      concatMapStrings (x: "${x.cfgText}\n") optionDescription
-      + ''
-      ${if cfg.userlistFile == null then ""
-        else "userlist_file=${cfg.userlistFile}"}
-      background=NO
-      listen=YES
-      nopriv_user=vsftpd
-      secure_chroot_dir=/var/empty
-    '';
+    systemd.services.vsftpd =
+      { description = "Vsftpd Server";
 
-    jobs.vsftpd =
-      { description = "vsftpd server";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
+        wantedBy = [ "multi-user.target" ];
 
         preStart =
-          ''
-            ${if cfg.anonymousUser then ''
+          optionalString cfg.anonymousUser
+            ''
               mkdir -p -m 555 ${cfg.anonymousUserHome}
               chown -R ftp:ftp ${cfg.anonymousUserHome}
-            '' else ""}
-          '';
+            '';
 
-        exec = "${vsftpd}/sbin/vsftpd /etc/vsftpd.conf";
+        serviceConfig.ExecStart = "@${vsftpd}/sbin/vsftpd vsftpd ${configFile}";
+        serviceConfig.Restart = "always";
       };
 
   };
diff --git a/pkgs/servers/ftp/vsftpd/default.nix b/pkgs/servers/ftp/vsftpd/default.nix
index 39b78958b031..3b9b32898e2f 100644
--- a/pkgs/servers/ftp/vsftpd/default.nix
+++ b/pkgs/servers/ftp/vsftpd/default.nix
@@ -1,23 +1,29 @@
 { stdenv, fetchurl, openssl, sslEnable ? false, libcap, pam }:
 
-stdenv.mkDerivation (rec {
+stdenv.mkDerivation rec {
   name = "vsftpd-3.0.2";
-  
+
   src = fetchurl {
     url = "https://security.appspot.com/downloads/${name}.tar.gz";
     sha256 = "0mjy345wszskz1vnk83360c1y37arwgap3gwz8hy13sjqpig0imy";
   };
 
+  preConfigure = stdenv.lib.optionalString sslEnable ''
+    echo "Will enable SSL"
+    sed -i "/VSF_BUILD_SSL/s/^#undef/#define/" builddefs.h
+  '';
+
   # The gcc-wrappers use -idirafter for glibc, and vsftpd also, and
   # their dummyinc come before those of glibc, then the build works bad.
   prePatch = ''
     sed -i -e 's/-idirafter.*//' Makefile
   '';
-  
-  preBuild = let
-      sslLibs = if sslEnable then "-lcrypt -lssl -lcrypto " else "";
+
+  preBuild =
+    let
+      sslLibs = if sslEnable then "-lcrypt -lssl -lcrypto" else "";
     in ''
-      makeFlagsArray=( "LIBS=${sslLibs}-lpam -lcap -fstack-protector" )
+      makeFlagsArray=( "LIBS=${sslLibs} -lpam -lcap -fstack-protector" )
     '';
 
   # It won't link without this flag, used in CFLAGS
@@ -35,11 +41,4 @@ stdenv.mkDerivation (rec {
     mkdir -pv $out/etc/xinetd.d
     install -v -m 644 xinetd.d/vsftpd $out/etc/xinetd.d/vsftpd
   '';
-} // (if sslEnable then {
-  preConfigure = ''
-    echo "Will enable SSL"
-    sed -i "/VSF_BUILD_SSL/s/^#undef/#define/" builddefs.h
-  '';
-
-} else { })
-)
+}