]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - modules/private/ftp.nix
Add chatons infos
[perso/Immae/Config/Nix.git] / modules / private / ftp.nix
1 { lib, pkgs, config, ... }:
2 let
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;
6 in
7 {
8 options = {
9 myServices.ftp.enable = lib.mkOption {
10 type = lib.types.bool;
11 default = false;
12 description = ''
13 Whether to enable ftp.
14 '';
15 };
16 myServices.ftp.pure-ftpd.enable = lib.mkOption {
17 type = lib.types.bool;
18 default = false;
19 description = ''
20 Whether to enable pure-ftpd.
21 '';
22 };
23 myServices.ftp.proftpd.enable = lib.mkOption {
24 type = lib.types.bool;
25 default = true;
26 description = ''
27 Whether to enable proftpd.
28 '';
29 };
30 };
31
32 config = lib.mkIf config.myServices.ftp.enable {
33 myServices.chatonsProperties.services.espace-de-stockage = {
34 file.datetime = "2022-08-22T01:00:00";
35 service = {
36 name = "Espace de stockage";
37 description = "Compte FTP/SFTP";
38 logo = if pure-ftpd-enabled
39 then "https://www.pureftpd.org/project/pure-ftpd/images/favicon.png"
40 else if proftpd-enabled
41 then "http://proftpd.org/proftpd.png"
42 else "";
43 website = "ftp.immae.eu";
44 status.level = "OK";
45 status.description = "OK";
46 registration."" = ["MEMBER" "CLIENT"];
47 registration.load = "OPEN";
48 install.type = "PACKAGE";
49 };
50 software = if pure-ftpd-enabled then {
51 name = "Pure-ftpd";
52 website = "https://www.pureftpd.org/project/pure-ftpd/";
53 license.url = "https://github.com/jedisct1/pure-ftpd/blob/master/COPYING";
54 license.name = "MIT Licence";
55 version = package.version;
56 source.url = "https://github.com/jedisct1/pure-ftpd/";
57 modules = "openssh";
58 } else if proftpd-enabled then {
59 name = "ProFTPD";
60 website = "http://proftpd.org/";
61 license.url = "https://github.com/proftpd/proftpd/blob/master/COPYING";
62 license.name = "GNU General Public License v2.0";
63 version = pkgs.proftpd.version;
64 source.url = "https://github.com/proftpd/proftpd/";
65 modules = "openssh";
66 } else {};
67 };
68 #myServices.chatonsProperties.services.ftp = {
69 # file.datetime = "2022-08-22T01:00:00";
70 # service = {
71 # name = "Comptes FTP";
72 # description = "Compte FTP/SFTP";
73 # logo = if pure-ftpd-enabled
74 # then "https://www.pureftpd.org/project/pure-ftpd/images/favicon.png"
75 # else if proftpd-enabled
76 # then "http://proftpd.org/proftpd.png"
77 # else "";
78 # website = "ftp.immae.eu";
79 # status.level = "OK";
80 # status.description = "OK";
81 # registration."" = ["MEMBER" "CLIENT"];
82 # registration.load = "OPEN";
83 # install.type = "PACKAGE";
84 # };
85 # software = if pure-ftpd-enabled then {
86 # name = "Pure-ftpd";
87 # website = "https://www.pureftpd.org/project/pure-ftpd/";
88 # license.url = "https://github.com/jedisct1/pure-ftpd/blob/master/COPYING";
89 # license.name = "MIT Licence";
90 # version = package.version;
91 # source.url = "https://github.com/jedisct1/pure-ftpd/";
92 # } else if proftpd-enabled then {
93 # name = "ProFTPD";
94 # website = "http://proftpd.org/";
95 # license.url = "https://github.com/proftpd/proftpd/blob/master/COPYING";
96 # license.name = "GNU General Public License v2.0";
97 # version = pkgs.proftpd.version;
98 # source.url = "https://github.com/proftpd/proftpd/";
99 # } else {};
100 #};
101 security.acme.certs."ftp" = config.myServices.certificates.certConfig // {
102 domain = "eldiron.immae.eu";
103 # FIXME: make it global
104 extraLegoRunFlags = ["--preferred-chain" "ISRG Root X1"];
105 extraLegoRenewFlags = ["--preferred-chain" "ISRG Root X1"];
106 postRun = (lib.optionalString pure-ftpd-enabled ''
107 systemctl restart pure-ftpd.service
108 '') + (lib.optionalString proftpd-enabled ''
109 systemctl restart proftpd.service
110 '');
111 extraDomainNames = [ "ftp.immae.eu" ];
112 };
113
114 networking = {
115 firewall = {
116 allowedTCPPorts = [ 21 115 ];
117 allowedTCPPortRanges = [ { from = 40000; to = 50000; } ];
118 };
119 };
120
121 users.users.ftp = {
122 uid = config.ids.uids.ftp; # 8
123 group = "ftp";
124 description = "Anonymous FTP user";
125 home = "/homeless-shelter";
126 extraGroups = [ "keys" ];
127 };
128
129 users.groups.ftp.gid = config.ids.gids.ftp;
130
131 system.activationScripts.ftp = ''
132 install -m 0755 -o ftp -g ftp -d /var/lib/ftp
133 '' + (lib.optionalString proftpd-enabled ''
134 install -m 0755 -o nobody -g nogroup -d /var/lib/proftpd/authorized_keys
135 '');
136
137 secrets.keys."pure-ftpd-ldap" = lib.mkIf pure-ftpd-enabled {
138 permissions = "0400";
139 user = "ftp";
140 group = "ftp";
141 text = ''
142 LDAPServer ${config.myEnv.ftp.ldap.host}
143 LDAPPort 389
144 LDAPUseTLS True
145 LDAPBaseDN ${config.myEnv.ftp.ldap.base}
146 LDAPBindDN ${config.myEnv.ftp.ldap.dn}
147 LDAPBindPW ${config.myEnv.ftp.ldap.password}
148 LDAPDefaultUID 500
149 LDAPForceDefaultUID False
150 LDAPDefaultGID 100
151 LDAPForceDefaultGID False
152 LDAPFilter ${config.myEnv.ftp.ldap.pure-ftpd_filter}
153
154 LDAPAuthMethod BIND
155
156 # Pas de possibilite de donner l'Uid/Gid !
157 # Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid
158 LDAPHomeDir immaeFtpDirectory
159 '';
160 };
161 secrets.keys."proftpd-ldap.conf" = lib.mkIf proftpd-enabled {
162 permissions = "0400";
163 user = "ftp";
164 group = "ftp";
165 text = ''
166 LDAPServer ldaps://${config.myEnv.ftp.ldap.host}:636/??sub
167 LDAPUseTLS on
168 LDAPAuthBinds on
169 LDAPBindDN "${config.myEnv.ftp.ldap.dn}" "${config.myEnv.ftp.ldap.password}"
170 LDAPSearchScope subtree
171 LDAPAuthBinds on
172 LDAPDefaultGID 100
173 LDAPDefaultUID 500
174 LDAPForceDefaultUID off
175 LDAPForceDefaultGID off
176 LDAPAttr gidNumber immaeFtpGid
177 LDAPAttr uidNumber immaeFtpUid
178 LDAPAttr homeDirectory immaeFtpDirectory
179 LDAPUsers "${config.myEnv.ftp.ldap.base}" "${config.myEnv.ftp.ldap.proftpd_filter}"
180 LDAPGroups "${config.myEnv.ftp.ldap.base}"
181 '';
182 };
183
184 services.filesWatcher.pure-ftpd = lib.mkIf pure-ftpd-enabled {
185 restart = true;
186 paths = [ config.secrets.fullPaths."pure-ftpd-ldap" ];
187 };
188 services.filesWatcher.proftpd = lib.mkIf proftpd-enabled {
189 restart = true;
190 paths = [ config.secrets.fullPaths."proftpd-ldap.conf" ];
191 };
192
193 systemd.services.pure-ftpd = let
194 configFile = pkgs.writeText "pure-ftpd.conf" ''
195 PassivePortRange 40000 50000
196 Bind 42
197 ChrootEveryone yes
198 CreateHomeDir yes
199 BrokenClientsCompatibility yes
200 MaxClientsNumber 50
201 Daemonize yes
202 MaxClientsPerIP 8
203 VerboseLog no
204 DisplayDotFiles yes
205 AnonymousOnly no
206 NoAnonymous no
207 SyslogFacility ftp
208 DontResolve yes
209 MaxIdleTime 15
210 LDAPConfigFile ${config.secrets.fullPaths."pure-ftpd-ldap"}
211 LimitRecursion 10000 8
212 AnonymousCanCreateDirs no
213 MaxLoad 4
214 AntiWarez yes
215 Umask 133:022
216 # ftp
217 MinUID 8
218 AllowUserFXP no
219 AllowAnonymousFXP no
220 ProhibitDotFilesWrite no
221 ProhibitDotFilesRead no
222 AutoRename no
223 AnonymousCantUpload no
224 MaxDiskUsage 99
225 CustomerProof yes
226 TLS 1
227 CertFile ${config.security.acme.certs.ftp.directory}/full.pem
228 '';
229 in lib.mkIf pure-ftpd-enabled {
230 description = "Pure-FTPd server";
231 wantedBy = [ "multi-user.target" ];
232 after = [ "network.target" ];
233
234 serviceConfig.ExecStart = "${package}/bin/pure-ftpd ${configFile}";
235 serviceConfig.Type = "forking";
236 serviceConfig.PIDFile = "/run/pure-ftpd.pid";
237 };
238
239 systemd.services.proftpd = let
240 configFile = pkgs.writeText "proftpd.conf" ''
241 ServerName "ProFTPD"
242 ServerType standalone
243 DefaultServer on
244
245 Port 21
246 UseIPv6 on
247 Umask 022
248 MaxInstances 30
249 MaxClients 50
250 MaxClientsPerHost 8
251
252 # Set the user and group under which the server will run.
253 User ftp
254 Group ftp
255
256 CreateHome on
257 DefaultRoot ~
258
259 AllowOverwrite on
260
261 TLSEngine on
262 TLSRequired off
263 TLSProtocol TLSv1.1 TLSv1.2 TLSv1.3
264
265 TLSCertificateChainFile ${config.security.acme.certs.ftp.directory}/fullchain.pem
266 TLSECCertificateFile ${config.security.acme.certs.ftp.directory}/cert.pem
267 TLSECCertificateKeyFile ${config.security.acme.certs.ftp.directory}/key.pem
268 TLSRenegotiate none
269 PidFile /run/proftpd/proftpd.pid
270
271 ScoreboardFile /run/proftpd/proftpd.scoreboard
272
273 PassivePorts 40000 50000
274 #DebugLevel 10
275 Include ${config.secrets.fullPaths."proftpd-ldap.conf"}
276
277 RequireValidShell off
278
279 # Bar use of SITE CHMOD by default
280 <Limit SITE_CHMOD>
281 DenyAll
282 </Limit>
283
284 <VirtualHost 0.0.0.0>
285 Umask 022
286 Port 115
287 SFTPEngine on
288 CreateHome on
289 DefaultRoot ~
290
291 AllowOverwrite on
292
293 SFTPHostKey /etc/ssh/ssh_host_ed25519_key
294 SFTPHostKey /etc/ssh/ssh_host_rsa_key
295 Include ${config.secrets.fullPaths."proftpd-ldap.conf"}
296 RequireValidShell off
297 SFTPAuthorizedUserKeys file:/var/lib/proftpd/authorized_keys/%u
298 SFTPAuthMethods password publickey
299
300 SFTPOptions IgnoreSFTPSetOwners
301 AllowChrootSymlinks off
302 </VirtualHost>
303 '';
304 in lib.mkIf proftpd-enabled {
305 description = "ProFTPD server";
306 wantedBy = [ "multi-user.target" ];
307 after = [ "network.target" ];
308
309 serviceConfig.ExecStart = "${pkgs.proftpd}/bin/proftpd -c ${configFile}";
310 serviceConfig.Type = "forking";
311 serviceConfig.PIDFile = "/run/proftpd/proftpd.pid";
312 serviceConfig.RuntimeDirectory = "proftpd";
313 };
314
315 services.cron.systemCronJobs = lib.mkIf proftpd-enabled [
316 "*/2 * * * * nobody ${./ftp_sync.sh}"
317 ];
318 };
319
320 }