diff options
Diffstat (limited to 'modules/private/system')
-rw-r--r-- | modules/private/system/backup-2.nix | 137 | ||||
-rw-r--r-- | modules/private/system/dilion.nix | 242 | ||||
-rw-r--r-- | modules/private/system/dilion/vms.nix | 185 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/base_configuration.nix | 21 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/base_image.nix | 94 | ||||
-rw-r--r-- | modules/private/system/dilion/vms/buildbot_configuration.nix | 67 | ||||
-rw-r--r-- | modules/private/system/eldiron.nix | 228 | ||||
-rw-r--r-- | modules/private/system/monitoring-1.nix | 69 | ||||
-rw-r--r-- | modules/private/system/quatresaisons.nix | 436 | ||||
-rw-r--r-- | modules/private/system/quatresaisons/databases.nix | 147 | ||||
-rw-r--r-- | modules/private/system/quatresaisons/landing.yml | 32 | ||||
-rw-r--r-- | modules/private/system/quatresaisons/landing_4c.yml | 24 | ||||
-rw-r--r-- | modules/private/system/quatresaisons/nextcloud.nix | 141 |
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: | ||
3 | let | ||
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"; | ||
56 | in | ||
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 @@ | |||
1 | configuration_file: { pkgs ? import <nixpkgs> {}, system ? builtins.currentSystem, myEnv, ... }: | ||
2 | let | ||
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; | ||
25 | in 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, ... }: | ||
2 | let | ||
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 | ''; | ||
159 | in | ||
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 | |||
5 | title: "Websites dashboard" | ||
6 | subtitle: "Salle-S" | ||
7 | footer: 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 | ||
12 | links: [] | ||
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). | ||
17 | services: | ||
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 | |||
5 | title: "Websites dashboard" | ||
6 | subtitle: "Quatre saisons" | ||
7 | footer: 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 | ||
12 | links: [] | ||
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). | ||
17 | services: | ||
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, ... }: | ||
2 | let | ||
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 | }; | ||
37 | in { | ||
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 | } | ||