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