aboutsummaryrefslogtreecommitdiff
path: root/modules/private/system
diff options
context:
space:
mode:
Diffstat (limited to 'modules/private/system')
-rw-r--r--modules/private/system/backup-2.nix137
-rw-r--r--modules/private/system/dilion.nix242
-rw-r--r--modules/private/system/dilion/vms.nix185
-rw-r--r--modules/private/system/dilion/vms/base_configuration.nix21
-rw-r--r--modules/private/system/dilion/vms/base_image.nix94
-rw-r--r--modules/private/system/dilion/vms/buildbot_configuration.nix67
-rw-r--r--modules/private/system/eldiron.nix228
-rw-r--r--modules/private/system/monitoring-1.nix69
-rw-r--r--modules/private/system/quatresaisons.nix436
-rw-r--r--modules/private/system/quatresaisons/databases.nix147
-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
13 files changed, 0 insertions, 1823 deletions
diff --git a/modules/private/system/backup-2.nix b/modules/private/system/backup-2.nix
deleted file mode 100644
index c01a666..0000000
--- a/modules/private/system/backup-2.nix
+++ /dev/null
@@ -1,137 +0,0 @@
1{ config, pkgs, resources, name, ... }:
2{
3 deployment = {
4 targetUser = "root";
5 targetHost = config.hostEnv.ips.main.ip4;
6 substituteOnDestination = true;
7 };
8 # ssh-keyscan backup-2 | nix-shell -p ssh-to-age --run ssh-to-age
9 secrets.ageKeys = [ "age1kk3nr27qu42j28mcfdag5lhq0zu2pky7gfanvne8l4z2ctevjpgskmw0sr" ];
10 secrets.keys = {
11 "rsync_backup/identity" = {
12 user = "backup";
13 group = "backup";
14 permissions = "0400";
15 text = config.myEnv.rsync_backup.ssh_key.private;
16 };
17 "rsync_backup/identity.pub" = {
18 user = "backup";
19 group = "backup";
20 permissions = "0444";
21 text = config.myEnv.rsync_backup.ssh_key.public;
22 };
23 };
24 boot.kernelPackages = pkgs.linuxPackages_latest;
25 myEnv = import ../../../nixops/secrets/environment.nix;
26
27 imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ] ++ builtins.attrValues (import ../..);
28
29 fileSystems = {
30 "/backup2" = {
31 fsType = "ext4";
32 device = "UUID=b9425333-f567-435d-94d8-b26c22d93426";
33 };
34 "/" = { device = "/dev/sda1"; fsType = "ext4"; };
35 };
36
37 networking = {
38 firewall.enable = true;
39 interfaces."ens3".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList
40 (n: ips: { address = ips.ip4; prefixLength = 32; })
41 (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips);
42 interfaces."ens3".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
43 (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
44 config.hostEnv.ips);
45 defaultGateway6 = { address = "fe80::1"; interface = "ens3"; };
46 };
47
48 boot.loader.grub.device = "nodev";
49
50 myServices.certificates.enable = true;
51 security.acme.certs."${name}" = {
52 user = config.services.nginx.user;
53 group = config.services.nginx.group;
54 };
55 services.nginx = {
56 enable = true;
57 recommendedOptimisation = true;
58 recommendedGzipSettings = true;
59 recommendedProxySettings = true;
60 };
61 networking.firewall.allowedTCPPorts = [ 80 443 ];
62
63 services.cron = {
64 mailto = "cron@immae.eu";
65 enable = true;
66 };
67
68 services.rsyncBackup = {
69 mountpoint = "/backup2";
70 profiles = config.myEnv.rsync_backup.profiles;
71 ssh_key_public = config.secrets.fullPaths."rsync_backup/identity.pub";
72 ssh_key_private = config.secrets.fullPaths."rsync_backup/identity";
73 };
74
75 myServices.mailRelay.enable = true;
76 myServices.mailBackup.enable = true;
77 myServices.monitoring.enable = true;
78 myServices.databasesReplication = {
79 postgresql = {
80 enable = true;
81 base = "/backup2";
82 mainPackage = pkgs.postgresql;
83 hosts = {
84 eldiron = {
85 slot = "backup_2";
86 connection = "postgresql://backup-2:${config.hostEnv.ldap.password}@eldiron.immae.eu";
87 package = pkgs.postgresql;
88 };
89 };
90 };
91 mariadb = {
92 enable = true;
93 base = "/backup2";
94 hosts = {
95 eldiron = {
96 serverId = 2;
97 # mysql resolves "backup-2" host and checks the ip, but uses /etc/hosts which only contains ip4
98 host = config.myEnv.servers.eldiron.ips.main.ip4;
99 port = "3306";
100 user = "backup-2";
101 password = config.hostEnv.ldap.password;
102 dumpUser = "root";
103 dumpPassword = config.myEnv.databases.mysql.systemUsers.root;
104 };
105 };
106 };
107 redis = {
108 enable = true;
109 base = "/backup2";
110 hosts = {
111 eldiron = {
112 host = "127.0.0.1";
113 port = "16379";
114 };
115 };
116 };
117 openldap = {
118 enable = true;
119 base = "/backup2";
120 hosts = {
121 eldiron = {
122 url = "ldaps://${config.myEnv.ldap.host}:636";
123 dn = config.myEnv.ldap.replication_dn;
124 password = config.myEnv.ldap.replication_pw;
125 base = config.myEnv.ldap.base;
126 };
127 };
128 };
129 };
130
131 # This value determines the NixOS release with which your system is
132 # to be compatible, in order to avoid breaking some software such as
133 # database servers. You should change this only after NixOS release
134 # notes say you should.
135 # https://nixos.org/nixos/manual/release-notes.html
136 system.stateVersion = "20.03"; # Did you read the comment?
137}
diff --git a/modules/private/system/dilion.nix b/modules/private/system/dilion.nix
deleted file mode 100644
index fa92cd9..0000000
--- a/modules/private/system/dilion.nix
+++ /dev/null
@@ -1,242 +0,0 @@
1{ config, pkgs, name, lib, ... }:
2{
3 deployment = {
4 targetUser = "root";
5 targetHost = config.hostEnv.ips.main.ip4;
6 substituteOnDestination = true;
7 };
8 # ssh-keyscan dilion | nix-shell -p ssh-to-age --run ssh-to-age
9 secrets.ageKeys = [ "age1x49n6qa0arkdpq8530s7umgm0gqkq90exv4jep97q30rfnzknpaqate06a" ];
10 nixpkgs.system = lib.mkOverride 900 "x86_64-linux";
11 boot = {
12 loader = {
13 grub = {
14 version = 2;
15 devices = [ "/dev/sda" "/dev/sdb" "/dev/sdc" "/dev/sdd" ];
16 };
17 timeout = 1;
18 };
19 blacklistedKernelModules = [ "nvidiafb" ];
20 supportedFilesystems = [ "zfs" ];
21 kernelPackages = pkgs.linuxPackages_latest;
22 kernelModules = [ "kvm-intel" ];
23 initrd.availableKernelModules = [ "ahci" "sd_mod" ];
24 initrd.secrets = {
25 "/boot/pass.key" = "/boot/pass.key";
26 };
27 kernel.sysctl."vm.nr_hugepages" = 256; # for xmr-stak
28 # available in nixos-20.09
29 #zfs.requestEncryptionCredentials = [ "zpool/root" ];
30 };
31 nix.maxJobs = 8;
32 powerManagement.cpuFreqGovernor = "powersave";
33 hardware.enableRedistributableFirmware = true;
34
35 myEnv = import ../../../nixops/secrets/environment.nix;
36
37 swapDevices = [ { label = "swap"; } ];
38 fileSystems = {
39 "/" = { fsType = "zfs"; device = "zpool/root"; };
40 "/boot" = { fsType = "ext4"; device = "/dev/disk/by-uuid/fd1c511e-2bc0-49d5-b8bb-95e7e8c8c816"; };
41 "/etc" = { fsType = "zfs"; device = "zpool/root/etc"; };
42 "/home" = { fsType = "zfs"; device = "zpool/root/home"; };
43 "/home/immae" = { fsType = "zfs"; device = "zpool/root/home/immae"; };
44 "/tmp" = { fsType = "zfs"; device = "zpool/root/tmp"; };
45 "/var" = { fsType = "zfs"; device = "zpool/root/var"; };
46 "/data" = { fsType = "ext4"; label = "data"; };
47 "/nix" = { fsType = "ext4"; label = "nix"; };
48 };
49
50 services.udev.extraRules = ''
51 ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="10:bf:48:7f:e6:3b", NAME="eth0"
52 '';
53
54 networking = {
55 hostId = "27c3048d"; # generated with head -c4 /dev/urandom | od -A none -t x4
56 firewall.enable = false;
57 interfaces."eth0".ipv4.addresses =
58 [ { address = config.hostEnv.ips.main.ip4; prefixLength = 27; } ]
59 ++ pkgs.lib.attrsets.mapAttrsToList
60 (n: ips: { address = ips.ip4; prefixLength = 32; })
61 (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips);
62 interfaces."eth0".ipv6.addresses =
63 [ { address = "2a01:4f8:141:53e7::"; prefixLength = 64; } ]
64 ++ pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
65 (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
66 config.hostEnv.ips);
67 defaultGateway = { address = "176.9.10.225"; interface = "eth0"; };
68 defaultGateway6 = { address = "fe80::1"; interface = "eth0"; };
69 nameservers = [
70 "213.133.98.98"
71 "213.133.99.99"
72 "213.133.100.100"
73 "2a01:4f8:0:a0a1::add:1010"
74 "2a01:4f8:0:a102::add:9999"
75 "2a01:4f8:0:a111::add:9898"
76 ];
77 };
78
79 myServices.ssh.modules = [ config.myServices.ssh.predefinedModules.regular ];
80 imports = builtins.attrValues (import ../..) ++ [ ./dilion/vms.nix ];
81
82 system.nssModules = [ pkgs.libvirt ];
83 system.nssDatabases.hosts = lib.mkForce [ "files" "libvirt_guest" "mymachines" "dns" "myhostname" ];
84 programs.zsh.enable = true;
85
86 users.users.libvirt = {
87 hashedPassword = "!";
88 shell = pkgs.bashInteractive;
89 isSystemUser = true;
90 group = "libvirtd";
91 packages = [ pkgs.netcat-openbsd ];
92 openssh.authorizedKeys.keys = [
93 config.myEnv.buildbot.ssh_key.public
94 config.myEnv.sshd.rootKeys.ismael_flony
95 ];
96 };
97
98 users.users.backup = {
99 hashedPassword = "!";
100 isSystemUser = true;
101 extraGroups = [ "keys" ];
102 shell = pkgs.bashInteractive;
103 openssh.authorizedKeys.keys = let
104 zreplConfig = config.secrets.fullPaths."zrepl/zrepl.yml";
105 in
106 ["command=\"${pkgs.zrepl}/bin/zrepl stdinserver --config ${zreplConfig} eldiron\",restrict ${config.myEnv.zrepl_backup.ssh_key.public}"];
107 };
108 security.sudo.extraRules = pkgs.lib.mkAfter [
109 {
110 commands = [
111 { command = "/home/immae/.nix-profile/root_scripts/*"; options = [ "NOPASSWD" ]; }
112 ];
113 users = [ "immae" ];
114 runAs = "root";
115 }
116 ];
117
118 system.activationScripts.libvirtd_exports = ''
119 install -m 0755 -o root -g root -d /var/lib/caldance
120 '';
121 virtualisation.docker.enable = true;
122 virtualisation.docker.storageDriver = "zfs";
123 virtualisation.libvirtd.enable = true;
124 users.extraUsers.immae.extraGroups = [ "libvirtd" "docker" ];
125 systemd.services.libvirtd.postStart = ''
126 install -m 0770 -g libvirtd -d /var/lib/libvirt/images
127 '';
128 systemd.services.socat-caldance = {
129 description = "Forward ssh port to caldance";
130 wantedBy = [ "multi-user.target" ];
131 after = [ "network.target" ];
132
133 serviceConfig = {
134 ExecStart = "${pkgs.socat}/bin/socat TCP-LISTEN:8022,fork TCP:caldance:22";
135 };
136 };
137
138 time.timeZone = "Europe/Paris";
139 nix = {
140 useSandbox = "relaxed";
141 extraOptions = ''
142 keep-outputs = true
143 keep-derivations = true
144 allow-unsafe-native-code-during-evaluation = true
145 experimental-features = nix-command flakes
146 #Assumed in NUR
147 allow-import-from-derivation = true
148 '';
149 };
150
151 security.pki.certificateFiles = [
152 (pkgs.fetchurl {
153 url = "http://downloads.e.eriomem.net/eriomemca.pem";
154 sha256 = "1ixx4c6j3m26j8dp9a3dkvxc80v1nr5aqgmawwgs06bskasqkvvh";
155 })
156 ];
157
158 # This is equivalent to setting environment.sessionVariables.NIX_PATH
159 nix.nixPath = [
160 "home-manager=${pkgs.sources.home-manager.url}"
161 "nixpkgs=${pkgs.sources.nixpkgs-home-manager.url}"
162 ];
163 nix.binaryCaches = [ "https://hydra.iohk.io" "https://cache.nixos.org" ];
164 nix.binaryCachePublicKeys = [ "hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ=" ];
165
166 myServices.monitoring.enable = true;
167 myServices.certificates.enable = true;
168 security.acme.certs."${name}-immae" = config.myServices.certificates.certConfig // {
169 user = "immae";
170 domain = "dilion.immae.eu";
171 };
172 security.acme.certs."${name}" = {
173 user = config.services.nginx.user;
174 group = config.services.nginx.group;
175 extraDomains = {
176 "dilion.immae.dev" = null;
177 "caldance.cs.immae.dev" = null;
178 };
179 };
180 services.nginx = {
181 enable = true;
182 recommendedOptimisation = true;
183 recommendedGzipSettings = true;
184 recommendedProxySettings = true;
185 upstreams = {
186 caldance.servers."caldance:3031" = {};
187 };
188 virtualHosts = {
189 "dilion.immae.dev" = {
190 acmeRoot = config.myServices.certificates.webroot;
191 useACMEHost = name;
192 forceSSL = true;
193 root = "/home/immae/www";
194 };
195 "caldance.cs.immae.dev" = {
196 acmeRoot = config.myServices.certificates.webroot;
197 useACMEHost = name;
198 forceSSL = true;
199 locations."/".extraConfig = ''
200 uwsgi_pass caldance;
201 '';
202 locations."/static/".alias = "/var/lib/caldance/caldance/app/www/static/";
203 locations."/media/".alias = "/var/lib/caldance/caldance/media/";
204 extraConfig = ''
205 auth_basic "Authentification requise";
206 auth_basic_user_file ${pkgs.writeText "htpasswd" config.myEnv.websites.caldance.integration.password};
207 '';
208 };
209 };
210 };
211
212 systemd.services.zrepl.serviceConfig.RuntimeDirectory = lib.mkForce "zrepl zrepl/stdinserver";
213 systemd.services.zrepl.serviceConfig.User = "backup";
214 # zfs allow backup create,mount,receive,destroy,rename,snapshot,hold,bookmark,release zpool/backup
215 services.zrepl = {
216 enable = true;
217 config = ''
218 global:
219 control:
220 sockpath: /run/zrepl/control
221 serve:
222 stdinserver:
223 sockdir: /run/zrepl/stdinserver
224 jobs:
225 - type: sink
226 # must not change
227 name: "backup-from-eldiron"
228 root_fs: "zpool/backup"
229 serve:
230 type: stdinserver
231 client_identities:
232 - eldiron
233 '';
234 };
235 # This value determines the NixOS release with which your system is
236 # to be compatible, in order to avoid breaking some software such as
237 # database servers. You should change this only after NixOS release
238 # notes say you should.
239 # https://nixos.org/nixos/manual/release-notes.html
240 system.stateVersion = "20.03"; # Did you read the comment?
241}
242
diff --git a/modules/private/system/dilion/vms.nix b/modules/private/system/dilion/vms.nix
deleted file mode 100644
index af96622..0000000
--- a/modules/private/system/dilion/vms.nix
+++ /dev/null
@@ -1,185 +0,0 @@
1# inspired from https://nixos.wiki/wiki/Virtualization_in_NixOS
2{ config, pkgs, lib, ... }@args:
3let
4 pools = {
5 niximages = {
6 type = "dir";
7 target = "/etc/libvirtd/base-images";
8 };
9 buildbot-disks = rec {
10 preStart = ''
11 mkdir -p ${target}
12 '';
13 type = "dir";
14 target = "/var/lib/libvirt/images/buildbot-disks";
15 };
16 zfspool = {
17 # pool-define-as --name zfspool --source-name zpool/libvirt --type zfs
18 type = "zfs";
19 xml = ''
20 <source>
21 <name>zpool/libvirt</name>
22 </source>
23 '';
24 };
25 };
26 networks = {
27 immae = {
28 bridgeNumber = "1";
29 ipRange = "192.168.100";
30 };
31 };
32 guests = {
33 caldance = {
34 pool = "zfspool";
35 cpus = "1";
36 memory = "2";
37 network = "immae";
38 diskSize = "10GiB";
39 extraDevicesXML = ''
40 <filesystem type="mount">
41 <source dir="/var/lib/caldance"/>
42 <target dir="home"/>
43 </filesystem>
44 '';
45 };
46 buildbot = {
47 pool = "zfspool";
48 cpus = "1";
49 memory = "3";
50 network = "immae";
51 diskSize = "10GiB";
52 destroyVolumeOnExit = true;
53 };
54 };
55 toImage = f: "${import ./vms/base_image.nix f (args // { myEnv = config.myEnv; })}/nixos.qcow2";
56in
57{
58 environment.etc."libvirtd/base-images/nixos.qcow2".source = toImage ./vms/base_configuration.nix;
59 environment.etc."libvirtd/base-images/buildbot.qcow2".source = toImage ./vms/buildbot_configuration.nix;
60 systemd.services = lib.mapAttrs' (name: guest: lib.nameValuePair "libvirtd-guest-${name}" {
61 after = [ "libvirtd.service" "libvirtd-pool-${guest.pool}.service" "libvirtd-network-${guest.network}.service" ];
62 requires = [ "libvirtd.service" "libvirtd-pool-${guest.pool}.service" "libvirtd-network-${guest.network}.service" ];
63 wantedBy = [ "multi-user.target" ];
64 serviceConfig = {
65 Type = "oneshot";
66 RemainAfterExit = "yes";
67 };
68 script =
69 let
70 xml = pkgs.writeText "libvirt-guest-${name}.xml"
71 ''
72 <domain type="kvm">
73 <name>${name}</name>
74 <uuid>UUID</uuid>
75 <memory unit="GiB">${guest.memory}</memory>
76 <vcpu>${guest.cpus}</vcpu>
77 <os>
78 <type arch="x86_64">hvm</type>
79 </os>
80 <devices>
81 <emulator>/run/current-system/sw/bin/qemu-system-x86_64</emulator>
82 <disk type="volume">
83 <source pool="${guest.pool}" volume="guest-${name}" />
84 <target dev="vda" bus="virtio"/>
85 </disk>
86 ${guest.extraDevicesXML or ""}
87 <input type="keyboard" bus="usb"/>
88 <graphics type="vnc" port="-1" autoport="yes"/>
89 <interface type="network">
90 <source network="${guest.network}" />
91 </interface>
92 </devices>
93 <features>
94 <acpi/>
95 </features>
96 </domain>
97 '';
98 in
99 guest.preStart or "" + ''
100 if ! ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then
101 ${pkgs.libvirt}/bin/virsh vol-create-as --pool ${guest.pool} --name 'guest-${name}' --capacity '${guest.diskSize}'
102 volume_path=$(${pkgs.libvirt}/bin/virsh vol-path --pool ${guest.pool} --vol 'guest-${name}')
103 ${pkgs.qemu}/bin/qemu-img convert /etc/libvirtd/base-images/nixos.qcow2 $volume_path
104 fi
105 uuid="$(${pkgs.libvirt}/bin/virsh domuuid '${name}' || true)"
106 ${pkgs.libvirt}/bin/virsh define <(sed "s/UUID/$uuid/" '${xml}')
107 ${pkgs.libvirt}/bin/virsh start '${name}'
108 '';
109 preStop = ''
110 ${pkgs.libvirt}/bin/virsh shutdown '${name}'
111 let "timeout = $(date +%s) + 10"
112 while [ "$(${pkgs.libvirt}/bin/virsh list --name | grep --count '^${name}$')" -gt 0 ]; do
113 if [ "$(date +%s)" -ge "$timeout" ]; then
114 # Meh, we warned it...
115 ${pkgs.libvirt}/bin/virsh destroy '${name}'
116 else
117 # The machine is still running, let's give it some time to shut down
118 sleep 0.5
119 fi
120 done
121 '' + lib.optionalString (guest.destroyVolumeOnExit or false) ''
122 if ${pkgs.libvirt}/bin/virsh vol-key 'guest-${name}' --pool ${guest.pool} &> /dev/null; then
123 ${pkgs.libvirt}/bin/virsh vol-wipe --pool ${guest.pool} --vol 'guest-${name}' || true
124 ${pkgs.libvirt}/bin/virsh vol-delete --pool ${guest.pool} --vol 'guest-${name}'
125 fi
126 '';
127 }) guests // (lib.mapAttrs' (name: network: lib.nameValuePair "libvirtd-network-${name}" {
128 after = [ "libvirtd.service" ];
129 requires = [ "libvirtd.service" ];
130 wantedBy = [ "multi-user.target" ];
131 serviceConfig = {
132 Type = "oneshot";
133 RemainAfterExit = "yes";
134 };
135 script = let
136 xml = pkgs.writeText "libvirt-network-${name}.xml" ''
137 <network>
138 <name>${name}</name>
139 <uuid>UUID</uuid>
140 <forward mode='nat' />
141 <bridge name='virbr${network.bridgeNumber}' />
142 <domain name='${name}' localOnly='yes'/>
143 <ip address='${network.ipRange}.1' netmask='255.255.255.0'>
144 <dhcp>
145 <range start='${network.ipRange}.2' end='${network.ipRange}.254'/>
146 </dhcp>
147 </ip>
148 </network>
149 '';
150 in ''
151 uuid="$(${pkgs.libvirt}/bin/virsh net-uuid '${name}' || true)"
152 ${pkgs.libvirt}/bin/virsh net-define <(sed "s/UUID/$uuid/" '${xml}')
153 ${pkgs.libvirt}/bin/virsh net-start '${name}'
154 '';
155 preStop = ''
156 ${pkgs.libvirt}/bin/virsh net-destroy '${name}'
157 '';
158 }) networks) // (lib.mapAttrs' (name: pool: lib.nameValuePair "libvirtd-pool-${name}" {
159 after = [ "libvirtd.service" ];
160 requires = [ "libvirtd.service" ];
161 wantedBy = [ "multi-user.target" ];
162 serviceConfig = {
163 Type = "oneshot";
164 RemainAfterExit = "yes";
165 };
166 script = let
167 xml = pkgs.writeText "libvirt-pool-${name}.xml" ''
168 <pool type="${pool.type}">
169 <name>${name}</name>
170 <uuid>UUID</uuid>
171 ${pool.xml or ""}
172 ${if pool ? target then ''
173 <target>
174 <path>${pool.target}</path>
175 </target>
176 '' else ""}
177 </pool>
178 '';
179 in pool.preStart or "" + ''
180 uuid="$(${pkgs.libvirt}/bin/virsh pool-uuid '${name}' || true)"
181 ${pkgs.libvirt}/bin/virsh pool-define <(sed "s/UUID/$uuid/" '${xml}')
182 ${pkgs.libvirt}/bin/virsh pool-start '${name}' || true
183 '';
184 }) pools);
185}
diff --git a/modules/private/system/dilion/vms/base_configuration.nix b/modules/private/system/dilion/vms/base_configuration.nix
deleted file mode 100644
index e2caba2..0000000
--- a/modules/private/system/dilion/vms/base_configuration.nix
+++ /dev/null
@@ -1,21 +0,0 @@
1{ lib, config, ... }@args:
2{
3 options.myEnv = (import ../../../environment.nix (args // { name = "dummy"; })).options.myEnv;
4 config = {
5 fileSystems."/".device = "/dev/disk/by-label/nixos";
6 boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "virtio_balloon" "virtio_blk" "virtio_pci" "virtio_ring" ];
7 boot.loader = {
8 grub = {
9 version = 2;
10 device = "/dev/vda";
11 };
12 timeout = 0;
13 };
14 services.openssh.enable = true;
15 networking.firewall.allowedTCPPorts = [ 22 ];
16 users = {
17 mutableUsers = false;
18 users.root.openssh.authorizedKeys.keys = [ config.myEnv.sshd.rootKeys.immae_dilion ];
19 };
20 };
21}
diff --git a/modules/private/system/dilion/vms/base_image.nix b/modules/private/system/dilion/vms/base_image.nix
deleted file mode 100644
index 8de8560..0000000
--- a/modules/private/system/dilion/vms/base_image.nix
+++ /dev/null
@@ -1,94 +0,0 @@
1configuration_file: { pkgs ? import <nixpkgs> {}, system ? builtins.currentSystem, myEnv, ... }:
2let
3 config = (import <nixpkgs/nixos/lib/eval-config.nix> {
4 inherit system;
5 modules = [ {
6 myEnv = myEnv;
7 imports = [ configuration_file ];
8
9 # We want our template image to be as small as possible, but the deployed image should be able to be
10 # of any size. Hence we resize on the first boot.
11 systemd.services.resize-main-fs = {
12 wantedBy = [ "multi-user.target" ];
13 serviceConfig.Type = "oneshot";
14 script =
15 ''
16 # Resize main partition to fill whole disk
17 echo ", +" | ${pkgs.utillinux}/bin/sfdisk /dev/vda --no-reread -N 1
18 ${pkgs.parted}/bin/partprobe
19 # Resize filesystem
20 ${pkgs.e2fsprogs}/bin/resize2fs /dev/vda1
21 '';
22 };
23 } ];
24 }).config;
25in pkgs.vmTools.runInLinuxVM (
26 pkgs.runCommand "nixos-base-image"
27 {
28 memSize = 768;
29 preVM =
30 ''
31 mkdir $out
32 diskImage=image.qcow2
33 ${pkgs.vmTools.qemu}/bin/qemu-img create -f qcow2 $diskImage 2G
34 mv closure xchg/
35 '';
36 postVM =
37 ''
38 echo compressing VM image...
39 ${pkgs.vmTools.qemu}/bin/qemu-img convert -c $diskImage -O qcow2 $out/nixos.qcow2
40 '';
41 buildInputs = [ pkgs.utillinux pkgs.perl pkgs.parted pkgs.e2fsprogs ];
42 exportReferencesGraph =
43 [ "closure" config.system.build.toplevel ];
44 }
45 ''
46 # Create the partition
47 parted /dev/vda mklabel msdos
48 parted /dev/vda -- mkpart primary ext4 1M -1s
49
50 # Format the partition
51 mkfs.ext4 -L nixos /dev/vda1
52 mkdir /mnt
53 mount /dev/vda1 /mnt
54
55 for dir in dev proc sys; do
56 mkdir /mnt/$dir
57 mount --bind /$dir /mnt/$dir
58 done
59
60 storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure)
61 echo filling Nix store...
62 mkdir -p /mnt/nix/store
63 set -f
64 cp -prd $storePaths /mnt/nix/store
65 # The permissions will be set up incorrectly if the host machine is not running NixOS
66 chown -R 0:30000 /mnt/nix/store
67
68 mkdir -p /mnt/etc/nix
69 echo 'build-users-group = ' > /mnt/etc/nix/nix.conf
70
71 # Register the paths in the Nix database.
72 export USER=root
73 printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \
74 chroot /mnt ${config.nix.package.out}/bin/nix-store --load-db
75
76 # Create the system profile to allow nixos-rebuild to work.
77 chroot /mnt ${config.nix.package.out}/bin/nix-env \
78 -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel}
79
80 # `nixos-rebuild' requires an /etc/NIXOS.
81 mkdir -p /mnt/etc/nixos
82 touch /mnt/etc/NIXOS
83
84 # `switch-to-configuration' requires a /bin/sh
85 mkdir -p /mnt/bin
86 ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh
87
88 # Generate the GRUB menu.
89 chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot
90
91 umount /mnt/{proc,dev,sys}
92 umount /mnt
93 ''
94)
diff --git a/modules/private/system/dilion/vms/buildbot_configuration.nix b/modules/private/system/dilion/vms/buildbot_configuration.nix
deleted file mode 100644
index 05b02d4..0000000
--- a/modules/private/system/dilion/vms/buildbot_configuration.nix
+++ /dev/null
@@ -1,67 +0,0 @@
1{ pkgs, config, lib, ... }:
2{
3 imports = [
4 <nixpkgs/nixos/modules/profiles/qemu-guest.nix>
5 ./base_configuration.nix
6 ];
7 systemd.services.buildbot-worker.serviceConfig.ExecStartPre = let
8 cfg = config.services.buildbot-worker;
9 script = pkgs.writeScript "decode-dmi" ''
10 #!${pkgs.stdenv.shell}
11
12 mkdir -vp "${cfg.buildbotDir}"
13 varfile=${cfg.buildbotDir}/variables
14 rm $varfile || true
15 echo "[DEFAULT]" > $varfile
16 strings=$(${pkgs.dmidecode}/bin/dmidecode --oem-string count)
17 for i in $(seq 1 $strings); do
18 ${pkgs.dmidecode}/bin/dmidecode --oem-string $i >> $varfile
19 done
20 chown -R ${cfg.user}:${cfg.group} ${cfg.buildbotDir}
21 '';
22 in
23 lib.mkForce ["+${script}"];
24 systemd.services.buildbot-worker.serviceConfig.ExecStart = let
25 cfg = config.services.buildbot-worker;
26 tacFile = pkgs.writeText "buildbot-worker.tac" ''
27 import os
28 from io import open
29
30 from buildbot_worker.bot import Worker
31 from twisted.application import service
32
33 basedir = '${cfg.buildbotDir}'
34
35 # note: this line is matched against to check that this is a worker
36 # directory; do not edit it.
37 application = service.Application('buildbot-worker')
38
39 import configparser
40 config = config = configparser.ConfigParser()
41 config.read("${cfg.buildbotDir}/variables")
42 master_url_split = config["DEFAULT"]["buildbot_master_url"].split(':')
43 buildmaster_host = master_url_split[0]
44 port = int(master_url_split[1])
45 workername = config["DEFAULT"]["buildbot_worker_name"]
46
47 with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file:
48 passwd = passwd_file.read().strip('\r\n')
49 keepalive = ${toString cfg.keepalive}
50 umask = None
51 maxdelay = 300
52 numcpus = None
53 allow_shutdown = None
54
55 s = Worker(buildmaster_host, port, workername, passwd, basedir,
56 keepalive, umask=umask, maxdelay=maxdelay,
57 numcpus=numcpus, allow_shutdown=allow_shutdown)
58 s.setServiceParent(application)
59 '';
60 in
61 lib.mkForce "${cfg.package.pythonModule.pkgs.twisted}/bin/twistd --nodaemon --pidfile= --logfile - --python ${tacFile}";
62 services.buildbot-worker = {
63 enable = true;
64 workerPass = config.myEnv.buildbot.workerPassword;
65 packages = [ pkgs.git pkgs.gzip pkgs.openssh ];
66 };
67}
diff --git a/modules/private/system/eldiron.nix b/modules/private/system/eldiron.nix
deleted file mode 100644
index 8b2784d..0000000
--- a/modules/private/system/eldiron.nix
+++ /dev/null
@@ -1,228 +0,0 @@
1{ config, pkgs, lib, ... }:
2{
3 deployment = {
4 targetUser = "root";
5 targetHost = config.hostEnv.ips.main.ip4;
6 substituteOnDestination = true;
7 };
8 # ssh-keyscan eldiron | nix-shell -p ssh-to-age --run ssh-to-age
9 secrets.ageKeys = [ "age1dxr5lhvtnjssfaqpnf6qx80h8gfwkxg3tdf35m6n9wljmk7wadfs3kmahj" ];
10 boot = {
11 kernelModules = [ "kvm-intel" ];
12 blacklistedKernelModules = [ "nvidiafb" ];
13 loader.timeout = 1;
14 loader.grub.devices = [ "/dev/sda" "/dev/sdb" ];
15 kernel.sysctl = {
16 # https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-001.md
17 "net.ipv4.tcp_sack" = 0;
18 };
19 supportedFilesystems = [ "zfs" ];
20 kernelParams = ["zfs.zfs_arc_max=6442450944"];
21 kernelPackages = pkgs.linuxPackages_latest;
22 initrd.availableKernelModules = [ "ahci" "sd_mod" ];
23 initrd.secrets = {
24 "/boot/pass.key" = "/boot/pass.key";
25 };
26 };
27 services.udev.extraRules = ''
28 ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="c8:60:00:56:a0:88", NAME="eth0"
29 '';
30 nix.maxJobs = 8;
31 powerManagement.cpuFreqGovernor = "powersave";
32 myEnv = import ../../../nixops/secrets/environment.nix;
33
34 fileSystems = {
35 # pools:
36 # zpool: ashift=12
37 # zfast: ashift=12
38 # zfs:
39 # zpool/: acltype=posixacl ; xattr=sa ; atime=off ; mountpoint=legacy
40 # zpool/root: encryption=on ; keyformat=passphrase ; keylocation=file:///boot/pass.key
41 # zpool/root/var: atime=on
42 # zfast/: acltype=posixacl ; xattr=sa ; atime=off ; mountpoint=legacy
43 # zfast/root: encryption=on ; keyformat=passphrase ; keylocation=file:///boot/pass.key
44 # zfast/root/etc: ø
45 # zfast/root/nix: ø
46 # zfast/root/tmp: async=disabled
47 # zfast/root/var: atime=on
48 # zfast/root/var/lib: ø
49 # zfast/root/var/lib/mysql: logbias=throughput ; atime=off ; primarycache=metadata
50 # zfast/root/var/lib/postgresql: recordsize=8K ; atime=off ; logbias=throughput
51 # zfast/root/var/lib/postgresql/11.0: ø
52 # zfast/root/var/lib/postgresql/11.0/pg_wal: ø
53 "/" = { fsType = "zfs"; device = "zpool/root"; };
54 "/boot" = { fsType = "ext4"; device = "/dev/disk/by-uuid/e6bb18fb-ff56-4b5f-ae9f-e60d40dc0622"; };
55 "/etc" = { fsType = "zfs"; device = "zpool/root/etc"; };
56 "/nix" = { fsType = "zfs"; device = "zfast/root/nix"; };
57 "/tmp" = { fsType = "zfs"; device = "zfast/root/tmp"; };
58 "/var" = { fsType = "zfs"; device = "zpool/root/var"; };
59 "/var/lib/mysql" = { fsType = "zfs"; device = "zfast/root/var/lib/mysql"; };
60 "/var/lib/postgresql" = { fsType = "zfs"; device = "zfast/root/var/lib/postgresql"; };
61 "/var/lib/postgresql/11.0" = { fsType = "zfs"; device = "zfast/root/var/lib/postgresql/11.0"; };
62 "/var/lib/postgresql/11.0/pg_wal" = { fsType = "zfs"; device = "zfast/root/var/lib/postgresql/11.0/pg_wal"; };
63 };
64 swapDevices = [ { label = "swap1"; } { label = "swap2"; } ];
65 hardware.enableRedistributableFirmware = true;
66
67 services.zfs = {
68 autoScrub = {
69 enable = false;
70 };
71 };
72 networking = {
73 hostId = "8262ca33"; # generated with head -c4 /dev/urandom | od -A none -t x4
74 firewall.enable = true;
75 # FIXME: on next reboot, remove the /27 and the localCommands
76 interfaces."eth0".ipv4.addresses =
77 pkgs.lib.attrsets.mapAttrsToList
78 (n: ips: { address = ips.ip4; prefixLength = 32; })
79 (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips)
80 ++ [ { address = config.hostEnv.ips.main.ip4; prefixLength = 27; } ];
81 interfaces."eth0".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
82 (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
83 config.hostEnv.ips);
84 defaultGateway = "176.9.151.65";
85 localCommands = ''
86 # FIXME: Those commands were added by nixops and may not be
87 # actually needed
88 ip -6 addr add '2a01:4f8:160:3445::/64' dev 'eth0' || true
89 ip -4 route change '176.9.151.64/27' via '176.9.151.65' dev 'eth0' || true
90 ip -6 route add default via 'fe80::1' dev eth0 || true
91 '';
92 nameservers = [
93 "213.133.98.98"
94 "213.133.99.99"
95 "213.133.100.100"
96 "2a01:4f8:0:a0a1::add:1010"
97 "2a01:4f8:0:a102::add:9999"
98 "2a01:4f8:0:a111::add:9898"
99 ];
100 };
101
102 imports = builtins.attrValues (import ../..);
103
104 myServices.buildbot.enable = true;
105 myServices.databases.enable = true;
106 myServices.gitolite.enable = true;
107 myServices.monitoring.enable = true;
108 myServices.irc.enable = true;
109 myServices.pub.enable = true;
110 myServices.tasks.enable = true;
111 myServices.mpd.enable = true;
112 myServices.dns.enable = true;
113 myServices.certificates.enable = true;
114 myServices.websites.enable = true;
115 myServices.gemini.enable = true;
116 myServices.mail.enable = true;
117 myServices.ejabberd.enable = true;
118 myServices.vpn.enable = true;
119 myServices.ftp.enable = true;
120
121 services.netdata.enable = true;
122 services.netdata.config.global."memory mode" = "none";
123 services.netdata.config.health."enabled" = "no";
124 services.netdata.config.web.mode = "none";
125 users.users."${config.services.netdata.user}".extraGroups = [ "keys" ];
126 environment.etc."netdata/stream.conf".source = config.secrets.fullPaths."netdata-stream.conf";
127 secrets.keys = {
128 "netdata-stream.conf" = {
129 user = config.services.netdata.user;
130 group = config.services.netdata.group;
131 permissions = "0400";
132 text = ''
133 [stream]
134 enabled = yes
135 destination = ${config.myEnv.monitoring.netdata_aggregator}
136 api key = ${config.myEnv.monitoring.netdata_keys.eldiron}
137 '';
138 };
139 "zrepl_backup/identity" = {
140 user = "root";
141 group = "root";
142 permissions = "0400";
143 text = config.myEnv.zrepl_backup.ssh_key.private;
144 };
145 };
146 programs.ssh.knownHosts.dilion = {
147 hostNames = ["dilion.immae.eu"];
148 publicKey = let
149 profile = config.myEnv.rsync_backup.profiles.dilion;
150 in
151 "${profile.host_key_type} ${profile.host_key}";
152 };
153
154 services.cron = {
155 enable = true;
156 mailto = "cron@immae.eu";
157 systemCronJobs = [
158 ''
159 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtpd -g "immae.eu.*Recipient address rejected"
160 # Need a way to blacklist properly
161 # 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtpd -g "NOQUEUE:"
162 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtp -g "status=bounced"
163 ''
164 ];
165 };
166
167 environment.systemPackages = [ pkgs.bindfs ];
168
169 services.zrepl = {
170 enable = true;
171 config = let
172 redis_dump = pkgs.writeScript "redis-dump" ''
173 #! ${pkgs.stdenv.shell}
174 ${pkgs.redis}/bin/redis-cli bgsave
175 '';
176 in ''
177 jobs:
178 - type: push
179 # must not change
180 name: "backup-to-dilion"
181 filesystems:
182 "zpool/root": true
183 "zpool/root/etc": true
184 "zpool/root/var<": true
185 connect:
186 type: ssh+stdinserver
187 host: dilion.immae.eu
188 user: backup
189 port: 22
190 identity_file: ${config.secrets.fullPaths."zrepl_backup/identity"}
191 snapshotting:
192 type: periodic
193 prefix: zrepl_
194 interval: 1h
195 #hooks:
196 # - type: mysql-lock-tables
197 # dsn: "${config.myEnv.zrepl_backup.mysql.user}:${config.myEnv.zrepl_backup.mysql.password}@tcp(localhost)/"
198 # filesystems:
199 # "zpool/root/var": true
200 # - type: command
201 # path: ${redis_dump}
202 # err_is_fatal: false
203 # filesystems:
204 # "zpool/root/var": true
205 send:
206 encrypted: true
207 pruning:
208 keep_sender:
209 - type: regex
210 regex: "^manual_.*"
211 - type: grid
212 grid: 24x1h | 7x1d | 4x7d | 6x30d
213 regex: "^zrepl_.*"
214 keep_receiver:
215 - type: regex
216 regex: "^manual_.*"
217 - type: grid
218 grid: 6x4h | 7x1d | 4x7d | 6x30d
219 regex: "^zrepl_.*"
220 '';
221 };
222 # This value determines the NixOS release with which your system is
223 # to be compatible, in order to avoid breaking some software such as
224 # database servers. You should change this only after NixOS release
225 # notes say you should.
226 # https://nixos.org/nixos/manual/release-notes.html
227 system.stateVersion = "20.03"; # Did you read the comment?
228}
diff --git a/modules/private/system/monitoring-1.nix b/modules/private/system/monitoring-1.nix
deleted file mode 100644
index dea5f45..0000000
--- a/modules/private/system/monitoring-1.nix
+++ /dev/null
@@ -1,69 +0,0 @@
1{ config, pkgs, resources, ... }:
2{
3 deployment = {
4 targetUser = "root";
5 targetHost = config.hostEnv.ips.main.ip4;
6 substituteOnDestination = true;
7 };
8 # ssh-keyscan monitoring-1 | nix-shell -p ssh-to-age --run ssh-to-age
9 secrets.ageKeys = [ "age1dn4lzhgxusqrpjjnzm7w8ml39ptf326htuzmpqdqs2gg3wq7cqzqxuvx8k" ];
10 boot.kernelPackages = pkgs.linuxPackages_latest;
11 myEnv = import ../../../nixops/secrets/environment.nix;
12
13 imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ] ++ builtins.attrValues (import ../..);
14
15 myServices.monitoring.enable = true;
16 myServices.monitoring.master = true;
17 myServices.status.enable = true;
18 networking = {
19 firewall.enable = true;
20 interfaces."ens3".ipv4.addresses = pkgs.lib.attrsets.mapAttrsToList
21 (n: ips: { address = ips.ip4; prefixLength = 32; })
22 (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips);
23 interfaces."ens3".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList
24 (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or []))
25 config.hostEnv.ips);
26 defaultGateway6 = { address = "fe80::1"; interface = "ens3"; };
27 };
28 boot.loader.grub.device = "nodev";
29 fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; };
30 myServices.mailRelay.enable = true;
31
32 security.pki.certificateFiles = [
33 (pkgs.fetchurl {
34 url = "http://downloads.e.eriomem.net/eriomemca.pem";
35 sha256 = "1ixx4c6j3m26j8dp9a3dkvxc80v1nr5aqgmawwgs06bskasqkvvh";
36 })
37 ];
38
39 services.netdata.enable = true;
40 services.netdata.config.web."allow dashboard from" = "localhost";
41 services.netdata.config.web."allow badges from" = "*";
42 services.netdata.config.web."allow streaming from" = "*";
43 services.netdata.config.web."allow netdata.conf from" = "fd*";
44 services.netdata.config.web."allow management from" = "fd*";
45 networking.firewall.allowedTCPPorts = [ 19999 ];
46 environment.etc."netdata/stream.conf".source = config.secrets.fullPaths."netdata-stream.conf";
47
48 secrets.keys = {
49 "netdata-stream.conf" = {
50 user = config.services.netdata.user;
51 group = config.services.netdata.group;
52 permissions = "0400";
53 text = builtins.concatStringsSep "\n" (pkgs.lib.mapAttrsToList (_: key: ''
54 [${key}]
55 enabled = yes
56 default history = 3600
57 default memory = ram
58 health enabled by default = auto
59 '') config.myEnv.monitoring.netdata_keys);
60 };
61 };
62 users.users."${config.services.netdata.user}".extraGroups = [ "keys" ];
63 # This value determines the NixOS release with which your system is
64 # to be compatible, in order to avoid breaking some software such as
65 # database servers. You should change this only after NixOS release
66 # notes say you should.
67 # https://nixos.org/nixos/manual/release-notes.html
68 system.stateVersion = "20.03"; # Did you read the comment?
69}
diff --git a/modules/private/system/quatresaisons.nix b/modules/private/system/quatresaisons.nix
deleted file mode 100644
index 82db70f..0000000
--- a/modules/private/system/quatresaisons.nix
+++ /dev/null
@@ -1,436 +0,0 @@
1{ config, pkgs, lib, ... }:
2let
3 serverSpecificConfig = config.myEnv.serverSpecific.quatresaisons;
4 yarnModules = pkgs.yarn2nix-moretea.mkYarnModules rec {
5 name = "landing";
6 pname = name;
7 version = "v1.0.0";
8 packageJSON = "${pkgs.sources.webapps-landing}/package.json";
9 yarnLock = "${pkgs.sources.webapps-landing}/yarn.lock";
10 yarnNix = ../websites/tools/tools/landing/yarn-packages.nix;
11 };
12 toLanding = landingConfig: pkgs.stdenv.mkDerivation rec {
13 pname = "landing";
14 version = "v1.0.0";
15 src = pkgs.sources.webapps-landing;
16
17 buildInputs = [ yarnModules pkgs.yarn2nix-moretea.yarn ];
18 configurePhase = ''
19 ln -s ${yarnModules}/node_modules .
20 '';
21 buildPhase = ''
22 yarn build
23 '';
24 installPhase = ''
25 cp -a dist $out
26 cp -f ${landingConfig} $out/config.yml
27 ln -s service-worker.js $out/worker.js
28 '';
29 };
30 normalUsers = serverSpecificConfig.users;
31 sponsoredUser = pkgs.writeScriptBin "sponsored_user" ''
32 #!/usr/bin/env bash
33
34 set -euo pipefail
35 [ -z "''${SUDO_USER+x}" ] && echo "Must be run with sudo" && exit 1
36
37 mygroup=$(id -ng $SUDO_USER)
38
39 sponsored=$(getent group $mygroup | cut -d':' -f4)
40
41 echo "Sponsored users: ''${sponsored:-<none>}"
42
43 log () {
44 touch /var/log/sponsored_users
45 chmod go-rwx /var/log/sponsored_users
46 echo "`date` $mygroup $1" | LANG=C cat -v | tr '\012' ' ' | sed 's:$:\x0a:' >> /var/log/sponsored_users
47 }
48
49 create_user () {
50 log "creates $1: $2"
51 useradd -m -G users,$mygroup -g $mygroup -p '!' "$1"
52 touch /var/lib/nixos/sponsored_users
53 chmod go-rwx /var/lib/nixos/sponsored_users
54 echo "$mygroup $1 $2" >> /var/lib/nixos/sponsored_users
55 (${pkgs.openldap}/bin/ldapadd -c -D cn=root,dc=salle-s,dc=org \
56 -y ${config.secrets.fullPaths."ldap/sync_password"} 2>/dev/null >/dev/null || true) <<EOF
57 dn: uid=$1,uid=$mygroup,ou=users,dc=salle-s,dc=org
58 objectClass: inetOrgPerson
59 cn: $1
60 description:: $(echo -n "$2" | base64)
61 sn: $1
62 uid: $1
63 EOF
64 while ! passwd "$1"; do
65 echo "please give an initial password"
66 done
67 }
68
69 delete_user () {
70 IFS=",";
71 for u in $sponsored; do
72 if [ "$u" = "$1" ]; then
73 log "deletes $1"
74 userdel -r "$1"
75 sed -i -e "/^$mygroup $1/d" /var/lib/nixos/sponsored_users
76 ${pkgs.openldap}/bin/ldapdelete -D cn=root,dc=salle-s,dc=org \
77 -y ${config.secrets.fullPaths."ldap/sync_password"} \
78 "uid=$1,uid=$mygroup,ou=users,dc=salle-s,dc=org"
79 echo "deleted"
80 exit 0
81 fi
82 done
83
84 echo "User does not exist or does not belong to you";
85 exit 1
86 }
87
88 reset_password () {
89 IFS=",";
90 for u in $sponsored; do
91 if [ "$u" = "$1" ]; then
92 log "resets password for $1"
93 passwd "$1"
94 exit 0
95 fi
96 done
97
98 echo "User does not exist or does not belong to you";
99 exit 1
100 }
101
102 reset_ldap_password () {
103 if [ "$1" = "$mygroup" ]; then
104 log "resets web password"
105 ${pkgs.openldap}/bin/ldappasswd -D cn=root,dc=salle-s,dc=org \
106 -y ${config.secrets.fullPaths."ldap/sync_password"} \
107 -S "uid=$mygroup,ou=users,dc=salle-s,dc=org"
108 else
109 IFS=",";
110 for u in $sponsored; do
111 if [ "$u" = "$1" ]; then
112 log "resets web password of $1"
113 ${pkgs.openldap}/bin/ldappasswd -D cn=root,dc=salle-s,dc=org \
114 -y ${config.secrets.fullPaths."ldap/sync_password"} \
115 -S "uid=$1,uid=$mygroup,ou=users,dc=salle-s,dc=org"
116 exit 0
117 fi
118 done
119
120 echo "User does not exist or does not belong to you";
121 exit 1
122 fi
123 }
124
125 show_help () {
126 echo "sponsored_users create username realname"
127 echo " create a new sub-user attached to your account"
128 echo "sponsored_users (delete|reset_password) username"
129 echo " delete a sub-user attached to your account or reset his password"
130 echo "sponsored_users reset_ldap_password username"
131 echo " reset the web password of a sub-user or yourself"
132 }
133
134 [ -z "''${1+x}" -o -z "''${2+x}" ] && { show_help ; exit 0; }
135 action="$1"
136 username="$2"
137 shift
138 shift
139
140 case "$action" in
141 create)
142 [ -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; }
143 create_user "$username" "$*";
144 ;;
145 delete)
146 delete_user "$username";
147 ;;
148 reset_password)
149 reset_password "$username";
150 ;;
151 reset_ldap_password)
152 reset_ldap_password "$username";
153 ;;
154 *)
155 show_help
156 ;;
157 esac
158 '';
159in
160{
161 deployment = {
162 targetUser = "root";
163 targetHost = config.hostEnv.ips.main.ip4;
164 substituteOnDestination = true;
165 };
166 # ssh-keyscan quatresaison | nix-shell -p ssh-to-age --run ssh-to-age
167 secrets.ageKeys = [ "age1yz8u6xvh2fltvyp96ep8crce3qx4tuceyhun6pwddfe0uvcrkarscxl7e7" ];
168
169 programs.ssh.package = pkgs.openssh.overrideAttrs(old: {
170 PATH_PASSWD_PROG = "/run/wrappers/bin/passwd";
171 buildFlags = [ "SSH_KEYSIGN=/run/wrappers/bin/ssh-keysign" ];
172 });
173
174 imports = builtins.attrValues (import ../..) ++
175 [ ./quatresaisons/nextcloud.nix ./quatresaisons/databases.nix ];
176
177 myEnv = import ../../../nixops/secrets/environment.nix;
178
179 fileSystems = {
180 "/" = { device = "/dev/disk/by-uuid/865931b4-c5cc-439f-8e42-8072c7a30634"; fsType = "ext4"; };
181 "/home" = { device = "/dev/disk/by-uuid/76020bc4-5b88-464c-8952-9a59072c597f"; fsType = "ext4"; neededForBoot = true; };
182 "/boot" = { device = "/dev/disk/by-uuid/0fb8421a-61e5-4ed5-a795-4dd3a9b2152a"; fsType = "ext4"; };
183 "/var/lib" = { device = "/home/var_lib"; fsType = "none"; options = [ "defaults,bind" ]; };
184 };
185 powerManagement.cpuFreqGovernor = "powersave";
186 hardware.enableRedistributableFirmware = true;
187
188 boot.initrd.availableKernelModules = [ "ahci" "megaraid_sas" "sd_mod" ];
189 boot.initrd.kernelModules = [ "dm-snapshot" ];
190 boot.kernelModules = [ "kvm-intel" ];
191
192 boot.loader.grub.enable = true;
193 boot.loader.grub.version = 2;
194 boot.loader.grub.device = "/dev/sda";
195
196 networking.firewall.enable = false;
197 networking.firewall.allowedTCPPorts = [ 80 443 ];
198 networking.useDHCP = false;
199 networking.interfaces.eth0.useDHCP = true;
200 networking.interfaces.eth0.ipv6.addresses = [
201 { address = pkgs.lib.head config.hostEnv.ips.main.ip6; prefixLength = 64; }
202 ];
203 networking.defaultGateway6 = { address = "fe80::1"; interface = "eth0"; };
204 services.udev.extraRules = ''
205 ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="c8:60:00:8b:2f:f0", NAME="eth0"
206 '';
207 security.pam.services.chage.text = ''
208 auth sufficient pam_rootok.so
209 auth required pam_unix.so
210 account required pam_unix.so
211 session required pam_unix.so
212 password required pam_permit.so
213 '';
214 security.pam.services.sshd.makeHomeDir = true;
215 security.pam.services.passwd_default = {};
216 security.pam.services.passwd.text = ''
217 password required pam_cracklib.so enforce_for_root difok=2 minlen=8 dcredit=2 ocredit=2 retry=3
218 '' + config.security.pam.services.passwd_default.text;
219
220 system.activationScripts.ldapSync = {
221 deps = [ "secrets" "users" ];
222 text =
223 let
224 com = "-D cn=root,dc=salle-s,dc=org -y ${config.secrets.fullPaths."ldap/sync_password"}";
225 in ''
226 # Add users
227 ${pkgs.openldap}/bin/ldapadd -c ${com} -f ${config.secrets.fullPaths."ldap/ldaptree.ldif"} 2>/dev/null >/dev/null || true
228
229 # Remove obsolete users
230 ${pkgs.openldap}/bin/ldapsearch -LLL ${com} -s one -b "ou=users,dc=salle-s,dc=org" "uid" |\
231 grep "^uid" | ${pkgs.gnused}/bin/sed -e "s/uid: //" | while read ldapuser; do
232
233 for user in ${builtins.concatStringsSep " " (builtins.attrNames normalUsers)}; do
234 if [ "$user" = "$ldapuser" ]; then
235 continue 2
236 fi
237 done
238 ${pkgs.openldap}/bin/ldapdelete -r ${com} uid=$ldapuser,ou=users,dc=salle-s,dc=org
239 done
240
241 # Subusers
242 if [ -f /var/lib/nixos/sponsored_users ]; then
243 cat /var/lib/nixos/sponsored_users | while read mainUser subUser name; do
244 (${pkgs.openldap}/bin/ldapadd -c ${com} 2>/dev/null >/dev/null || true) <<EOF
245 dn: uid=$subUser,uid=$mainUser,ou=users,dc=salle-s,dc=org
246 objectClass: inetOrgPerson
247 cn: $subUser
248 description:: $(echo -n "$name" | base64)
249 sn: $subUser
250 uid: $subUser
251 EOF
252 done
253 fi
254 '';
255 };
256
257 secrets.keys = {
258 "ldap/sync_password" = {
259 permissions = "0400";
260 text = serverSpecificConfig.ldap_sync_password;
261 };
262 "ldap/ldaptree.ldif" = {
263 permissions = "0400";
264 text = serverSpecificConfig.ldap_service_users
265 + (builtins.concatStringsSep "\n" (lib.mapAttrsToList (n: v: ''
266 dn: uid=${n},ou=users,dc=salle-s,dc=org
267 objectClass: inetOrgPerson
268 cn: ${n}
269 description: ${v._meta.name or n} ${v._meta.email}
270 sn: ${n}
271 uid: ${n}
272 '') normalUsers));
273 };
274 };
275
276 myServices.monitoring.enable = true;
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 { command = "/run/current-system/sw/bin/sponsored_user"; options = [ "NOPASSWD" ]; }
337 ];
338 users = builtins.attrNames normalUsers;
339 runAs = "root";
340 }
341 ];
342
343 environment.systemPackages = [
344 sponsoredUser
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
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}
diff --git a/modules/private/system/quatresaisons/databases.nix b/modules/private/system/quatresaisons/databases.nix
deleted file mode 100644
index f7b27e0..0000000
--- a/modules/private/system/quatresaisons/databases.nix
+++ /dev/null
@@ -1,147 +0,0 @@
1{ pkgs, config, lib, ... }:
2{
3 config = let
4 serverSpecificConfig = config.myEnv.serverSpecific.quatresaisons;
5 phpLdapAdmin = pkgs.webapps.phpldapadmin.override { config = config.secrets.fullPaths."webapps/tools-ldap"; };
6 in {
7 services.postgresql.enable = true;
8 services.postgresql.package = pkgs.postgresql_12;
9 services.postgresql.ensureUsers = [
10 { name = "naemon"; }
11 ];
12 secrets.keys = {
13 "ldap/password" = {
14 permissions = "0400";
15 user = "openldap";
16 group = "openldap";
17 text = "rootpw ${serverSpecificConfig.ldap_root_pw}";
18 };
19 "webapps/tools-ldap" = {
20 user = "wwwrun";
21 group = "wwwrun";
22 permissions = "0400";
23 text = ''
24 <?php
25 $config->custom->appearance['show_clear_password'] = true;
26 $config->custom->appearance['hide_template_warning'] = true;
27 $config->custom->appearance['theme'] = "tango";
28 $config->custom->appearance['minimalMode'] = false;
29 $config->custom->appearance['tree'] = 'AJAXTree';
30
31 $servers = new Datastore();
32
33 $servers->newServer('ldap_pla');
34 $servers->setValue('server','name','LDAP');
35 $servers->setValue('server','host','ldap://localhost');
36 $servers->setValue('login','auth_type','cookie');
37 $servers->setValue('login','bind_id','${serverSpecificConfig.ldap_phpldapadmin_dn}');
38 $servers->setValue('login','bind_pass','${serverSpecificConfig.ldap_phpldapadmin_password}');
39 $servers->setValue('appearance','pla_password_hash','ssha');
40 $servers->setValue('login','attr','uid');
41 $servers->setValue('login','fallback_dn',true);
42 '';
43 };
44 };
45
46 users.users.openldap.extraGroups = [ "keys" ];
47 services.openldap = {
48 enable = true;
49 dataDir = "/var/lib/openldap";
50 urlList = [ "ldap://localhost" ];
51 logLevel = "none";
52 extraConfig = ''
53 pidfile /run/slapd/slapd.pid
54 argsfile /run/slapd/slapd.args
55
56 moduleload back_hdb
57 backend hdb
58 '';
59
60 extraDatabaseConfig = ''
61 moduleload memberof
62 overlay memberof
63
64 moduleload syncprov
65 overlay syncprov
66 syncprov-checkpoint 100 10
67
68 index objectClass eq
69 index uid pres,eq
70 #index uidMember pres,eq
71 index mail pres,sub,eq
72 index cn pres,sub,eq
73 index sn pres,sub,eq
74 index dc eq
75 index member eq
76 index memberOf eq
77
78 # No one must access that information except root
79 access to attrs=description
80 by * none
81
82 access to attrs=entry,uid filter="(uid=*)"
83 by dn.exact="${serverSpecificConfig.ldap_phpldapadmin_dn}" read
84 by * break
85
86 access to dn.subtree="ou=users,dc=salle-s,dc=org"
87 by dn.subtree="ou=services,dc=salle-s,dc=org" read
88 by * break
89
90 access to *
91 by self read
92 by anonymous auth
93 by * break
94 '';
95 rootpwFile = config.secrets.fullPaths."ldap/password";
96 suffix = "dc=salle-s,dc=org";
97 rootdn = "cn=root,dc=salle-s,dc=org";
98 database = "hdb";
99 };
100
101 services.websites.env.production.modules = [ "proxy_fcgi" ];
102 services.websites.env.production.vhostConfs.tools.extraConfig = [
103 ''
104 Alias /ldap "${phpLdapAdmin}/htdocs"
105 <Directory "${phpLdapAdmin}/htdocs">
106 DirectoryIndex index.php
107 <FilesMatch "\.php$">
108 SetHandler "proxy:unix:${config.services.phpfpm.pools.ldap.socket}|fcgi://localhost"
109 </FilesMatch>
110
111 AllowOverride None
112 Require all granted
113 </Directory>
114 ''
115 ];
116 services.phpfpm.pools.ldap = {
117 user = "wwwrun";
118 group = "wwwrun";
119 settings =
120 let
121 basedir = builtins.concatStringsSep ":" [ phpLdapAdmin config.secrets.fullPaths."webapps/tools-ldap" ];
122 in {
123 "listen.owner" = "wwwrun";
124 "listen.group" = "wwwrun";
125 "pm" = "ondemand";
126 "pm.max_children" = "60";
127 "pm.process_idle_timeout" = "60";
128
129 # Needed to avoid clashes in browser cookies (same domain)
130 "php_value[session.name]" = "LdapPHPSESSID";
131 "php_admin_value[open_basedir]" = "${basedir}:/tmp:/var/lib/php/sessions/phpldapadmin";
132 "php_admin_value[session.save_path]" = "/var/lib/php/sessions/phpldapadmin";
133 };
134 phpPackage = pkgs.php72;
135 };
136 system.activationScripts.ldap = {
137 deps = [ "users" ];
138 text = ''
139 install -m 0755 -o wwwrun -g wwwrun -d /var/lib/php/sessions/phpldapadmin
140 '';
141 };
142 systemd.services.phpfpm-ldap = {
143 after = lib.mkAfter [ "openldap.service" ];
144 wants = [ "openldap.service" ];
145 };
146 };
147}
diff --git a/modules/private/system/quatresaisons/landing.yml b/modules/private/system/quatresaisons/landing.yml
deleted file mode 100644
index cf4ba87..0000000
--- a/modules/private/system/quatresaisons/landing.yml
+++ /dev/null
@@ -1,32 +0,0 @@
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
deleted file mode 100644
index 0b9f6b6..0000000
--- a/modules/private/system/quatresaisons/landing_4c.yml
+++ /dev/null
@@ -1,24 +0,0 @@
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
deleted file mode 100644
index 89d69d5..0000000
--- a/modules/private/system/quatresaisons/nextcloud.nix
+++ /dev/null
@@ -1,141 +0,0 @@
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 -E -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}