blob: cae25c1dc5fdc2828efa59701213e15ffcba4f3f (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
{ lib, pkgs, config, ... }:
let
package = pkgs.pure-ftpd.override { ldapFtpId = "immaeFtp"; };
pure-ftpd-enabled = config.myServices.ftp.pure-ftpd.enable;
proftpd-enabled = config.myServices.ftp.proftpd.enable;
in
{
options = {
myServices.ftp.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to enable ftp.
'';
};
myServices.ftp.pure-ftpd.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to enable pure-ftpd.
'';
};
myServices.ftp.proftpd.enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to enable proftpd.
'';
};
};
config = lib.mkIf config.myServices.ftp.enable {
security.acme.certs."ftp" = config.myServices.certificates.certConfig // {
domain = "eldiron.immae.eu";
postRun = (lib.optionalString pure-ftpd-enabled ''
systemctl restart pure-ftpd.service
'') + (lib.optionalString proftpd-enabled ''
systemctl restart proftpd.service
'');
extraDomains = { "ftp.immae.eu" = null; };
};
networking = {
firewall = {
allowedTCPPorts = [ 21 115 ];
allowedTCPPortRanges = [ { from = 40000; to = 50000; } ];
};
};
users.users.ftp = {
uid = config.ids.uids.ftp; # 8
group = "ftp";
description = "Anonymous FTP user";
home = "/homeless-shelter";
extraGroups = [ "keys" ];
};
users.groups.ftp.gid = config.ids.gids.ftp;
system.activationScripts.ftp = ''
install -m 0755 -o ftp -g ftp -d /var/lib/ftp
'' + (lib.optionalString proftpd-enabled ''
install -m 0755 -o nobody -g nogroup -d /var/lib/proftpd/authorized_keys
'');
secrets.keys."pure-ftpd-ldap" = lib.mkIf pure-ftpd-enabled {
permissions = "0400";
user = "ftp";
group = "ftp";
text = ''
LDAPServer ${config.myEnv.ftp.ldap.host}
LDAPPort 389
LDAPUseTLS True
LDAPBaseDN ${config.myEnv.ftp.ldap.base}
LDAPBindDN ${config.myEnv.ftp.ldap.dn}
LDAPBindPW ${config.myEnv.ftp.ldap.password}
LDAPDefaultUID 500
LDAPForceDefaultUID False
LDAPDefaultGID 100
LDAPForceDefaultGID False
LDAPFilter ${config.myEnv.ftp.ldap.pure-ftpd_filter}
LDAPAuthMethod BIND
# Pas de possibilite de donner l'Uid/Gid !
# Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid
LDAPHomeDir immaeFtpDirectory
'';
};
secrets.keys."proftpd-ldap.conf" = lib.mkIf proftpd-enabled {
permissions = "0400";
user = "ftp";
group = "ftp";
text = ''
LDAPServer ldaps://${config.myEnv.ftp.ldap.host}:636/??sub
LDAPUseTLS on
LDAPAuthBinds on
LDAPBindDN "${config.myEnv.ftp.ldap.dn}" "${config.myEnv.ftp.ldap.password}"
LDAPSearchScope subtree
LDAPAuthBinds on
LDAPDefaultGID 100
LDAPDefaultUID 500
LDAPForceDefaultUID off
LDAPForceDefaultGID off
LDAPAttr gidNumber immaeFtpGid
LDAPAttr uidNumber immaeFtpUid
LDAPAttr homeDirectory immaeFtpDirectory
LDAPUsers "${config.myEnv.ftp.ldap.base}" "${config.myEnv.ftp.ldap.proftpd_filter}"
LDAPGroups "${config.myEnv.ftp.ldap.base}"
'';
};
services.filesWatcher.pure-ftpd = lib.mkIf pure-ftpd-enabled {
restart = true;
paths = [ config.secrets.fullPaths."pure-ftpd-ldap" ];
};
services.filesWatcher.proftpd = lib.mkIf proftpd-enabled {
restart = true;
paths = [ config.secrets.fullPaths."proftpd-ldap.conf" ];
};
systemd.services.pure-ftpd = let
configFile = pkgs.writeText "pure-ftpd.conf" ''
PassivePortRange 40000 50000
Bind 42
ChrootEveryone yes
CreateHomeDir yes
BrokenClientsCompatibility yes
MaxClientsNumber 50
Daemonize yes
MaxClientsPerIP 8
VerboseLog no
DisplayDotFiles yes
AnonymousOnly no
NoAnonymous no
SyslogFacility ftp
DontResolve yes
MaxIdleTime 15
LDAPConfigFile ${config.secrets.fullPaths."pure-ftpd-ldap"}
LimitRecursion 10000 8
AnonymousCanCreateDirs no
MaxLoad 4
AntiWarez yes
Umask 133:022
# ftp
MinUID 8
AllowUserFXP no
AllowAnonymousFXP no
ProhibitDotFilesWrite no
ProhibitDotFilesRead no
AutoRename no
AnonymousCantUpload no
MaxDiskUsage 99
CustomerProof yes
TLS 1
CertFile ${config.security.acme.certs.ftp.directory}/full.pem
'';
in lib.mkIf pure-ftpd-enabled {
description = "Pure-FTPd server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig.ExecStart = "${package}/bin/pure-ftpd ${configFile}";
serviceConfig.Type = "forking";
serviceConfig.PIDFile = "/run/pure-ftpd.pid";
};
systemd.services.proftpd = let
configFile = pkgs.writeText "proftpd.conf" ''
ServerName "ProFTPD"
ServerType standalone
DefaultServer on
Port 21
UseIPv6 on
Umask 022
MaxInstances 30
MaxClients 50
MaxClientsPerHost 8
# Set the user and group under which the server will run.
User ftp
Group ftp
CreateHome on
DefaultRoot ~
AllowOverwrite on
TLSEngine on
TLSRequired off
TLSProtocol TLSv1.1 TLSv1.2 TLSv1.3
TLSCertificateChainFile ${config.security.acme.certs.ftp.directory}/fullchain.pem
TLSECCertificateFile ${config.security.acme.certs.ftp.directory}/cert.pem
TLSECCertificateKeyFile ${config.security.acme.certs.ftp.directory}/key.pem
TLSRenegotiate none
PidFile /run/proftpd/proftpd.pid
ScoreboardFile /run/proftpd/proftpd.scoreboard
PassivePorts 40000 50000
#DebugLevel 10
Include ${config.secrets.fullPaths."proftpd-ldap.conf"}
RequireValidShell off
# Bar use of SITE CHMOD by default
<Limit SITE_CHMOD>
DenyAll
</Limit>
<VirtualHost 0.0.0.0>
Umask 022
Port 115
SFTPEngine on
CreateHome on
DefaultRoot ~
AllowOverwrite on
SFTPHostKey /etc/ssh/ssh_host_ed25519_key
SFTPHostKey /etc/ssh/ssh_host_rsa_key
Include ${config.secrets.fullPaths."proftpd-ldap.conf"}
RequireValidShell off
SFTPAuthorizedUserKeys file:/var/lib/proftpd/authorized_keys/%u
SFTPAuthMethods password publickey
SFTPOptions IgnoreSFTPSetOwners
</VirtualHost>
'';
in lib.mkIf proftpd-enabled {
description = "ProFTPD server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig.ExecStart = "${pkgs.proftpd}/bin/proftpd -c ${configFile}";
serviceConfig.Type = "forking";
serviceConfig.PIDFile = "/run/proftpd/proftpd.pid";
serviceConfig.RuntimeDirectory = "proftpd";
};
services.cron.systemCronJobs = lib.mkIf proftpd-enabled [
"*/2 * * * * nobody ${./ftp_sync.sh}"
];
};
}
|