]> git.immae.eu Git - perso/Immae/Config/Nix.git/blame - modules/private/system/quatresaisons.nix
Add monitoring for dilion and quatresaisons
[perso/Immae/Config/Nix.git] / modules / private / system / quatresaisons.nix
CommitLineData
75489e72
IB
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
6ee77836 277 myServices.monitoring.enable = true;
75489e72
IB
278 myServices.certificates.enable = true;
279 users.mutableUsers = true;
280 system.stateVersion = "21.03";
281 programs.zsh.enable = true;
282
283 users.motd = ''
284 Bienvenue sur quatresaisons.salle-s.org !
285
286 * Charte :
287 https://4c.salle-s.org/charte
288 * Gérer les utilisateurs unix additionnels :
289 sudo sponsored_user -h
290 * Applications web :
291 * tableau de bord : https://4c.salle-s.org/
292 * nextcloud : https://nextcloud.4c.salle-s.org/
293 '';
294
295 users.groups =
296 lib.mapAttrs (n: v: { gid = v.uid; }) normalUsers
297 // { wwwrun = { gid = config.ids.gids.wwwrun; }; };
298 users.users =
299 let
300 defaultNormal = n: {
301 group = n;
302 extraGroups = [ "users" ];
303 isNormalUser = true;
304 };
305 in
306 lib.mapAttrs (n: v: defaultNormal n // (lib.filterAttrs (k: _: k != "_meta") v)) normalUsers
307 // {
308 sponsored-separator = {
309 uid = 10000;
310 group = "users";
311 home = "/var/empty";
312 extraGroups = [];
313 isNormalUser = true;
314 createHome = false;
315 };
316 wwwrun = {
317 group = "wwwrun";
318 description = "Apache httpd user";
319 uid = config.ids.uids.wwwrun;
320 extraGroups = [ "keys" ];
321 };
322 };
323
324 system.activationScripts.usersPost = {
325 deps = [ "users" "groups" ];
326 text = builtins.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
327 if getent shadow "${n}" | grep -q '^${n}:${v.initialHashedPassword or "!"}:1'; then
328 chage -d 0 "${n}"
329 [ '${v.initialHashedPassword or "!"}' = '!' ] && passwd -d "${n}"
330 fi
331 '') normalUsers);
332 };
333 security.sudo.extraRules = [
334 {
335 commands = [
336 { command = "${sponsoredUser}/bin/sponsored_user"; options = [ "NOPASSWD" ]; }
337 ];
338 users = builtins.attrNames normalUsers;
339 runAs = "root";
340 }
341 ];
342
343 environment.systemPackages = [
344 sponsoredUser
cd30f699
IB
345 pkgs.git pkgs.vim pkgs.rsync pkgs.strace pkgs.home-manager
346 pkgs.telnet pkgs.htop pkgs.iftop pkgs.bind.dnsutils pkgs.httpie
347 pkgs.iotop pkgs.whois pkgs.ngrep pkgs.tcpdump pkgs.tshark
348 pkgs.tcpflow pkgs.nmap pkgs.p0f pkgs.socat pkgs.lsof pkgs.psmisc
349 pkgs.openssl pkgs.wget pkgs.pv pkgs.smartmontools pkgs.youtube-dl
350 pkgs.unzip pkgs.octave pkgs.feh pkgs.xv pkgs.sshfs pkgs.gdb
351 pkgs.file pkgs.lynx pkgs.tmux pkgs.awesome pkgs.libreoffice
352 pkgs.evince pkgs.firefox pkgs.xcalib pkgs.python3 pkgs.python2
353 pkgs.xorg.xkbcomp pkgs.subversion pkgs.xclip pkgs.imagemagick
354 pkgs.bc pkgs.sox pkgs.zip pkgs.gnome3.gnome-screenshot
355 pkgs.datadog-process-agent
75489e72
IB
356 ];
357
358 services.websites.env.production = {
359 enable = true;
360 adminAddr = "httpd@immae.eu";
361 httpdName = "Prod";
362 modules = [ "http2" "deflate" "filter" ];
363 extraConfig = [
364 ''
365 LogFormat "%{Host}i:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedVhost
366 Protocols h2 http/1.1
367 AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
368 '' ];
369 ips =
370 let ips = config.hostEnv.ips.main;
371 in [ips.ip4] ++ (ips.ip6 or []);
372
373 fallbackVhost = {
374 certName = "quatresaisons";
375 hosts = [ "quatresaisons.immae.eu" ];
376 root = pkgs.runCommand "empty" {} "mkdir $out && touch $out/index.html";
377 extraConfig = [ "DirectoryIndex index.html" ];
378 };
379 vhostConfs.salle-s = {
380 certName = "quatresaisons";
381 addToCerts = true;
382 hosts = [ "salle-s.org" ];
383 root = toLanding ./quatresaisons/landing.yml;
384 extraConfig = [
385 ''
386 <Directory ${toLanding ./quatresaisons/landing.yml}>
387 AllowOverride None
388 Require all granted
389 DirectoryIndex index.html
390 </Directory>
391 ''
392 ];
393 };
394 vhostConfs.tools = {
395 certName = "quatresaisons";
396 addToCerts = true;
397 hosts = [ "4c.salle-s.org" "quatresaisons.salle-s.org" "quatre-saisons.salle-s.org" ];
398 root = toLanding ./quatresaisons/landing_4c.yml;
399 extraConfig = [
400 ''
401 Alias /charte ${serverSpecificConfig.charte_path}
402 <Directory ${serverSpecificConfig.charte_path}>
403 AllowOverride None
404 Require all granted
405 DirectoryIndex index.html index.txt
406 </Directory>
407
408 <Directory ${toLanding ./quatresaisons/landing_4c.yml}>
409 AllowOverride None
410 Require all granted
411 DirectoryIndex index.html
412 </Directory>
413 ''
414 ];
415 };
416 };
417 system.activationScripts.httpd = ''
418 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php
419 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions
420 '';
421
422 services.phpfpm = {
423 phpOptions = ''
424 session.save_path = "/var/lib/php/sessions"
425 post_max_size = 20M
426 ; 15 days (seconds)
427 session.gc_maxlifetime = 1296000
428 ; 30 days (minutes)
429 session.cache_expire = 43200
430 '';
431 settings = {
432 log_level = "notice";
433 };
434 };
435
436}