]> git.immae.eu Git - perso/Immae/Config/Nix.git/blame - modules/private/ftp.nix
Fix rsync backup failures
[perso/Immae/Config/Nix.git] / modules / private / ftp.nix
CommitLineData
ab8f306d 1{ lib, pkgs, config, ... }:
fe696f35
IB
2let
3 package = pkgs.pure-ftpd.override { ldapFtpId = "immaeFtp"; };
fcbdf67a
IB
4 pure-ftpd-enabled = config.myServices.ftp.pure-ftpd.enable;
5 proftpd-enabled = config.myServices.ftp.proftpd.enable;
fe696f35 6in
439049e5
IB
7{
8 options = {
fcbdf67a
IB
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 {
439049e5
IB
17 type = lib.types.bool;
18 default = false;
19 description = ''
20 Whether to enable pure-ftpd.
21 '';
22 };
fcbdf67a
IB
23 myServices.ftp.proftpd.enable = lib.mkOption {
24 type = lib.types.bool;
25 default = true;
26 description = ''
27 Whether to enable proftpd.
28 '';
29 };
439049e5
IB
30 };
31
fcbdf67a 32 config = lib.mkIf config.myServices.ftp.enable {
120bcf4d
IB
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 #};
5400b9b6 101 security.acme.certs."ftp" = config.myServices.certificates.certConfig // {
439049e5 102 domain = "eldiron.immae.eu";
e34b3079
IB
103 # FIXME: make it global
104 extraLegoRunFlags = ["--preferred-chain" "ISRG Root X1"];
105 extraLegoRenewFlags = ["--preferred-chain" "ISRG Root X1"];
fcbdf67a 106 postRun = (lib.optionalString pure-ftpd-enabled ''
740f9843 107 systemctl restart pure-ftpd.service
fcbdf67a
IB
108 '') + (lib.optionalString proftpd-enabled ''
109 systemctl restart proftpd.service
110 '');
e34b3079 111 extraDomainNames = [ "ftp.immae.eu" ];
439049e5
IB
112 };
113
439049e5
IB
114 networking = {
115 firewall = {
fcbdf67a 116 allowedTCPPorts = [ 21 115 ];
439049e5
IB
117 allowedTCPPortRanges = [ { from = 40000; to = 50000; } ];
118 };
119 };
120
258dd18b
IB
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 };
439049e5
IB
128
129 users.groups.ftp.gid = config.ids.gids.ftp;
130
fcbdf67a 131 system.activationScripts.ftp = ''
439049e5 132 install -m 0755 -o ftp -g ftp -d /var/lib/ftp
fcbdf67a
IB
133 '' + (lib.optionalString proftpd-enabled ''
134 install -m 0755 -o nobody -g nogroup -d /var/lib/proftpd/authorized_keys
135 '');
439049e5 136
fcbdf67a 137 secrets.keys."pure-ftpd-ldap" = lib.mkIf pure-ftpd-enabled {
926a4007
IB
138 permissions = "0400";
139 user = "ftp";
140 group = "ftp";
141 text = ''
ab8f306d 142 LDAPServer ${config.myEnv.ftp.ldap.host}
439049e5
IB
143 LDAPPort 389
144 LDAPUseTLS True
ab8f306d
IB
145 LDAPBaseDN ${config.myEnv.ftp.ldap.base}
146 LDAPBindDN ${config.myEnv.ftp.ldap.dn}
147 LDAPBindPW ${config.myEnv.ftp.ldap.password}
439049e5
IB
148 LDAPDefaultUID 500
149 LDAPForceDefaultUID False
150 LDAPDefaultGID 100
151 LDAPForceDefaultGID False
fcbdf67a 152 LDAPFilter ${config.myEnv.ftp.ldap.pure-ftpd_filter}
439049e5
IB
153
154 LDAPAuthMethod BIND
155
926a4007
IB
156 # Pas de possibilite de donner l'Uid/Gid !
157 # Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid
439049e5
IB
158 LDAPHomeDir immaeFtpDirectory
159 '';
4c4652aa 160 };
fcbdf67a
IB
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 };
926a4007 183
fcbdf67a 184 services.filesWatcher.pure-ftpd = lib.mkIf pure-ftpd-enabled {
17f6eae9 185 restart = true;
da30ae4f 186 paths = [ config.secrets.fullPaths."pure-ftpd-ldap" ];
17f6eae9 187 };
fcbdf67a
IB
188 services.filesWatcher.proftpd = lib.mkIf proftpd-enabled {
189 restart = true;
190 paths = [ config.secrets.fullPaths."proftpd-ldap.conf" ];
191 };
17f6eae9 192
926a4007 193 systemd.services.pure-ftpd = let
439049e5
IB
194 configFile = pkgs.writeText "pure-ftpd.conf" ''
195 PassivePortRange 40000 50000
fcbdf67a 196 Bind 42
439049e5
IB
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
da30ae4f 210 LDAPConfigFile ${config.secrets.fullPaths."pure-ftpd-ldap"}
439049e5
IB
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
5400b9b6 227 CertFile ${config.security.acme.certs.ftp.directory}/full.pem
439049e5 228 '';
fcbdf67a 229 in lib.mkIf pure-ftpd-enabled {
439049e5
IB
230 description = "Pure-FTPd server";
231 wantedBy = [ "multi-user.target" ];
232 after = [ "network.target" ];
233
fe696f35 234 serviceConfig.ExecStart = "${package}/bin/pure-ftpd ${configFile}";
439049e5
IB
235 serviceConfig.Type = "forking";
236 serviceConfig.PIDFile = "/run/pure-ftpd.pid";
237 };
fcbdf67a
IB
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
87e1ff0f
IB
299
300 SFTPOptions IgnoreSFTPSetOwners
343e326e 301 AllowChrootSymlinks off
fcbdf67a
IB
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 ];
439049e5
IB
318 };
319
320}