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