1 { lib, pkgs, config, ... }:
3 package = pkgs.pure-ftpd.override { ldapFtpId = "immaeFtp"; };
4 pure-ftpd-enabled = config.myServices.ftp.pure-ftpd.enable;
5 proftpd-enabled = config.myServices.ftp.proftpd.enable;
9 myServices.ftp.enable = lib.mkOption {
10 type = lib.types.bool;
13 Whether to enable ftp.
16 myServices.ftp.pure-ftpd.enable = lib.mkOption {
17 type = lib.types.bool;
20 Whether to enable pure-ftpd.
23 myServices.ftp.proftpd.enable = lib.mkOption {
24 type = lib.types.bool;
27 Whether to enable proftpd.
32 config = lib.mkIf config.myServices.ftp.enable {
33 security.acme.certs."ftp" = config.myServices.certificates.certConfig // {
34 domain = "eldiron.immae.eu";
35 # FIXME: make it global
36 extraLegoRunFlags = ["--preferred-chain" "ISRG Root X1"];
37 extraLegoRenewFlags = ["--preferred-chain" "ISRG Root X1"];
38 postRun = (lib.optionalString pure-ftpd-enabled ''
39 systemctl restart pure-ftpd.service
40 '') + (lib.optionalString proftpd-enabled ''
41 systemctl restart proftpd.service
43 extraDomainNames = [ "ftp.immae.eu" ];
48 allowedTCPPorts = [ 21 115 ];
49 allowedTCPPortRanges = [ { from = 40000; to = 50000; } ];
54 uid = config.ids.uids.ftp; # 8
56 description = "Anonymous FTP user";
57 home = "/homeless-shelter";
58 extraGroups = [ "keys" ];
61 users.groups.ftp.gid = config.ids.gids.ftp;
63 system.activationScripts.ftp = ''
64 install -m 0755 -o ftp -g ftp -d /var/lib/ftp
65 '' + (lib.optionalString proftpd-enabled ''
66 install -m 0755 -o nobody -g nogroup -d /var/lib/proftpd/authorized_keys
69 secrets.keys."pure-ftpd-ldap" = lib.mkIf pure-ftpd-enabled {
74 LDAPServer ${config.myEnv.ftp.ldap.host}
77 LDAPBaseDN ${config.myEnv.ftp.ldap.base}
78 LDAPBindDN ${config.myEnv.ftp.ldap.dn}
79 LDAPBindPW ${config.myEnv.ftp.ldap.password}
81 LDAPForceDefaultUID False
83 LDAPForceDefaultGID False
84 LDAPFilter ${config.myEnv.ftp.ldap.pure-ftpd_filter}
88 # Pas de possibilite de donner l'Uid/Gid !
89 # Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid
90 LDAPHomeDir immaeFtpDirectory
93 secrets.keys."proftpd-ldap.conf" = lib.mkIf proftpd-enabled {
98 LDAPServer ldaps://${config.myEnv.ftp.ldap.host}:636/??sub
101 LDAPBindDN "${config.myEnv.ftp.ldap.dn}" "${config.myEnv.ftp.ldap.password}"
102 LDAPSearchScope subtree
106 LDAPForceDefaultUID off
107 LDAPForceDefaultGID off
108 LDAPAttr gidNumber immaeFtpGid
109 LDAPAttr uidNumber immaeFtpUid
110 LDAPAttr homeDirectory immaeFtpDirectory
111 LDAPUsers "${config.myEnv.ftp.ldap.base}" "${config.myEnv.ftp.ldap.proftpd_filter}"
112 LDAPGroups "${config.myEnv.ftp.ldap.base}"
116 services.filesWatcher.pure-ftpd = lib.mkIf pure-ftpd-enabled {
118 paths = [ config.secrets.fullPaths."pure-ftpd-ldap" ];
120 services.filesWatcher.proftpd = lib.mkIf proftpd-enabled {
122 paths = [ config.secrets.fullPaths."proftpd-ldap.conf" ];
125 systemd.services.pure-ftpd = let
126 configFile = pkgs.writeText "pure-ftpd.conf" ''
127 PassivePortRange 40000 50000
131 BrokenClientsCompatibility yes
142 LDAPConfigFile ${config.secrets.fullPaths."pure-ftpd-ldap"}
143 LimitRecursion 10000 8
144 AnonymousCanCreateDirs no
152 ProhibitDotFilesWrite no
153 ProhibitDotFilesRead no
155 AnonymousCantUpload no
159 CertFile ${config.security.acme.certs.ftp.directory}/full.pem
161 in lib.mkIf pure-ftpd-enabled {
162 description = "Pure-FTPd server";
163 wantedBy = [ "multi-user.target" ];
164 after = [ "network.target" ];
166 serviceConfig.ExecStart = "${package}/bin/pure-ftpd ${configFile}";
167 serviceConfig.Type = "forking";
168 serviceConfig.PIDFile = "/run/pure-ftpd.pid";
171 systemd.services.proftpd = let
172 configFile = pkgs.writeText "proftpd.conf" ''
174 ServerType standalone
184 # Set the user and group under which the server will run.
195 TLSProtocol TLSv1.1 TLSv1.2 TLSv1.3
197 TLSCertificateChainFile ${config.security.acme.certs.ftp.directory}/fullchain.pem
198 TLSECCertificateFile ${config.security.acme.certs.ftp.directory}/cert.pem
199 TLSECCertificateKeyFile ${config.security.acme.certs.ftp.directory}/key.pem
201 PidFile /run/proftpd/proftpd.pid
203 ScoreboardFile /run/proftpd/proftpd.scoreboard
205 PassivePorts 40000 50000
207 Include ${config.secrets.fullPaths."proftpd-ldap.conf"}
209 RequireValidShell off
211 # Bar use of SITE CHMOD by default
216 <VirtualHost 0.0.0.0>
225 SFTPHostKey /etc/ssh/ssh_host_ed25519_key
226 SFTPHostKey /etc/ssh/ssh_host_rsa_key
227 Include ${config.secrets.fullPaths."proftpd-ldap.conf"}
228 RequireValidShell off
229 SFTPAuthorizedUserKeys file:/var/lib/proftpd/authorized_keys/%u
230 SFTPAuthMethods password publickey
232 SFTPOptions IgnoreSFTPSetOwners
233 AllowChrootSymlinks off
236 in lib.mkIf proftpd-enabled {
237 description = "ProFTPD server";
238 wantedBy = [ "multi-user.target" ];
239 after = [ "network.target" ];
241 serviceConfig.ExecStart = "${pkgs.proftpd}/bin/proftpd -c ${configFile}";
242 serviceConfig.Type = "forking";
243 serviceConfig.PIDFile = "/run/proftpd/proftpd.pid";
244 serviceConfig.RuntimeDirectory = "proftpd";
247 services.cron.systemCronJobs = lib.mkIf proftpd-enabled [
248 "*/2 * * * * nobody ${./ftp_sync.sh}"