aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2020-10-24 12:30:42 +0200
committerIsmaël Bouya <ismael.bouya@normalesup.org>2020-10-24 12:30:42 +0200
commit75489e72e379af8aeac64bc4967717d9ae776ff0 (patch)
tree1d028e5a9ab73d096e48e3f177eb60b4f73486bd
parente43fdf341072e4a0150324196fc7af8f383860ec (diff)
downloadNix-75489e72e379af8aeac64bc4967717d9ae776ff0.tar.gz
Nix-75489e72e379af8aeac64bc4967717d9ae776ff0.tar.zst
Nix-75489e72e379af8aeac64bc4967717d9ae776ff0.zip
Add quatresaisons server
-rw-r--r--Makefile4
-rw-r--r--modules/private/environment.nix1
-rw-r--r--modules/private/system/quatresaisons.nix449
-rw-r--r--modules/private/system/quatresaisons/databases.nix146
-rw-r--r--modules/private/system/quatresaisons/landing.yml32
-rw-r--r--modules/private/system/quatresaisons/landing_4c.yml24
-rw-r--r--modules/private/system/quatresaisons/nextcloud.nix141
-rw-r--r--nixops/Makefile3
-rw-r--r--nixops/default.nix2
m---------nixops/secrets0
10 files changed, 800 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 9c12ff4..466b63a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
1subrecipes = setup nix-info edit_env 1subrecipes = setup nix-info edit_env
2subrecipes += ssh-eldiron ssh-backup-2 ssh-monitoring-1 2subrecipes += ssh-eldiron ssh-backup-2 ssh-monitoring-1 ssh-4c
3subrecipes += debug build upload deploy deploy-reboot 3subrecipes += debug build dry-run upload deploy deploy-reboot
4subrecipes += list-generations delete-generations cleanup 4subrecipes += list-generations delete-generations cleanup
5${subrecipes}: 5${subrecipes}:
6 @$(MAKE) --no-print-directory -C nixops/ $@ 6 @$(MAKE) --no-print-directory -C nixops/ $@
diff --git a/modules/private/environment.nix b/modules/private/environment.nix
index a8799d2..e79feec 100644
--- a/modules/private/environment.nix
+++ b/modules/private/environment.nix
@@ -1171,6 +1171,7 @@ in
1171 }; 1171 };
1172 }; 1172 };
1173 }; 1173 };
1174 serverSpecific = mkOption { type = attrsOf unspecified; description = "Server specific configuration"; };
1174 websites = mkOption { 1175 websites = mkOption {
1175 description = "Websites configurations"; 1176 description = "Websites configurations";
1176 type = submodule { 1177 type = submodule {
diff --git a/modules/private/system/quatresaisons.nix b/modules/private/system/quatresaisons.nix
new file mode 100644
index 0000000..395b604
--- /dev/null
+++ b/modules/private/system/quatresaisons.nix
@@ -0,0 +1,449 @@
1{ privateFiles }:
2{ config, pkgs, lib, ... }:
3let
4 serverSpecificConfig = config.myEnv.serverSpecific.quatresaisons;
5 yarnModules = pkgs.yarn2nix-moretea.mkYarnModules rec {
6 name = "landing";
7 pname = name;
8 version = "v1.0.0";
9 packageJSON = "${pkgs.sources.webapps-landing}/package.json";
10 yarnLock = "${pkgs.sources.webapps-landing}/yarn.lock";
11 yarnNix = ../websites/tools/tools/landing/yarn-packages.nix;
12 };
13 toLanding = landingConfig: pkgs.stdenv.mkDerivation rec {
14 pname = "landing";
15 version = "v1.0.0";
16 src = pkgs.sources.webapps-landing;
17
18 buildInputs = [ yarnModules pkgs.yarn2nix-moretea.yarn ];
19 configurePhase = ''
20 ln -s ${yarnModules}/node_modules .
21 '';
22 buildPhase = ''
23 yarn build
24 '';
25 installPhase = ''
26 cp -a dist $out
27 cp -f ${landingConfig} $out/config.yml
28 ln -s service-worker.js $out/worker.js
29 '';
30 };
31 normalUsers = serverSpecificConfig.users;
32 sponsoredUser = pkgs.writeScriptBin "sponsored_user" ''
33 #!/usr/bin/env bash
34
35 set -euo pipefail
36 [ -z "''${SUDO_USER+x}" ] && echo "Must be run with sudo" && exit 1
37
38 mygroup=$(id -ng $SUDO_USER)
39
40 sponsored=$(getent group $mygroup | cut -d':' -f4)
41
42 echo "Sponsored users: ''${sponsored:-<none>}"
43
44 log () {
45 touch /var/log/sponsored_users
46 chmod go-rwx /var/log/sponsored_users
47 echo "`date` $mygroup $1" | LANG=C cat -v | tr '\012' ' ' | sed 's:$:\x0a:' >> /var/log/sponsored_users
48 }
49
50 create_user () {
51 log "creates $1: $2"
52 useradd -m -G users,$mygroup -g $mygroup -p '!' "$1"
53 touch /var/lib/nixos/sponsored_users
54 chmod go-rwx /var/lib/nixos/sponsored_users
55 echo "$mygroup $1 $2" >> /var/lib/nixos/sponsored_users
56 (${pkgs.openldap}/bin/ldapadd -c -D cn=root,dc=salle-s,dc=org \
57 -y /var/secrets/ldap/sync_password 2>/dev/null >/dev/null || true) <<EOF
58 dn: uid=$1,uid=$mygroup,ou=users,dc=salle-s,dc=org
59 objectClass: inetOrgPerson
60 cn: $1
61 description:: $(echo -n "$2" | base64)
62 sn: $1
63 uid: $1
64 EOF
65 while ! passwd "$1"; do
66 echo "please give an initial password"
67 done
68 }
69
70 delete_user () {
71 IFS=",";
72 for u in $sponsored; do
73 if [ "$u" = "$1" ]; then
74 log "deletes $1"
75 userdel -r "$1"
76 sed -i -e "/^$mygroup $1/d" /var/lib/nixos/sponsored_users
77 ${pkgs.openldap}/bin/ldapdelete -D cn=root,dc=salle-s,dc=org \
78 -y /var/secrets/ldap/sync_password \
79 "uid=$1,uid=$mygroup,ou=users,dc=salle-s,dc=org"
80 echo "deleted"
81 exit 0
82 fi
83 done
84
85 echo "User does not exist or does not belong to you";
86 exit 1
87 }
88
89 reset_password () {
90 IFS=",";
91 for u in $sponsored; do
92 if [ "$u" = "$1" ]; then
93 log "resets password for $1"
94 passwd "$1"
95 exit 0
96 fi
97 done
98
99 echo "User does not exist or does not belong to you";
100 exit 1
101 }
102
103 reset_ldap_password () {
104 if [ "$1" = "$mygroup" ]; then
105 log "resets web password"
106 ${pkgs.openldap}/bin/ldappasswd -D cn=root,dc=salle-s,dc=org \
107 -y /var/secrets/ldap/sync_password \
108 -S "uid=$mygroup,ou=users,dc=salle-s,dc=org"
109 else
110 IFS=",";
111 for u in $sponsored; do
112 if [ "$u" = "$1" ]; then
113 log "resets web password of $1"
114 ${pkgs.openldap}/bin/ldappasswd -D cn=root,dc=salle-s,dc=org \
115 -y /var/secrets/ldap/sync_password \
116 -S "uid=$1,uid=$mygroup,ou=users,dc=salle-s,dc=org"
117 exit 0
118 fi
119 done
120
121 echo "User does not exist or does not belong to you";
122 exit 1
123 fi
124 }
125
126 show_help () {
127 echo "sponsored_users create username realname"
128 echo " create a new sub-user attached to your account"
129 echo "sponsored_users (delete|reset_password) username"
130 echo " delete a sub-user attached to your account or reset his password"
131 echo "sponsored_users reset_ldap_password username"
132 echo " reset the web password of a sub-user or yourself"
133 }
134
135 [ -z "''${1+x}" -o -z "''${2+x}" ] && { show_help ; exit 0; }
136 action="$1"
137 username="$2"
138 shift
139 shift
140
141 case "$action" in
142 create)
143 [ -z "''${1+x}" ] && { show_help ; echo "Conformément à la charte https://4c.salle-s.org/charte veuillez préciser le nom réel du futur utilisateur du compte $username, juste pour root." ; exit 1; }
144 create_user "$username" "$*";
145 ;;
146 delete)
147 delete_user "$username";
148 ;;
149 reset_password)
150 reset_password "$username";
151 ;;
152 reset_ldap_password)
153 reset_ldap_password "$username";
154 ;;
155 *)
156 show_help
157 ;;
158 esac
159 '';
160in
161{
162 deployment = {
163 targetUser = "root";
164 targetHost = config.hostEnv.ips.main.ip4;
165 substituteOnDestination = true;
166 };
167
168 programs.ssh.package = pkgs.openssh.overrideAttrs(old: {
169 PATH_PASSWD_PROG = "/run/wrappers/bin/passwd";
170 buildFlags = [ "SSH_KEYSIGN=/run/wrappers/bin/ssh-keysign" ];
171 });
172
173 imports = builtins.attrValues (import ../..) ++
174 [ ./quatresaisons/nextcloud.nix ./quatresaisons/databases.nix ];
175
176 myEnv = import "${privateFiles}/environment.nix" // { inherit privateFiles; };
177
178 fileSystems = {
179 "/" = { device = "/dev/disk/by-uuid/865931b4-c5cc-439f-8e42-8072c7a30634"; fsType = "ext4"; };
180 "/home" = { device = "/dev/disk/by-uuid/76020bc4-5b88-464c-8952-9a59072c597f"; fsType = "ext4"; neededForBoot = true; };
181 "/boot" = { device = "/dev/disk/by-uuid/0fb8421a-61e5-4ed5-a795-4dd3a9b2152a"; fsType = "ext4"; };
182 "/var/lib" = { device = "/home/var_lib"; fsType = "none"; options = [ "defaults,bind" ]; };
183 };
184 powerManagement.cpuFreqGovernor = "powersave";
185 hardware.enableRedistributableFirmware = true;
186
187 boot.initrd.availableKernelModules = [ "ahci" "megaraid_sas" "sd_mod" ];
188 boot.initrd.kernelModules = [ "dm-snapshot" ];
189 boot.kernelModules = [ "kvm-intel" ];
190
191 boot.loader.grub.enable = true;
192 boot.loader.grub.version = 2;
193 boot.loader.grub.device = "/dev/sda";
194
195 networking.firewall.enable = false;
196 networking.firewall.allowedTCPPorts = [ 80 443 ];
197 networking.useDHCP = false;
198 networking.interfaces.eth0.useDHCP = true;
199 networking.interfaces.eth0.ipv6.addresses = [
200 { address = pkgs.lib.head config.hostEnv.ips.main.ip6; prefixLength = 64; }
201 ];
202 networking.defaultGateway6 = { address = "fe80::1"; interface = "eth0"; };
203 services.udev.extraRules = ''
204 ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="c8:60:00:8b:2f:f0", NAME="eth0"
205 '';
206 security.pam.services.chage.text = ''
207 auth sufficient pam_rootok.so
208 auth required pam_unix.so
209 account required pam_unix.so
210 session required pam_unix.so
211 password required pam_permit.so
212 '';
213 security.pam.services.sshd.makeHomeDir = true;
214 security.pam.services.passwd_default = {};
215 security.pam.services.passwd.text = ''
216 password required pam_cracklib.so enforce_for_root difok=2 minlen=8 dcredit=2 ocredit=2 retry=3
217 '' + config.security.pam.services.passwd_default.text;
218
219 system.activationScripts.ldapSync = {
220 deps = [ "secrets" "users" ];
221 text =
222 let
223 com = "-D cn=root,dc=salle-s,dc=org -y /var/secrets/ldap/sync_password";
224 in ''
225 # Add users
226 ${pkgs.openldap}/bin/ldapadd -c ${com} -f /var/secrets/ldap/ldaptree.ldif 2>/dev/null >/dev/null || true
227
228 # Remove obsolete users
229 ${pkgs.openldap}/bin/ldapsearch -LLL ${com} -s one -b "ou=users,dc=salle-s,dc=org" "uid" |\
230 grep "^uid" | ${pkgs.gnused}/bin/sed -e "s/uid: //" | while read ldapuser; do
231
232 for user in ${builtins.concatStringsSep " " (builtins.attrNames normalUsers)}; do
233 if [ "$user" = "$ldapuser" ]; then
234 continue 2
235 fi
236 done
237 ${pkgs.openldap}/bin/ldapdelete -r ${com} uid=$ldapuser,ou=users,dc=salle-s,dc=org
238 done
239
240 # Subusers
241 if [ -f /var/lib/nixos/sponsored_users ]; then
242 cat /var/lib/nixos/sponsored_users | while read mainUser subUser name; do
243 (${pkgs.openldap}/bin/ldapadd -c ${com} 2>/dev/null >/dev/null || true) <<EOF
244 dn: uid=$subUser,uid=$mainUser,ou=users,dc=salle-s,dc=org
245 objectClass: inetOrgPerson
246 cn: $subUser
247 description:: $(echo -n "$name" | base64)
248 sn: $subUser
249 uid: $subUser
250 EOF
251 done
252 fi
253 '';
254 };
255
256 secrets.keys = [
257 {
258 dest = "ldap/sync_password";
259 permissions = "0400";
260 text = serverSpecificConfig.ldap_sync_password;
261 }
262 {
263 dest = "ldap/ldaptree.ldif";
264 permissions = "0400";
265 text = serverSpecificConfig.ldap_service_users
266 + (builtins.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
267 dn: uid=${n},ou=users,dc=salle-s,dc=org
268 objectClass: inetOrgPerson
269 cn: ${n}
270 description: ${v._meta.name or n} ${v._meta.email}
271 sn: ${n}
272 uid: ${n}
273 '') normalUsers));
274 }
275 ];
276
277 myServices.certificates.enable = true;
278 users.mutableUsers = true;
279 system.stateVersion = "21.03";
280 programs.zsh.enable = true;
281
282 users.motd = ''
283 Bienvenue sur quatresaisons.salle-s.org !
284
285 * Charte :
286 https://4c.salle-s.org/charte
287 * Gérer les utilisateurs unix additionnels :
288 sudo sponsored_user -h
289 * Applications web :
290 * tableau de bord : https://4c.salle-s.org/
291 * nextcloud : https://nextcloud.4c.salle-s.org/
292 '';
293
294 users.groups =
295 lib.mapAttrs (n: v: { gid = v.uid; }) normalUsers
296 // { wwwrun = { gid = config.ids.gids.wwwrun; }; };
297 users.users =
298 let
299 defaultNormal = n: {
300 group = n;
301 extraGroups = [ "users" ];
302 isNormalUser = true;
303 };
304 in
305 lib.mapAttrs (n: v: defaultNormal n // (lib.filterAttrs (k: _: k != "_meta") v)) normalUsers
306 // {
307 sponsored-separator = {
308 uid = 10000;
309 group = "users";
310 home = "/var/empty";
311 extraGroups = [];
312 isNormalUser = true;
313 createHome = false;
314 };
315 wwwrun = {
316 group = "wwwrun";
317 description = "Apache httpd user";
318 uid = config.ids.uids.wwwrun;
319 extraGroups = [ "keys" ];
320 };
321 };
322
323 system.activationScripts.usersPost = {
324 deps = [ "users" "groups" ];
325 text = builtins.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
326 if getent shadow "${n}" | grep -q '^${n}:${v.initialHashedPassword or "!"}:1'; then
327 chage -d 0 "${n}"
328 [ '${v.initialHashedPassword or "!"}' = '!' ] && passwd -d "${n}"
329 fi
330 '') normalUsers);
331 };
332 security.sudo.extraRules = [
333 {
334 commands = [
335 { command = "${sponsoredUser}/bin/sponsored_user"; options = [ "NOPASSWD" ]; }
336 ];
337 users = builtins.attrNames normalUsers;
338 runAs = "root";
339 }
340 ];
341
342 environment.systemPackages = [
343 sponsoredUser
344 pkgs.git
345 pkgs.vim
346 pkgs.rsync
347 pkgs.strace
348 pkgs.home-manager
349 pkgs.telnet
350 pkgs.htop
351 pkgs.iftop
352 pkgs.bind.dnsutils
353 pkgs.httpie
354 pkgs.iotop
355 pkgs.whois
356 pkgs.ngrep
357 pkgs.tcpdump
358 pkgs.tshark
359 pkgs.tcpflow
360 pkgs.nmap
361 pkgs.p0f
362 pkgs.socat
363 pkgs.lsof
364 pkgs.psmisc
365 pkgs.openssl
366 pkgs.wget
367 pkgs.pv
368 pkgs.smartmontools
369 ];
370
371 services.websites.env.production = {
372 enable = true;
373 adminAddr = "httpd@immae.eu";
374 httpdName = "Prod";
375 modules = [ "http2" "deflate" "filter" ];
376 extraConfig = [
377 ''
378 LogFormat "%{Host}i:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedVhost
379 Protocols h2 http/1.1
380 AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
381 '' ];
382 ips =
383 let ips = config.hostEnv.ips.main;
384 in [ips.ip4] ++ (ips.ip6 or []);
385
386 fallbackVhost = {
387 certName = "quatresaisons";
388 hosts = [ "quatresaisons.immae.eu" ];
389 root = pkgs.runCommand "empty" {} "mkdir $out && touch $out/index.html";
390 extraConfig = [ "DirectoryIndex index.html" ];
391 };
392 vhostConfs.salle-s = {
393 certName = "quatresaisons";
394 addToCerts = true;
395 hosts = [ "salle-s.org" ];
396 root = toLanding ./quatresaisons/landing.yml;
397 extraConfig = [
398 ''
399 <Directory ${toLanding ./quatresaisons/landing.yml}>
400 AllowOverride None
401 Require all granted
402 DirectoryIndex index.html
403 </Directory>
404 ''
405 ];
406 };
407 vhostConfs.tools = {
408 certName = "quatresaisons";
409 addToCerts = true;
410 hosts = [ "4c.salle-s.org" "quatresaisons.salle-s.org" "quatre-saisons.salle-s.org" ];
411 root = toLanding ./quatresaisons/landing_4c.yml;
412 extraConfig = [
413 ''
414 Alias /charte ${serverSpecificConfig.charte_path}
415 <Directory ${serverSpecificConfig.charte_path}>
416 AllowOverride None
417 Require all granted
418 DirectoryIndex index.html index.txt
419 </Directory>
420
421 <Directory ${toLanding ./quatresaisons/landing_4c.yml}>
422 AllowOverride None
423 Require all granted
424 DirectoryIndex index.html
425 </Directory>
426 ''
427 ];
428 };
429 };
430 system.activationScripts.httpd = ''
431 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php
432 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions
433 '';
434
435 services.phpfpm = {
436 phpOptions = ''
437 session.save_path = "/var/lib/php/sessions"
438 post_max_size = 20M
439 ; 15 days (seconds)
440 session.gc_maxlifetime = 1296000
441 ; 30 days (minutes)
442 session.cache_expire = 43200
443 '';
444 settings = {
445 log_level = "notice";
446 };
447 };
448
449}
diff --git a/modules/private/system/quatresaisons/databases.nix b/modules/private/system/quatresaisons/databases.nix
new file mode 100644
index 0000000..3491ae4
--- /dev/null
+++ b/modules/private/system/quatresaisons/databases.nix
@@ -0,0 +1,146 @@
1{ pkgs, config, lib, ... }:
2{
3 config = let
4 serverSpecificConfig = config.myEnv.serverSpecific.quatresaisons;
5 phpLdapAdmin = pkgs.webapps.phpldapadmin.override { config = "/var/secrets/webapps/tools-ldap"; };
6 in {
7 services.postgresql.enable = true;
8 services.postgresql.package = pkgs.postgresql_12;
9 secrets.keys = [
10 {
11 dest = "ldap/password";
12 permissions = "0400";
13 user = "openldap";
14 group = "openldap";
15 text = "rootpw ${serverSpecificConfig.ldap_root_pw}";
16 }
17 {
18 dest = "webapps/tools-ldap";
19 user = "wwwrun";
20 group = "wwwrun";
21 permissions = "0400";
22 text = ''
23 <?php
24 $config->custom->appearance['show_clear_password'] = true;
25 $config->custom->appearance['hide_template_warning'] = true;
26 $config->custom->appearance['theme'] = "tango";
27 $config->custom->appearance['minimalMode'] = false;
28 $config->custom->appearance['tree'] = 'AJAXTree';
29
30 $servers = new Datastore();
31
32 $servers->newServer('ldap_pla');
33 $servers->setValue('server','name','LDAP');
34 $servers->setValue('server','host','ldap://localhost');
35 $servers->setValue('login','auth_type','cookie');
36 $servers->setValue('login','bind_id','${serverSpecificConfig.ldap_phpldapadmin_dn}');
37 $servers->setValue('login','bind_pass','${serverSpecificConfig.ldap_phpldapadmin_password}');
38 $servers->setValue('appearance','pla_password_hash','ssha');
39 $servers->setValue('login','attr','uid');
40 $servers->setValue('login','fallback_dn',true);
41 '';
42 }
43 ];
44
45 users.users.openldap.extraGroups = [ "keys" ];
46 services.openldap = {
47 enable = true;
48 dataDir = "/var/lib/openldap";
49 urlList = [ "ldap://localhost" ];
50 logLevel = "none";
51 extraConfig = ''
52 pidfile /run/slapd/slapd.pid
53 argsfile /run/slapd/slapd.args
54
55 moduleload back_hdb
56 backend hdb
57 '';
58
59 extraDatabaseConfig = ''
60 moduleload memberof
61 overlay memberof
62
63 moduleload syncprov
64 overlay syncprov
65 syncprov-checkpoint 100 10
66
67 index objectClass eq
68 index uid pres,eq
69 #index uidMember pres,eq
70 index mail pres,sub,eq
71 index cn pres,sub,eq
72 index sn pres,sub,eq
73 index dc eq
74 index member eq
75 index memberOf eq
76
77 # No one must access that information except root
78 access to attrs=description
79 by * none
80
81 access to attrs=entry,uid filter="(uid=*)"
82 by dn.exact="${serverSpecificConfig.ldap_phpldapadmin_dn}" read
83 by * break
84
85 access to dn.subtree="ou=users,dc=salle-s,dc=org"
86 by dn.subtree="ou=services,dc=salle-s,dc=org" read
87 by * break
88
89 access to *
90 by self read
91 by anonymous auth
92 by * break
93 '';
94 rootpwFile = "${config.secrets.location}/ldap/password";
95 suffix = "dc=salle-s,dc=org";
96 rootdn = "cn=root,dc=salle-s,dc=org";
97 database = "hdb";
98 };
99
100 services.websites.env.production.modules = [ "proxy_fcgi" ];
101 services.websites.env.production.vhostConfs.tools.extraConfig = [
102 ''
103 Alias /ldap "${phpLdapAdmin}/htdocs"
104 <Directory "${phpLdapAdmin}/htdocs">
105 DirectoryIndex index.php
106 <FilesMatch "\.php$">
107 SetHandler "proxy:unix:${config.services.phpfpm.pools.ldap.socket}|fcgi://localhost"
108 </FilesMatch>
109
110 AllowOverride None
111 Require all granted
112 </Directory>
113 ''
114 ];
115 services.phpfpm.pools.ldap = {
116 user = "wwwrun";
117 group = "wwwrun";
118 settings =
119 let
120 basedir = builtins.concatStringsSep ":" [ phpLdapAdmin "/var/secrets/webapps/tools-ldap" ];
121 in {
122 "listen.owner" = "wwwrun";
123 "listen.group" = "wwwrun";
124 "pm" = "ondemand";
125 "pm.max_children" = "60";
126 "pm.process_idle_timeout" = "60";
127
128 # Needed to avoid clashes in browser cookies (same domain)
129 "php_value[session.name]" = "LdapPHPSESSID";
130 "php_admin_value[open_basedir]" = "${basedir}:/tmp:/var/lib/php/sessions/phpldapadmin";
131 "php_admin_value[session.save_path]" = "/var/lib/php/sessions/phpldapadmin";
132 };
133 phpPackage = pkgs.php72;
134 };
135 system.activationScripts.ldap = {
136 deps = [ "users" ];
137 text = ''
138 install -m 0755 -o wwwrun -g wwwrun -d /var/lib/php/sessions/phpldapadmin
139 '';
140 };
141 systemd.services.phpfpm-ldap = {
142 after = lib.mkAfter [ "openldap.service" ];
143 wants = [ "openldap.service" ];
144 };
145 };
146}
diff --git a/modules/private/system/quatresaisons/landing.yml b/modules/private/system/quatresaisons/landing.yml
new file mode 100644
index 0000000..cf4ba87
--- /dev/null
+++ b/modules/private/system/quatresaisons/landing.yml
@@ -0,0 +1,32 @@
1---
2# Homepage configuration
3# See https://fontawesome.com/icons for icons options
4
5title: "Websites dashboard"
6subtitle: "Salle-S"
7footer: false
8#footer: '<p>Created with <span class="has-text-danger">❤️</span> with <a href="https://bulma.io/">bulma</a>, <a href="https://vuejs.org/">vuejs</a> & <a href="https://fontawesome.com/">font awesome</a> // Fork me on <a href="https://github.com/bastienwirtz/homer"><i class="fab fa-github-alt"></i></a></p>' # set false if you want to hide it.
9
10# Optional navbar
11# links: [] # Allows for navbar (dark mode, layout, and search) without any links
12links: []
13
14# Services
15# First level array represent a group.
16# Leave only a "items" key if not using group (group name, icon & tagstyle are optional, section separation will not be displayed).
17services:
18 - name: "Quatramaran"
19 items:
20 - name: "Roundcube"
21 logo: "assets/tools/roundcube.svg"
22 url: "https://quatramaran.salle-s.org/roundcube/"
23 - name: "Les dessous de paillasse"
24 url: "https://dessous-de-paillasse.salle-s.org"
25 - name: "Quatre Saisons"
26 items:
27 - name: "Charte d’utilisation"
28 icon: "fas fa-scroll"
29 url: "https://4c.salle-s.org/charte/"
30 - name: "Nextcloud"
31 logo: "assets/tools/nextcloud.png"
32 url: "https://nextcloud.4c.salle-s.org"
diff --git a/modules/private/system/quatresaisons/landing_4c.yml b/modules/private/system/quatresaisons/landing_4c.yml
new file mode 100644
index 0000000..0b9f6b6
--- /dev/null
+++ b/modules/private/system/quatresaisons/landing_4c.yml
@@ -0,0 +1,24 @@
1---
2# Homepage configuration
3# See https://fontawesome.com/icons for icons options
4
5title: "Websites dashboard"
6subtitle: "Quatre saisons"
7footer: false
8#footer: '<p>Created with <span class="has-text-danger">❤️</span> with <a href="https://bulma.io/">bulma</a>, <a href="https://vuejs.org/">vuejs</a> & <a href="https://fontawesome.com/">font awesome</a> // Fork me on <a href="https://github.com/bastienwirtz/homer"><i class="fab fa-github-alt"></i></a></p>' # set false if you want to hide it.
9
10# Optional navbar
11# links: [] # Allows for navbar (dark mode, layout, and search) without any links
12links: []
13
14# Services
15# First level array represent a group.
16# Leave only a "items" key if not using group (group name, icon & tagstyle are optional, section separation will not be displayed).
17services:
18 - items:
19 - name: "Charte d’utilisation"
20 icon: "fas fa-scroll"
21 url: "https://4c.salle-s.org/charte/"
22 - name: "Nextcloud"
23 logo: "assets/tools/nextcloud.png"
24 url: "https://nextcloud.4c.salle-s.org"
diff --git a/modules/private/system/quatresaisons/nextcloud.nix b/modules/private/system/quatresaisons/nextcloud.nix
new file mode 100644
index 0000000..047d17e
--- /dev/null
+++ b/modules/private/system/quatresaisons/nextcloud.nix
@@ -0,0 +1,141 @@
1{ lib, pkgs, config, ... }:
2let
3 nextcloud = pkgs.webapps.nextcloud.withApps (a: [
4 a.apporder a.audioplayer a.bookmarks a.calendar a.carnet a.circles
5 a.contacts a.cookbook a.deck a.extract a.files_markdown
6 a.files_readmemd a.flowupload a.gpxedit a.gpxpod a.keeweb a.maps
7 a.metadata a.music a.notes a.ocsms a.passman a.polls a.spreed
8 a.social a.tasks
9 ]);
10 varDir = "/var/lib/nextcloud";
11 phpFpm = rec {
12 basedir = builtins.concatStringsSep ":" ([ nextcloud varDir ] ++ nextcloud.apps);
13 pool = {
14 "listen.owner" = "wwwrun";
15 "listen.group" = "wwwrun";
16 "pm" = "ondemand";
17 "pm.max_children" = "60";
18 "pm.process_idle_timeout" = "60";
19
20 "php_admin_value[output_buffering]" = "0";
21 "php_admin_value[max_execution_time]" = "1800";
22 "php_admin_value[zend_extension]" = "opcache";
23 #already enabled by default?
24 #"php_value[opcache.enable]" = "1";
25 "php_value[opcache.enable_cli]" = "1";
26 "php_value[opcache.interned_strings_buffer]" = "8";
27 "php_value[opcache.max_accelerated_files]" = "10000";
28 "php_value[opcache.memory_consumption]" = "128";
29 "php_value[opcache.save_comments]" = "1";
30 "php_value[opcache.revalidate_freq]" = "1";
31 "php_admin_value[memory_limit]" = "512M";
32
33 "php_admin_value[open_basedir]" = "/run/wrappers/bin/sendmail:${basedir}:/proc/meminfo:/dev/urandom:/proc/self/fd:/tmp";
34 "php_admin_value[session.save_path]" = "${varDir}/phpSessions";
35 };
36 };
37in {
38 config = {
39 services.postgresql.ensureDatabases = [ "nextcloud" ];
40 services.postgresql.ensureUsers = [
41 { name = "nextcloud"; ensurePermissions = { "DATABASE nextcloud" = "ALL PRIVILEGES"; }; }
42 ];
43 services.websites.env.production.modules = [ "proxy_fcgi" ];
44
45 services.websites.env.production.vhostConfs.cloud = {
46 certName = "quatresaisons";
47 addToCerts = true;
48 hosts = ["nextcloud.4c.salle-s.org" ];
49 root = nextcloud;
50 extraConfig =
51 [
52 ''
53 SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
54 <Directory ${nextcloud}>
55 AcceptPathInfo On
56 DirectoryIndex index.php
57 Options FollowSymlinks
58 Require all granted
59 AllowOverride all
60
61 <IfModule mod_headers.c>
62 Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
63 </IfModule>
64 <FilesMatch "\.php$">
65 CGIPassAuth on
66 SetHandler "proxy:unix:${config.services.phpfpm.pools.nextcloud.socket}|fcgi://localhost"
67 </FilesMatch>
68
69 </Directory>
70 ''
71 ];
72 };
73 services.websites.env.production.vhostConfs.cloud_wait = let
74 content = pkgs.writeText "contenu" ''
75 nextcloud est un service qui a besoin de pérennité du nom
76 "nextcloud.salle-s.org", on va peut-etre y arriver, c'est une
77 question de jours, voir le message informatique.internet:8017
78 '';
79 in {
80 certName = "quatresaisons";
81 addToCerts = true;
82 hosts = ["nextcloud.salle-s.org" ];
83 root = content;
84 extraConfig =
85 [
86 ''
87 Alias / ${content}
88 ''
89 ];
90 };
91
92 users.users.root.packages = let
93 occ = pkgs.writeScriptBin "nextcloud-occ" ''
94 #! ${pkgs.stdenv.shell}
95 cd ${nextcloud}
96 NEXTCLOUD_CONFIG_DIR="${nextcloud}/config" \
97 exec \
98 sudo -u wwwrun ${pkgs.php74}/bin/php \
99 -c ${pkgs.php74}/etc/php.ini \
100 occ $*
101 '';
102 in [ occ ];
103
104 system.activationScripts.nextcloud = {
105 deps = [ "users" ];
106 text = let
107 confs = lib.attrsets.mapAttrs (n: v: pkgs.writeText "${n}.json" (builtins.toJSON v)) nextcloud.otherConfig;
108 in
109 ''
110 install -m 0755 -o wwwrun -g wwwrun -d ${varDir}
111 install -m 0755 -o wwwrun -g wwwrun -d ${varDir}/config
112 install -m 0750 -o wwwrun -g wwwrun -d ${varDir}/phpSessions
113 ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v:
114 "install -D -m 0644 -o wwwrun -g wwwrun -T ${v} ${varDir}/config/${n}.json"
115 ) confs)}
116 '';
117 };
118 services.phpfpm.pools.nextcloud = {
119 user = "wwwrun";
120 group = "wwwrun";
121 settings = phpFpm.pool;
122 phpPackage = pkgs.php74.withExtensions({ enabled, all }: enabled ++ [ all.redis all.apcu all.opcache all.imagick ]);
123 };
124
125 services.cron = {
126 enable = true;
127 systemCronJobs = let
128 script = pkgs.writeScriptBin "nextcloud-cron" ''
129 #! ${pkgs.stdenv.shell}
130 export LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive
131 export PATH=/run/wrappers/bin:$PATH
132 ${pkgs.php74}/bin/php -d memory_limit=512M -f ${nextcloud}/cron.php
133 '';
134 in [
135 ''
136 */15 * * * * wwwrun ${script}/bin/nextcloud-cron
137 ''
138 ];
139 };
140 };
141}
diff --git a/nixops/Makefile b/nixops/Makefile
index cefd677..27d8d95 100644
--- a/nixops/Makefile
+++ b/nixops/Makefile
@@ -40,6 +40,9 @@ ssh-backup-2:
40ssh-monitoring-1: 40ssh-monitoring-1:
41 ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@monitoring-1 $(SSH_ARGS)' 41 ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@monitoring-1 $(SSH_ARGS)'
42 42
43ssh-4c:
44 ./scripts/with_env bash -c 'ssh -i $$SSH_IDENTITY_FILE root@quatresaisons $(SSH_ARGS)'
45
43debug: 46debug:
44 ./scripts/with_env morph build --show-trace default.nix $(MORPH_ARGS) 47 ./scripts/with_env morph build --show-trace default.nix $(MORPH_ARGS)
45 48
diff --git a/nixops/default.nix b/nixops/default.nix
index 7c6dd38..f048c80 100644
--- a/nixops/default.nix
+++ b/nixops/default.nix
@@ -6,4 +6,6 @@ in
6 eldiron = import ../modules/private/system/eldiron.nix { inherit privateFiles; }; 6 eldiron = import ../modules/private/system/eldiron.nix { inherit privateFiles; };
7 backup-2 = import ../modules/private/system/backup-2.nix { inherit privateFiles; }; 7 backup-2 = import ../modules/private/system/backup-2.nix { inherit privateFiles; };
8 monitoring-1 = import ../modules/private/system/monitoring-1.nix { inherit privateFiles; }; 8 monitoring-1 = import ../modules/private/system/monitoring-1.nix { inherit privateFiles; };
9
10 quatresaisons = import ../modules/private/system/quatresaisons.nix { inherit privateFiles; };
9} 11}
diff --git a/nixops/secrets b/nixops/secrets
Subproject c91ba443bf2849b8fb81fc72818b77be77b3aab Subproject 3475398eed524be65d0516cf2a648b20a2418f3