diff options
Diffstat (limited to 'systems/monitoring-1')
-rw-r--r-- | systems/monitoring-1/base.nix | 75 | ||||
-rw-r--r-- | systems/monitoring-1/flake.lock | 790 | ||||
-rw-r--r-- | systems/monitoring-1/flake.nix | 45 | ||||
-rw-r--r-- | systems/monitoring-1/monitoring-master.nix | 87 | ||||
-rw-r--r-- | systems/monitoring-1/monitoring.nix | 61 | ||||
-rw-r--r-- | systems/monitoring-1/monitoring/master.nix | 43 | ||||
-rw-r--r-- | systems/monitoring-1/monitoring/phare.nix | 20 | ||||
-rw-r--r-- | systems/monitoring-1/monitoring/ulminfo-fr.nix | 20 | ||||
-rw-r--r-- | systems/monitoring-1/status.nix | 84 | ||||
-rwxr-xr-x | systems/monitoring-1/status/app.py | 414 | ||||
-rw-r--r-- | systems/monitoring-1/status_engine.nix | 123 |
11 files changed, 1762 insertions, 0 deletions
diff --git a/systems/monitoring-1/base.nix b/systems/monitoring-1/base.nix new file mode 100644 index 0000000..8bfacc1 --- /dev/null +++ b/systems/monitoring-1/base.nix | |||
@@ -0,0 +1,75 @@ | |||
1 | { config, pkgs, lib, nixpkgs, php, secrets, ... }: | ||
2 | { | ||
3 | # ssh-keyscan monitoring-1 | nix-shell -p ssh-to-age --run ssh-to-age | ||
4 | secrets.ageKeys = [ "age1dn4lzhgxusqrpjjnzm7w8ml39ptf326htuzmpqdqs2gg3wq7cqzqxuvx8k" ]; | ||
5 | boot.kernelPackages = pkgs.linuxPackages_latest; | ||
6 | |||
7 | imports = [ | ||
8 | secrets.nixosModules.users-config-monitoring-1 | ||
9 | (nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") | ||
10 | ./monitoring-master.nix | ||
11 | ./monitoring.nix | ||
12 | ./status.nix | ||
13 | ./status_engine.nix | ||
14 | ]; | ||
15 | |||
16 | nixpkgs.overlays = builtins.attrValues php.overlays; | ||
17 | nixpkgs.config.permittedInsecurePackages = [ | ||
18 | "python-2.7.18.6" # for nagios-cli | ||
19 | ]; | ||
20 | |||
21 | myServices.monitoring.enable = true; | ||
22 | myServices.monitoring.master = true; | ||
23 | myServices.status.enable = true; | ||
24 | networking = { | ||
25 | firewall.enable = true; | ||
26 | interfaces."ens3".ipv4.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | ||
27 | (n: ips: map (ip: { address = ip; prefixLength = 32; }) (ips.ip4 or [])) | ||
28 | (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips)); | ||
29 | interfaces."ens3".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | ||
30 | (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or [])) | ||
31 | config.hostEnv.ips); | ||
32 | defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; | ||
33 | }; | ||
34 | boot.loader.grub.device = "nodev"; | ||
35 | fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; | ||
36 | myServices.mailRelay.enable = true; | ||
37 | |||
38 | security.pki.certificateFiles = [ | ||
39 | (pkgs.fetchurl { | ||
40 | url = "http://downloads.e.eriomem.net/eriomemca.pem"; | ||
41 | sha256 = "1ixx4c6j3m26j8dp9a3dkvxc80v1nr5aqgmawwgs06bskasqkvvh"; | ||
42 | }) | ||
43 | ]; | ||
44 | |||
45 | services.netdata.enable = true; | ||
46 | services.netdata.configDir."stream.conf" = config.secrets.fullPaths."netdata-stream.conf"; | ||
47 | services.netdata.config.web."allow dashboard from" = "localhost"; | ||
48 | services.netdata.config.web."allow badges from" = "*"; | ||
49 | services.netdata.config.web."allow streaming from" = "*"; | ||
50 | services.netdata.config.web."allow netdata.conf from" = "fd*"; | ||
51 | services.netdata.config.web."allow management from" = "fd*"; | ||
52 | networking.firewall.allowedTCPPorts = [ 19999 ]; | ||
53 | |||
54 | secrets.keys = { | ||
55 | "netdata-stream.conf" = { | ||
56 | user = config.services.netdata.user; | ||
57 | group = config.services.netdata.group; | ||
58 | permissions = "0400"; | ||
59 | text = builtins.concatStringsSep "\n" (pkgs.lib.mapAttrsToList (_: key: '' | ||
60 | [${key}] | ||
61 | enabled = yes | ||
62 | default history = 3600 | ||
63 | default memory = ram | ||
64 | health enabled by default = auto | ||
65 | '') config.myEnv.monitoring.netdata_keys); | ||
66 | }; | ||
67 | }; | ||
68 | users.users."${config.services.netdata.user}".extraGroups = [ "keys" ]; | ||
69 | # This value determines the NixOS release with which your system is | ||
70 | # to be compatible, in order to avoid breaking some software such as | ||
71 | # database servers. You should change this only after NixOS release | ||
72 | # notes say you should. | ||
73 | # https://nixos.org/nixos/manual/release-notes.html | ||
74 | system.stateVersion = "23.05"; # Did you read the comment? | ||
75 | } | ||
diff --git a/systems/monitoring-1/flake.lock b/systems/monitoring-1/flake.lock new file mode 100644 index 0000000..d4a2c8d --- /dev/null +++ b/systems/monitoring-1/flake.lock | |||
@@ -0,0 +1,790 @@ | |||
1 | { | ||
2 | "nodes": { | ||
3 | "backports": { | ||
4 | "inputs": { | ||
5 | "flake-utils": "flake-utils_3", | ||
6 | "nixpkgs": "nixpkgs_7" | ||
7 | }, | ||
8 | "locked": { | ||
9 | "lastModified": 1, | ||
10 | "narHash": "sha256-VewHWeZvwLvWVm2bMQk5UQ0G/HyO8X87BssvmbLWbrY=", | ||
11 | "path": "../../backports", | ||
12 | "type": "path" | ||
13 | }, | ||
14 | "original": { | ||
15 | "path": "../../backports", | ||
16 | "type": "path" | ||
17 | } | ||
18 | }, | ||
19 | "chatons": { | ||
20 | "inputs": { | ||
21 | "environment": "environment" | ||
22 | }, | ||
23 | "locked": { | ||
24 | "lastModified": 1, | ||
25 | "narHash": "sha256-UNkS/IZGHCdSX4hCzpTZwNBj9B8RGCMr9Za+G9Xdm4Y=", | ||
26 | "path": "../../flakes/private/chatons", | ||
27 | "type": "path" | ||
28 | }, | ||
29 | "original": { | ||
30 | "path": "../../flakes/private/chatons", | ||
31 | "type": "path" | ||
32 | } | ||
33 | }, | ||
34 | "colmena": { | ||
35 | "inputs": { | ||
36 | "flake-compat": "flake-compat", | ||
37 | "flake-utils": "flake-utils", | ||
38 | "nixpkgs": "nixpkgs", | ||
39 | "stable": "stable" | ||
40 | }, | ||
41 | "locked": { | ||
42 | "lastModified": 1687954574, | ||
43 | "narHash": "sha256-YasVTaNXq2xqZdejyIhuyqvNypmx+K/Y1ZZ4+raeeII=", | ||
44 | "owner": "immae", | ||
45 | "repo": "colmena", | ||
46 | "rev": "e427171150a35e23204c4c15a2483358d22a0eff", | ||
47 | "type": "github" | ||
48 | }, | ||
49 | "original": { | ||
50 | "owner": "immae", | ||
51 | "ref": "add-lib-get-flake", | ||
52 | "repo": "colmena", | ||
53 | "type": "github" | ||
54 | } | ||
55 | }, | ||
56 | "disko": { | ||
57 | "inputs": { | ||
58 | "nixpkgs": "nixpkgs_2" | ||
59 | }, | ||
60 | "locked": { | ||
61 | "lastModified": 1687968164, | ||
62 | "narHash": "sha256-L9jr2zCB6NIaBE3towusjGBigsnE2pMID8wBGkYbTS4=", | ||
63 | "owner": "nix-community", | ||
64 | "repo": "disko", | ||
65 | "rev": "8002e7cb899bc2a02a2ebfb7f999fcd7c18b92a1", | ||
66 | "type": "github" | ||
67 | }, | ||
68 | "original": { | ||
69 | "owner": "nix-community", | ||
70 | "repo": "disko", | ||
71 | "type": "github" | ||
72 | } | ||
73 | }, | ||
74 | "environment": { | ||
75 | "locked": { | ||
76 | "lastModified": 1, | ||
77 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
78 | "path": "../environment", | ||
79 | "type": "path" | ||
80 | }, | ||
81 | "original": { | ||
82 | "path": "../environment", | ||
83 | "type": "path" | ||
84 | } | ||
85 | }, | ||
86 | "environment_2": { | ||
87 | "locked": { | ||
88 | "lastModified": 1, | ||
89 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
90 | "path": "../../flakes/private/environment", | ||
91 | "type": "path" | ||
92 | }, | ||
93 | "original": { | ||
94 | "path": "../../flakes/private/environment", | ||
95 | "type": "path" | ||
96 | } | ||
97 | }, | ||
98 | "environment_3": { | ||
99 | "locked": { | ||
100 | "lastModified": 1, | ||
101 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
102 | "path": "../environment", | ||
103 | "type": "path" | ||
104 | }, | ||
105 | "original": { | ||
106 | "path": "../environment", | ||
107 | "type": "path" | ||
108 | } | ||
109 | }, | ||
110 | "environment_4": { | ||
111 | "locked": { | ||
112 | "lastModified": 1, | ||
113 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
114 | "path": "../environment", | ||
115 | "type": "path" | ||
116 | }, | ||
117 | "original": { | ||
118 | "path": "../environment", | ||
119 | "type": "path" | ||
120 | } | ||
121 | }, | ||
122 | "environment_5": { | ||
123 | "locked": { | ||
124 | "lastModified": 1, | ||
125 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
126 | "path": "../environment", | ||
127 | "type": "path" | ||
128 | }, | ||
129 | "original": { | ||
130 | "path": "../environment", | ||
131 | "type": "path" | ||
132 | } | ||
133 | }, | ||
134 | "files-watcher": { | ||
135 | "locked": { | ||
136 | "lastModified": 1, | ||
137 | "narHash": "sha256-ZsdumUVoSPkV/DB6gO6dNDttjzalye0ToVBF9bl5W0k=", | ||
138 | "path": "../../flakes/files-watcher", | ||
139 | "type": "path" | ||
140 | }, | ||
141 | "original": { | ||
142 | "path": "../../flakes/files-watcher", | ||
143 | "type": "path" | ||
144 | } | ||
145 | }, | ||
146 | "flake-compat": { | ||
147 | "flake": false, | ||
148 | "locked": { | ||
149 | "lastModified": 1650374568, | ||
150 | "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", | ||
151 | "owner": "edolstra", | ||
152 | "repo": "flake-compat", | ||
153 | "rev": "b4a34015c698c7793d592d66adbab377907a2be8", | ||
154 | "type": "github" | ||
155 | }, | ||
156 | "original": { | ||
157 | "owner": "edolstra", | ||
158 | "repo": "flake-compat", | ||
159 | "type": "github" | ||
160 | } | ||
161 | }, | ||
162 | "flake-parts": { | ||
163 | "inputs": { | ||
164 | "nixpkgs-lib": "nixpkgs-lib_2" | ||
165 | }, | ||
166 | "locked": { | ||
167 | "lastModified": 1687762428, | ||
168 | "narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=", | ||
169 | "owner": "hercules-ci", | ||
170 | "repo": "flake-parts", | ||
171 | "rev": "37dd7bb15791c86d55c5121740a1887ab55ee836", | ||
172 | "type": "github" | ||
173 | }, | ||
174 | "original": { | ||
175 | "owner": "hercules-ci", | ||
176 | "repo": "flake-parts", | ||
177 | "type": "github" | ||
178 | } | ||
179 | }, | ||
180 | "flake-parts_2": { | ||
181 | "inputs": { | ||
182 | "nixpkgs-lib": "nixpkgs-lib_3" | ||
183 | }, | ||
184 | "locked": { | ||
185 | "lastModified": 1675295133, | ||
186 | "narHash": "sha256-dU8fuLL98WFXG0VnRgM00bqKX6CEPBLybhiIDIgO45o=", | ||
187 | "owner": "hercules-ci", | ||
188 | "repo": "flake-parts", | ||
189 | "rev": "bf53492df08f3178ce85e0c9df8ed8d03c030c9f", | ||
190 | "type": "github" | ||
191 | }, | ||
192 | "original": { | ||
193 | "owner": "hercules-ci", | ||
194 | "repo": "flake-parts", | ||
195 | "type": "github" | ||
196 | } | ||
197 | }, | ||
198 | "flake-utils": { | ||
199 | "locked": { | ||
200 | "lastModified": 1659877975, | ||
201 | "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", | ||
202 | "owner": "numtide", | ||
203 | "repo": "flake-utils", | ||
204 | "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", | ||
205 | "type": "github" | ||
206 | }, | ||
207 | "original": { | ||
208 | "owner": "numtide", | ||
209 | "repo": "flake-utils", | ||
210 | "type": "github" | ||
211 | } | ||
212 | }, | ||
213 | "flake-utils_2": { | ||
214 | "locked": { | ||
215 | "lastModified": 1648297722, | ||
216 | "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", | ||
217 | "owner": "numtide", | ||
218 | "repo": "flake-utils", | ||
219 | "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", | ||
220 | "type": "github" | ||
221 | }, | ||
222 | "original": { | ||
223 | "owner": "numtide", | ||
224 | "repo": "flake-utils", | ||
225 | "type": "github" | ||
226 | } | ||
227 | }, | ||
228 | "flake-utils_3": { | ||
229 | "locked": { | ||
230 | "lastModified": 1667395993, | ||
231 | "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", | ||
232 | "owner": "numtide", | ||
233 | "repo": "flake-utils", | ||
234 | "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", | ||
235 | "type": "github" | ||
236 | }, | ||
237 | "original": { | ||
238 | "owner": "numtide", | ||
239 | "repo": "flake-utils", | ||
240 | "type": "github" | ||
241 | } | ||
242 | }, | ||
243 | "loginctl-linger": { | ||
244 | "locked": { | ||
245 | "lastModified": 1, | ||
246 | "narHash": "sha256-TLlUOhiQzYo6SwH0E3oPCDfhgW249qPZTlVar1VmpKw=", | ||
247 | "path": "../../flakes/loginctl-linger", | ||
248 | "type": "path" | ||
249 | }, | ||
250 | "original": { | ||
251 | "path": "../../flakes/loginctl-linger", | ||
252 | "type": "path" | ||
253 | } | ||
254 | }, | ||
255 | "mail-relay": { | ||
256 | "inputs": { | ||
257 | "environment": "environment_3", | ||
258 | "secrets": "secrets" | ||
259 | }, | ||
260 | "locked": { | ||
261 | "lastModified": 1, | ||
262 | "narHash": "sha256-xISja892g6YTu9YjGwaD36BBWi/1+IcuREw6iUDqfVw=", | ||
263 | "path": "../../flakes/private/mail-relay", | ||
264 | "type": "path" | ||
265 | }, | ||
266 | "original": { | ||
267 | "path": "../../flakes/private/mail-relay", | ||
268 | "type": "path" | ||
269 | } | ||
270 | }, | ||
271 | "monitoring": { | ||
272 | "inputs": { | ||
273 | "environment": "environment_4", | ||
274 | "naemon": "naemon", | ||
275 | "nixpkgs-lib": "nixpkgs-lib", | ||
276 | "secrets": "secrets_2" | ||
277 | }, | ||
278 | "locked": { | ||
279 | "lastModified": 1, | ||
280 | "narHash": "sha256-K720bqCEHPK0F7GBaxo/ioJ3LVAyhjl/ZZobWwO4ebU=", | ||
281 | "path": "../../flakes/private/monitoring", | ||
282 | "type": "path" | ||
283 | }, | ||
284 | "original": { | ||
285 | "path": "../../flakes/private/monitoring", | ||
286 | "type": "path" | ||
287 | } | ||
288 | }, | ||
289 | "my-lib": { | ||
290 | "inputs": { | ||
291 | "colmena": "colmena", | ||
292 | "disko": "disko", | ||
293 | "flake-parts": "flake-parts", | ||
294 | "nixos-anywhere": "nixos-anywhere", | ||
295 | "nixpkgs": "nixpkgs_4" | ||
296 | }, | ||
297 | "locked": { | ||
298 | "lastModified": 1, | ||
299 | "narHash": "sha256-wwpT+I5/zrln85BDzlZoEDC19GwYrcZSXbrJjyvC4jk=", | ||
300 | "path": "../../flakes/lib", | ||
301 | "type": "path" | ||
302 | }, | ||
303 | "original": { | ||
304 | "path": "../../flakes/lib", | ||
305 | "type": "path" | ||
306 | } | ||
307 | }, | ||
308 | "mypackages": { | ||
309 | "inputs": { | ||
310 | "flake-parts": "flake-parts_2", | ||
311 | "nixpkgs": "nixpkgs_8", | ||
312 | "webapps-ttrss": "webapps-ttrss" | ||
313 | }, | ||
314 | "locked": { | ||
315 | "lastModified": 1, | ||
316 | "narHash": "sha256-C0plEL+g6kv5fo/VmTjMJK45RfFcGufqPKJVnviMyGY=", | ||
317 | "path": "../../mypackages", | ||
318 | "type": "path" | ||
319 | }, | ||
320 | "original": { | ||
321 | "path": "../../mypackages", | ||
322 | "type": "path" | ||
323 | } | ||
324 | }, | ||
325 | "myuids": { | ||
326 | "locked": { | ||
327 | "lastModified": 1, | ||
328 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
329 | "path": "../../flakes/myuids", | ||
330 | "type": "path" | ||
331 | }, | ||
332 | "original": { | ||
333 | "path": "../../flakes/myuids", | ||
334 | "type": "path" | ||
335 | } | ||
336 | }, | ||
337 | "myuids_2": { | ||
338 | "locked": { | ||
339 | "lastModified": 1, | ||
340 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
341 | "path": "../../myuids", | ||
342 | "type": "path" | ||
343 | }, | ||
344 | "original": { | ||
345 | "path": "../../myuids", | ||
346 | "type": "path" | ||
347 | } | ||
348 | }, | ||
349 | "naemon": { | ||
350 | "locked": { | ||
351 | "lastModified": 1, | ||
352 | "narHash": "sha256-6le57WLKj1HXdhe4cgYO6N0Z9nJZC+plQY8HhOwzEIk=", | ||
353 | "path": "../../naemon", | ||
354 | "type": "path" | ||
355 | }, | ||
356 | "original": { | ||
357 | "path": "../../naemon", | ||
358 | "type": "path" | ||
359 | } | ||
360 | }, | ||
361 | "nixos-2305": { | ||
362 | "locked": { | ||
363 | "lastModified": 1687938137, | ||
364 | "narHash": "sha256-Z00c0Pk3aE1aw9x44lVcqHmvx+oX7dxCXCvKcUuE150=", | ||
365 | "owner": "NixOS", | ||
366 | "repo": "nixpkgs", | ||
367 | "rev": "ba2ded3227a2992f2040fad4ba6f218a701884a5", | ||
368 | "type": "github" | ||
369 | }, | ||
370 | "original": { | ||
371 | "owner": "NixOS", | ||
372 | "ref": "release-23.05", | ||
373 | "repo": "nixpkgs", | ||
374 | "type": "github" | ||
375 | } | ||
376 | }, | ||
377 | "nixos-anywhere": { | ||
378 | "inputs": { | ||
379 | "disko": [ | ||
380 | "my-lib", | ||
381 | "disko" | ||
382 | ], | ||
383 | "flake-parts": [ | ||
384 | "my-lib", | ||
385 | "flake-parts" | ||
386 | ], | ||
387 | "nixos-2305": "nixos-2305", | ||
388 | "nixos-images": "nixos-images", | ||
389 | "nixpkgs": "nixpkgs_3", | ||
390 | "treefmt-nix": "treefmt-nix" | ||
391 | }, | ||
392 | "locked": { | ||
393 | "lastModified": 1689945193, | ||
394 | "narHash": "sha256-+GPRt7ouE84A7GPNKnFYGU0cQL7skKxz0BAY0sUjUmw=", | ||
395 | "owner": "numtide", | ||
396 | "repo": "nixos-anywhere", | ||
397 | "rev": "27161266077a177ac116e2cb72cc70af5f145189", | ||
398 | "type": "github" | ||
399 | }, | ||
400 | "original": { | ||
401 | "owner": "numtide", | ||
402 | "repo": "nixos-anywhere", | ||
403 | "type": "github" | ||
404 | } | ||
405 | }, | ||
406 | "nixos-images": { | ||
407 | "inputs": { | ||
408 | "nixos-2305": [ | ||
409 | "my-lib", | ||
410 | "nixos-anywhere", | ||
411 | "nixos-2305" | ||
412 | ], | ||
413 | "nixos-unstable": [ | ||
414 | "my-lib", | ||
415 | "nixos-anywhere", | ||
416 | "nixpkgs" | ||
417 | ] | ||
418 | }, | ||
419 | "locked": { | ||
420 | "lastModified": 1686819168, | ||
421 | "narHash": "sha256-IbRVStbKoMC2fUX6TxNO82KgpVfI8LL4Cq0bTgdYhnY=", | ||
422 | "owner": "nix-community", | ||
423 | "repo": "nixos-images", | ||
424 | "rev": "ccc1a2c08ce2fc38bcece85d2a6e7bf17bac9e37", | ||
425 | "type": "github" | ||
426 | }, | ||
427 | "original": { | ||
428 | "owner": "nix-community", | ||
429 | "repo": "nixos-images", | ||
430 | "type": "github" | ||
431 | } | ||
432 | }, | ||
433 | "nixpkgs": { | ||
434 | "locked": { | ||
435 | "lastModified": 1683408522, | ||
436 | "narHash": "sha256-9kcPh6Uxo17a3kK3XCHhcWiV1Yu1kYj22RHiymUhMkU=", | ||
437 | "owner": "NixOS", | ||
438 | "repo": "nixpkgs", | ||
439 | "rev": "897876e4c484f1e8f92009fd11b7d988a121a4e7", | ||
440 | "type": "github" | ||
441 | }, | ||
442 | "original": { | ||
443 | "owner": "NixOS", | ||
444 | "ref": "nixos-unstable", | ||
445 | "repo": "nixpkgs", | ||
446 | "type": "github" | ||
447 | } | ||
448 | }, | ||
449 | "nixpkgs-4": { | ||
450 | "flake": false, | ||
451 | "locked": { | ||
452 | "lastModified": 1646497237, | ||
453 | "narHash": "sha256-Ccpot1h/rV8MgcngDp5OrdmLTMaUTbStZTR5/sI7zW0=", | ||
454 | "owner": "NixOS", | ||
455 | "repo": "nixpkgs", | ||
456 | "rev": "062a0c5437b68f950b081bbfc8a699d57a4ee026", | ||
457 | "type": "github" | ||
458 | }, | ||
459 | "original": { | ||
460 | "owner": "NixOS", | ||
461 | "repo": "nixpkgs", | ||
462 | "rev": "062a0c5437b68f950b081bbfc8a699d57a4ee026", | ||
463 | "type": "github" | ||
464 | } | ||
465 | }, | ||
466 | "nixpkgs-lib": { | ||
467 | "locked": { | ||
468 | "dir": "lib", | ||
469 | "lastModified": 1691269286, | ||
470 | "narHash": "sha256-7cPTz1bPhwq8smt9rHDcFtJsd1tFDcBukzj5jOXqjfk=", | ||
471 | "owner": "NixOS", | ||
472 | "repo": "nixpkgs", | ||
473 | "rev": "85d4248a4f5aa6bc55dd2cea8131bb68b2d43804", | ||
474 | "type": "github" | ||
475 | }, | ||
476 | "original": { | ||
477 | "dir": "lib", | ||
478 | "owner": "NixOS", | ||
479 | "repo": "nixpkgs", | ||
480 | "type": "github" | ||
481 | } | ||
482 | }, | ||
483 | "nixpkgs-lib_2": { | ||
484 | "locked": { | ||
485 | "dir": "lib", | ||
486 | "lastModified": 1685564631, | ||
487 | "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=", | ||
488 | "owner": "NixOS", | ||
489 | "repo": "nixpkgs", | ||
490 | "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a", | ||
491 | "type": "github" | ||
492 | }, | ||
493 | "original": { | ||
494 | "dir": "lib", | ||
495 | "owner": "NixOS", | ||
496 | "ref": "nixos-unstable", | ||
497 | "repo": "nixpkgs", | ||
498 | "type": "github" | ||
499 | } | ||
500 | }, | ||
501 | "nixpkgs-lib_3": { | ||
502 | "locked": { | ||
503 | "dir": "lib", | ||
504 | "lastModified": 1675183161, | ||
505 | "narHash": "sha256-Zq8sNgAxDckpn7tJo7V1afRSk2eoVbu3OjI1QklGLNg=", | ||
506 | "owner": "NixOS", | ||
507 | "repo": "nixpkgs", | ||
508 | "rev": "e1e1b192c1a5aab2960bf0a0bd53a2e8124fa18e", | ||
509 | "type": "github" | ||
510 | }, | ||
511 | "original": { | ||
512 | "dir": "lib", | ||
513 | "owner": "NixOS", | ||
514 | "ref": "nixos-unstable", | ||
515 | "repo": "nixpkgs", | ||
516 | "type": "github" | ||
517 | } | ||
518 | }, | ||
519 | "nixpkgs_2": { | ||
520 | "locked": { | ||
521 | "lastModified": 1687701825, | ||
522 | "narHash": "sha256-aMC9hqsf+4tJL7aJWSdEUurW2TsjxtDcJBwM9Y4FIYM=", | ||
523 | "owner": "NixOS", | ||
524 | "repo": "nixpkgs", | ||
525 | "rev": "07059ee2fa34f1598758839b9af87eae7f7ae6ea", | ||
526 | "type": "github" | ||
527 | }, | ||
528 | "original": { | ||
529 | "owner": "NixOS", | ||
530 | "ref": "nixpkgs-unstable", | ||
531 | "repo": "nixpkgs", | ||
532 | "type": "github" | ||
533 | } | ||
534 | }, | ||
535 | "nixpkgs_3": { | ||
536 | "locked": { | ||
537 | "lastModified": 1687893427, | ||
538 | "narHash": "sha256-jJHj0Lxpvov1IPYQK441oLAKxxemHm16U9jf60bXAFU=", | ||
539 | "owner": "nixos", | ||
540 | "repo": "nixpkgs", | ||
541 | "rev": "4b14ab2a916508442e685089672681dff46805be", | ||
542 | "type": "github" | ||
543 | }, | ||
544 | "original": { | ||
545 | "owner": "nixos", | ||
546 | "ref": "nixos-unstable-small", | ||
547 | "repo": "nixpkgs", | ||
548 | "type": "github" | ||
549 | } | ||
550 | }, | ||
551 | "nixpkgs_4": { | ||
552 | "locked": { | ||
553 | "lastModified": 1648725829, | ||
554 | "narHash": "sha256-tXEzI38lLrzW2qCAIs0UAatE2xcsTsoKWaaXqAcF1NI=", | ||
555 | "owner": "NixOS", | ||
556 | "repo": "nixpkgs", | ||
557 | "rev": "72152ff5ad470ed1a5b97c0ba2737938c136c994", | ||
558 | "type": "github" | ||
559 | }, | ||
560 | "original": { | ||
561 | "owner": "NixOS", | ||
562 | "repo": "nixpkgs", | ||
563 | "type": "github" | ||
564 | } | ||
565 | }, | ||
566 | "nixpkgs_5": { | ||
567 | "locked": { | ||
568 | "lastModified": 1693158576, | ||
569 | "narHash": "sha256-aRTTXkYvhXosGx535iAFUaoFboUrZSYb1Ooih/auGp0=", | ||
570 | "owner": "nixos", | ||
571 | "repo": "nixpkgs", | ||
572 | "rev": "a999c1cc0c9eb2095729d5aa03e0d8f7ed256780", | ||
573 | "type": "github" | ||
574 | }, | ||
575 | "original": { | ||
576 | "owner": "nixos", | ||
577 | "ref": "nixos-unstable", | ||
578 | "repo": "nixpkgs", | ||
579 | "type": "github" | ||
580 | } | ||
581 | }, | ||
582 | "nixpkgs_6": { | ||
583 | "flake": false, | ||
584 | "locked": { | ||
585 | "lastModified": 1596265691, | ||
586 | "narHash": "sha256-9ofCzFqttTsGrvTaS4RrDSTNQO9PFOz5uyn8V+2eA5M=", | ||
587 | "owner": "NixOS", | ||
588 | "repo": "nixpkgs", | ||
589 | "rev": "840c782d507d60aaa49aa9e3f6d0b0e780912742", | ||
590 | "type": "github" | ||
591 | }, | ||
592 | "original": { | ||
593 | "owner": "NixOS", | ||
594 | "repo": "nixpkgs", | ||
595 | "rev": "840c782d507d60aaa49aa9e3f6d0b0e780912742", | ||
596 | "type": "github" | ||
597 | } | ||
598 | }, | ||
599 | "nixpkgs_7": { | ||
600 | "locked": { | ||
601 | "lastModified": 1687502512, | ||
602 | "narHash": "sha256-dBL/01TayOSZYxtY4cMXuNCBk8UMLoqRZA+94xiFpJA=", | ||
603 | "owner": "NixOS", | ||
604 | "repo": "nixpkgs", | ||
605 | "rev": "3ae20aa58a6c0d1ca95c9b11f59a2d12eebc511f", | ||
606 | "type": "github" | ||
607 | }, | ||
608 | "original": { | ||
609 | "owner": "NixOS", | ||
610 | "ref": "nixos-unstable", | ||
611 | "repo": "nixpkgs", | ||
612 | "type": "github" | ||
613 | } | ||
614 | }, | ||
615 | "nixpkgs_8": { | ||
616 | "locked": { | ||
617 | "lastModified": 1646497237, | ||
618 | "narHash": "sha256-Ccpot1h/rV8MgcngDp5OrdmLTMaUTbStZTR5/sI7zW0=", | ||
619 | "owner": "nixos", | ||
620 | "repo": "nixpkgs", | ||
621 | "rev": "062a0c5437b68f950b081bbfc8a699d57a4ee026", | ||
622 | "type": "github" | ||
623 | }, | ||
624 | "original": { | ||
625 | "owner": "nixos", | ||
626 | "repo": "nixpkgs", | ||
627 | "rev": "062a0c5437b68f950b081bbfc8a699d57a4ee026", | ||
628 | "type": "github" | ||
629 | } | ||
630 | }, | ||
631 | "php": { | ||
632 | "inputs": { | ||
633 | "flake-utils": "flake-utils_2", | ||
634 | "nixpkgs": "nixpkgs_6", | ||
635 | "nixpkgs-4": "nixpkgs-4" | ||
636 | }, | ||
637 | "locked": { | ||
638 | "lastModified": 1, | ||
639 | "narHash": "sha256-Qs+O86L4sPArYWm7wMCFNKLCWfUwkz8STePsn5K9Xwk=", | ||
640 | "path": "../../flakes/private/php", | ||
641 | "type": "path" | ||
642 | }, | ||
643 | "original": { | ||
644 | "path": "../../flakes/private/php", | ||
645 | "type": "path" | ||
646 | } | ||
647 | }, | ||
648 | "root": { | ||
649 | "inputs": { | ||
650 | "chatons": "chatons", | ||
651 | "environment": "environment_2", | ||
652 | "files-watcher": "files-watcher", | ||
653 | "loginctl-linger": "loginctl-linger", | ||
654 | "mail-relay": "mail-relay", | ||
655 | "monitoring": "monitoring", | ||
656 | "my-lib": "my-lib", | ||
657 | "myuids": "myuids", | ||
658 | "nixpkgs": "nixpkgs_5", | ||
659 | "php": "php", | ||
660 | "secrets": "secrets_3", | ||
661 | "system": "system" | ||
662 | } | ||
663 | }, | ||
664 | "secrets": { | ||
665 | "locked": { | ||
666 | "lastModified": 1, | ||
667 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
668 | "path": "../../secrets", | ||
669 | "type": "path" | ||
670 | }, | ||
671 | "original": { | ||
672 | "path": "../../secrets", | ||
673 | "type": "path" | ||
674 | } | ||
675 | }, | ||
676 | "secrets-public": { | ||
677 | "locked": { | ||
678 | "lastModified": 1, | ||
679 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
680 | "path": "../../secrets", | ||
681 | "type": "path" | ||
682 | }, | ||
683 | "original": { | ||
684 | "path": "../../secrets", | ||
685 | "type": "path" | ||
686 | } | ||
687 | }, | ||
688 | "secrets_2": { | ||
689 | "locked": { | ||
690 | "lastModified": 1, | ||
691 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
692 | "path": "../../secrets", | ||
693 | "type": "path" | ||
694 | }, | ||
695 | "original": { | ||
696 | "path": "../../secrets", | ||
697 | "type": "path" | ||
698 | } | ||
699 | }, | ||
700 | "secrets_3": { | ||
701 | "locked": { | ||
702 | "lastModified": 1, | ||
703 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
704 | "path": "../../flakes/secrets", | ||
705 | "type": "path" | ||
706 | }, | ||
707 | "original": { | ||
708 | "path": "../../flakes/secrets", | ||
709 | "type": "path" | ||
710 | } | ||
711 | }, | ||
712 | "stable": { | ||
713 | "locked": { | ||
714 | "lastModified": 1669735802, | ||
715 | "narHash": "sha256-qtG/o/i5ZWZLmXw108N2aPiVsxOcidpHJYNkT45ry9Q=", | ||
716 | "owner": "NixOS", | ||
717 | "repo": "nixpkgs", | ||
718 | "rev": "731cc710aeebecbf45a258e977e8b68350549522", | ||
719 | "type": "github" | ||
720 | }, | ||
721 | "original": { | ||
722 | "owner": "NixOS", | ||
723 | "ref": "nixos-22.11", | ||
724 | "repo": "nixpkgs", | ||
725 | "type": "github" | ||
726 | } | ||
727 | }, | ||
728 | "system": { | ||
729 | "inputs": { | ||
730 | "backports": "backports", | ||
731 | "environment": "environment_5", | ||
732 | "mypackages": "mypackages", | ||
733 | "myuids": "myuids_2", | ||
734 | "secrets-public": "secrets-public" | ||
735 | }, | ||
736 | "locked": { | ||
737 | "lastModified": 1, | ||
738 | "narHash": "sha256-vOs7fcQVsOSl/gsyzFXfsWE7u0/O9mIKpHnwDwHxJTQ=", | ||
739 | "path": "../../flakes/private/system", | ||
740 | "type": "path" | ||
741 | }, | ||
742 | "original": { | ||
743 | "path": "../../flakes/private/system", | ||
744 | "type": "path" | ||
745 | } | ||
746 | }, | ||
747 | "treefmt-nix": { | ||
748 | "inputs": { | ||
749 | "nixpkgs": [ | ||
750 | "my-lib", | ||
751 | "nixos-anywhere", | ||
752 | "nixpkgs" | ||
753 | ] | ||
754 | }, | ||
755 | "locked": { | ||
756 | "lastModified": 1687940979, | ||
757 | "narHash": "sha256-D4ZFkgIG2s9Fyi78T3fVG9mqMD+/UnFDB62jS4gjZKY=", | ||
758 | "owner": "numtide", | ||
759 | "repo": "treefmt-nix", | ||
760 | "rev": "0a4f06c27610a99080b69433873885df82003aae", | ||
761 | "type": "github" | ||
762 | }, | ||
763 | "original": { | ||
764 | "owner": "numtide", | ||
765 | "repo": "treefmt-nix", | ||
766 | "type": "github" | ||
767 | } | ||
768 | }, | ||
769 | "webapps-ttrss": { | ||
770 | "flake": false, | ||
771 | "locked": { | ||
772 | "lastModified": 1546759381, | ||
773 | "narHash": "sha256-urjf4EoLWS7G0s0hRtaErrs2B8DUatNK/eoneuB0anY=", | ||
774 | "ref": "master", | ||
775 | "rev": "986ca251f995f7754a0470d3e0c44538a545081f", | ||
776 | "revCount": 9256, | ||
777 | "type": "git", | ||
778 | "url": "https://git.tt-rss.org/fox/tt-rss.git" | ||
779 | }, | ||
780 | "original": { | ||
781 | "ref": "master", | ||
782 | "rev": "986ca251f995f7754a0470d3e0c44538a545081f", | ||
783 | "type": "git", | ||
784 | "url": "https://git.tt-rss.org/fox/tt-rss.git" | ||
785 | } | ||
786 | } | ||
787 | }, | ||
788 | "root": "root", | ||
789 | "version": 7 | ||
790 | } | ||
diff --git a/systems/monitoring-1/flake.nix b/systems/monitoring-1/flake.nix new file mode 100644 index 0000000..e97cb05 --- /dev/null +++ b/systems/monitoring-1/flake.nix | |||
@@ -0,0 +1,45 @@ | |||
1 | { | ||
2 | inputs = { | ||
3 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; | ||
4 | |||
5 | my-lib.url = "path:../../flakes/lib"; | ||
6 | |||
7 | monitoring.url = "path:../../flakes/private/monitoring"; | ||
8 | mail-relay.url = "path:../../flakes/private/mail-relay"; | ||
9 | chatons.url = "path:../../flakes/private/chatons"; | ||
10 | environment.url = "path:../../flakes/private/environment"; | ||
11 | system.url = "path:../../flakes/private/system"; | ||
12 | php.url = "path:../../flakes/private/php"; | ||
13 | |||
14 | myuids.url = "path:../../flakes/myuids"; | ||
15 | secrets.url = "path:../../flakes/secrets"; | ||
16 | files-watcher.url = "path:../../flakes/files-watcher"; | ||
17 | loginctl-linger.url = "path:../../flakes/loginctl-linger"; | ||
18 | }; | ||
19 | outputs = inputs@{ self, my-lib, nixpkgs, ...}: | ||
20 | my-lib.lib.mkColmenaFlake { | ||
21 | name = "monitoring-1"; | ||
22 | inherit self nixpkgs; | ||
23 | system = "x86_64-linux"; | ||
24 | targetHost = "95.216.164.150"; | ||
25 | targetUser = "root"; | ||
26 | nixosModules = { | ||
27 | base = ./base.nix; | ||
28 | system = inputs.system.nixosModule; | ||
29 | mail-relay = inputs.mail-relay.nixosModule; | ||
30 | chatons = inputs.chatons.nixosModule; | ||
31 | monitoring = inputs.monitoring.nixosModule; | ||
32 | environment = inputs.environment.nixosModule; | ||
33 | |||
34 | myuids = inputs.myuids.nixosModule; | ||
35 | secrets = inputs.secrets.nixosModule; | ||
36 | files-watcher = inputs.files-watcher.nixosModule; | ||
37 | loginctl-linger = inputs.loginctl-linger.nixosModule; | ||
38 | }; | ||
39 | moduleArgs = { | ||
40 | nixpkgs = inputs.nixpkgs; | ||
41 | monitoring = inputs.monitoring; | ||
42 | php = inputs.php; | ||
43 | }; | ||
44 | }; | ||
45 | } | ||
diff --git a/systems/monitoring-1/monitoring-master.nix b/systems/monitoring-1/monitoring-master.nix new file mode 100644 index 0000000..09319b8 --- /dev/null +++ b/systems/monitoring-1/monitoring-master.nix | |||
@@ -0,0 +1,87 @@ | |||
1 | { config, pkgs, lib, nodes, name, monitoring, ... }: | ||
2 | let | ||
3 | mlib = monitoring.lib; | ||
4 | nodesWithMonitoring = lib.filterAttrs (n: v: (v.config.myServices or {}) ? "monitoring") nodes; | ||
5 | in | ||
6 | { | ||
7 | imports = [ | ||
8 | ./monitoring/master.nix | ||
9 | ./monitoring/phare.nix | ||
10 | ./monitoring/ulminfo-fr.nix | ||
11 | ]; | ||
12 | myServices.monitoring.activatedPlugins = lib.flatten (lib.mapAttrsToList (_: n: n.config.myServices.monitoring.fromMasterActivatedPlugins) nodesWithMonitoring); | ||
13 | myServices.monitoring.objects = lib.mkMerge ( | ||
14 | lib.mapAttrsToList (_: n: | ||
15 | mlib.toMasterPassiveObject "external-passive-service" 1.5 n.config.myServices.monitoring.objects | ||
16 | ) (lib.filterAttrs (n: v: n != name) nodesWithMonitoring) | ||
17 | ++ | ||
18 | lib.mapAttrsToList (_: n: n.config.myServices.monitoring.fromMasterObjects) nodesWithMonitoring | ||
19 | ); | ||
20 | myServices.chatonsProperties.hostings.monitoring = { | ||
21 | file.datetime = "2022-08-27T16:00:00"; | ||
22 | hosting = { | ||
23 | name = "Monitoring"; | ||
24 | description = "Website and server health monitoring"; | ||
25 | website = "https://status.immae.eu"; | ||
26 | logo = "https://www.naemon.io/favicon.ico"; | ||
27 | status.level = "OK"; | ||
28 | status.description = "OK"; | ||
29 | registration.load = "OPEN"; | ||
30 | install.type = "PACKAGE"; | ||
31 | }; | ||
32 | software = { | ||
33 | name = "naemon"; | ||
34 | website = "https://www.naemon.io/"; | ||
35 | license.url = "https://github.com/naemon/naemon-core/blob/master/COPYING"; | ||
36 | license.name = "GNU General Public License v2.0"; | ||
37 | version = config.services.naemon.package.version; | ||
38 | source.url = "https://github.com/naemon/naemon-core"; | ||
39 | modules = "livestatus,status-engine"; | ||
40 | }; | ||
41 | }; | ||
42 | |||
43 | services.nginx = { | ||
44 | virtualHosts."status.immae.eu".locations = { | ||
45 | "=/common/immae.cfg" = { | ||
46 | alias = pkgs.writeText "immae.cfg" '' | ||
47 | # put me for instance in /etc/naemon/module-conf.d/immae.cfg | ||
48 | # Make sure that you have include_dir=module-conf.d in | ||
49 | # naemon.cfg | ||
50 | log_initial_states=1 | ||
51 | date_format=iso8601 | ||
52 | admin_email=${config.myEnv.monitoring.email} | ||
53 | obsess_over_services=1 | ||
54 | ocsp_command=notify-master | ||
55 | ''; | ||
56 | }; | ||
57 | "=/common/resource.cfg" = { | ||
58 | alias = pkgs.writeText "resource.cfg" '' | ||
59 | # Resource.cfg file | ||
60 | # Replace this with path to monitoring plugins | ||
61 | $USER1$=@@COMMON_PLUGINS@@ | ||
62 | # Replace this with a path to scripts from | ||
63 | # https://git.immae.eu/cgit/perso/Immae/Config/Nix.git/tree/modules/private/monitoring/plugins | ||
64 | $USER2$=@@IMMAE_PLUGINS@@ | ||
65 | $USER200$=https://status.immae.eu/ | ||
66 | $USER201$=@@TOKEN@@ | ||
67 | ''; | ||
68 | }; | ||
69 | }; | ||
70 | }; | ||
71 | |||
72 | secrets.keys = lib.mapAttrs' (k: v: lib.nameValuePair "${k}_access_key" { | ||
73 | user = "naemon"; | ||
74 | group = "naemon"; | ||
75 | permissions = "0400"; | ||
76 | text = '' | ||
77 | export AWS_ACCESS_KEY_ID="${v.accessKeyId}" | ||
78 | export AWS_SECRET_ACCESS_KEY="${v.secretAccessKey}" | ||
79 | export BASE_URL="${v.remote "immae-eldiron"}" | ||
80 | ''; | ||
81 | }) config.myEnv.backup.remotes; | ||
82 | |||
83 | services.naemon.extraConfig = '' | ||
84 | broker_module=${pkgs.naemon-livestatus}/lib/naemon-livestatus/livestatus.so ${config.services.naemon.runDir}/live | ||
85 | broker_module=${pkgs.status-engine-module}/lib/status-engine/naemon/statusengine-${pkgs.naemon.status_engine_version}.o use_service_perfdata=1 use_process_data=0 use_system_command_data=0 use_external_command_data=0 use_flapping_data=0 use_program_status_data=0 use_notification_data=0 use_contact_status_data=0 use_contact_notification_data=0 use_event_handler_data=0 use_object_data=0 | ||
86 | ''; | ||
87 | } | ||
diff --git a/systems/monitoring-1/monitoring.nix b/systems/monitoring-1/monitoring.nix new file mode 100644 index 0000000..421c71f --- /dev/null +++ b/systems/monitoring-1/monitoring.nix | |||
@@ -0,0 +1,61 @@ | |||
1 | { config, pkgs, lib, name, monitoring, ... }: | ||
2 | let | ||
3 | hostFQDN = config.hostEnv.fqdn; | ||
4 | emailCheck = monitoring.lib.emailCheck config.myEnv.monitoring.email_check; | ||
5 | in | ||
6 | { | ||
7 | config.myServices.monitoring.activatedPlugins = [ "memory" "command" "bandwidth" "emails" "ovh" "notify-primary" ]; | ||
8 | config.myServices.monitoring.objects = lib.mkMerge [ | ||
9 | (monitoring.lib.objectsCommon { | ||
10 | inherit hostFQDN; | ||
11 | hostName = name; | ||
12 | master = true; | ||
13 | processWarn = "70"; processAlert = "80"; | ||
14 | loadWarn = "4.0"; loadAlert = "5.0"; | ||
15 | load15Warn = "1.0"; load15Alert = "2.0"; | ||
16 | interface = builtins.head (builtins.attrNames config.networking.interfaces); | ||
17 | }) | ||
18 | |||
19 | { | ||
20 | service = [ | ||
21 | (emailCheck "monitoring-1" hostFQDN) | ||
22 | |||
23 | { | ||
24 | service_description = "OVH account has enough sms"; | ||
25 | host_name = hostFQDN; | ||
26 | use = "external-service"; | ||
27 | check_command = "check_ovh_sms"; | ||
28 | |||
29 | check_interval = 120; | ||
30 | notification_interval = "1440"; | ||
31 | } | ||
32 | |||
33 | # Dummy service for testing | ||
34 | # { | ||
35 | # service_description = "Dummy failing test"; | ||
36 | # host_name = "dummy-host"; | ||
37 | # use = "local-service"; | ||
38 | # check_interval = 0.3; | ||
39 | # max_check_attempts = "1"; | ||
40 | # flap_detection_enabled = "0"; | ||
41 | # notification_interval = "0.1"; | ||
42 | # check_command = "check_critical"; | ||
43 | # } | ||
44 | ]; | ||
45 | |||
46 | host = { | ||
47 | # Dummy host for testing | ||
48 | # "dummy-host" = { | ||
49 | # alias = "dummy.host"; | ||
50 | # check_interval = 0.3; | ||
51 | # max_check_attempts = "1"; | ||
52 | # flap_detection_enabled = "0"; | ||
53 | # notification_interval = "0.1"; | ||
54 | # address = "dummy.host"; | ||
55 | # use = "linux-server"; | ||
56 | # check_command = "check_ok"; | ||
57 | # }; | ||
58 | }; | ||
59 | } | ||
60 | ]; | ||
61 | } | ||
diff --git a/systems/monitoring-1/monitoring/master.nix b/systems/monitoring-1/monitoring/master.nix new file mode 100644 index 0000000..c8f52ea --- /dev/null +++ b/systems/monitoring-1/monitoring/master.nix | |||
@@ -0,0 +1,43 @@ | |||
1 | { config, ... }: | ||
2 | { | ||
3 | myServices.monitoring.objects = { | ||
4 | contact = { | ||
5 | immae = { | ||
6 | alias = "Immae"; | ||
7 | email = config.myEnv.monitoring.immae_contact; | ||
8 | use = "generic-contact"; | ||
9 | contactgroups = "admins"; | ||
10 | host_notification_commands = "notify-host-by-email,notify-host-by-apprise!$USER210$"; | ||
11 | service_notification_commands = "notify-service-by-email,notify-service-by-apprise!$USER210$"; | ||
12 | }; | ||
13 | }; | ||
14 | command = { | ||
15 | check_passive = "$USER1$/check_dummy 3 \"Service result are stale\""; | ||
16 | }; | ||
17 | templates = { | ||
18 | service = { | ||
19 | external-passive-service = { | ||
20 | active_checks_enabled = "0"; | ||
21 | check_freshness = "1"; | ||
22 | check_period = "24x7"; | ||
23 | contact_groups = "admins"; | ||
24 | event_handler_enabled = "1"; | ||
25 | flap_detection_enabled = "1"; | ||
26 | is_volatile = "0"; | ||
27 | max_check_attempts = "3"; | ||
28 | notification_interval = "60"; | ||
29 | notification_options = "w,u,c,r,f,s"; | ||
30 | notification_period = "24x7"; | ||
31 | notifications_enabled = "1"; | ||
32 | passive_checks_enabled = "1"; | ||
33 | process_perf_data = "1"; | ||
34 | retain_nonstatus_information = "1"; | ||
35 | retain_status_information = "1"; | ||
36 | retry_interval = "2"; | ||
37 | check_command = "check_passive"; | ||
38 | _webstatus_namespace = "immae"; | ||
39 | }; | ||
40 | }; | ||
41 | }; | ||
42 | }; | ||
43 | } | ||
diff --git a/systems/monitoring-1/monitoring/phare.nix b/systems/monitoring-1/monitoring/phare.nix new file mode 100644 index 0000000..0ce9ffe --- /dev/null +++ b/systems/monitoring-1/monitoring/phare.nix | |||
@@ -0,0 +1,20 @@ | |||
1 | { monitoring, config, ... }: | ||
2 | let | ||
3 | emailCheck = monitoring.lib.emailCheck config.myEnv.monitoring.email_check; | ||
4 | in | ||
5 | { | ||
6 | config.myServices.monitoring.activatedPlugins = [ "emails" ]; | ||
7 | config.myServices.monitoring.objects.host = { | ||
8 | "phare.normalesup.org" = { | ||
9 | alias = "phare.normalesup.org"; | ||
10 | address = "phare.normalesup.org"; | ||
11 | use = "linux-server"; | ||
12 | hostgroups = "webstatus-hosts"; | ||
13 | _webstatus_name = "phare"; | ||
14 | _webstatus_vhost = "status.immae.eu"; | ||
15 | }; | ||
16 | }; | ||
17 | config.myServices.monitoring.objects.service = [ | ||
18 | (emailCheck "phare" "phare.normalesup.org") | ||
19 | ]; | ||
20 | } | ||
diff --git a/systems/monitoring-1/monitoring/ulminfo-fr.nix b/systems/monitoring-1/monitoring/ulminfo-fr.nix new file mode 100644 index 0000000..b0c6657 --- /dev/null +++ b/systems/monitoring-1/monitoring/ulminfo-fr.nix | |||
@@ -0,0 +1,20 @@ | |||
1 | { monitoring, config, ... }: | ||
2 | let | ||
3 | emailCheck = monitoring.lib.emailCheck config.myEnv.monitoring.email_check; | ||
4 | in | ||
5 | { | ||
6 | config.myServices.monitoring.activatedPlugins = [ "emails" ]; | ||
7 | config.myServices.monitoring.objects.host = { | ||
8 | "ulminfo.fr" = { | ||
9 | alias = "ulminfo.fr"; | ||
10 | address = "ulminfo.fr"; | ||
11 | use = "linux-server"; | ||
12 | hostgroups = "webstatus-hosts"; | ||
13 | _webstatus_name = "ulminfo"; | ||
14 | _webstatus_vhost = "status.immae.eu"; | ||
15 | }; | ||
16 | }; | ||
17 | config.myServices.monitoring.objects.service = [ | ||
18 | (emailCheck "ulminfo" "ulminfo.fr") | ||
19 | ]; | ||
20 | } | ||
diff --git a/systems/monitoring-1/status.nix b/systems/monitoring-1/status.nix new file mode 100644 index 0000000..8b6615f --- /dev/null +++ b/systems/monitoring-1/status.nix | |||
@@ -0,0 +1,84 @@ | |||
1 | { config, pkgs, lib, name, ... }: | ||
2 | { | ||
3 | options = { | ||
4 | myServices.status = { | ||
5 | enable = lib.mkOption { | ||
6 | type = lib.types.bool; | ||
7 | default = false; | ||
8 | description = '' | ||
9 | Whether to enable status app. | ||
10 | ''; | ||
11 | }; | ||
12 | }; | ||
13 | }; | ||
14 | config = lib.mkIf config.myServices.status.enable { | ||
15 | secrets.keys."naemon-status/environment" = { | ||
16 | user = "naemon"; | ||
17 | group = "naemon"; | ||
18 | permissions = "0400"; | ||
19 | text = '' | ||
20 | TOKENS=${builtins.concatStringsSep " " config.myEnv.monitoring.nrdp_tokens} | ||
21 | ''; | ||
22 | }; | ||
23 | services.nginx = { | ||
24 | enable = true; | ||
25 | recommendedOptimisation = true; | ||
26 | recommendedGzipSettings = true; | ||
27 | recommendedProxySettings = true; | ||
28 | upstreams."netdata".servers = { "127.0.0.1:19999" = {}; }; | ||
29 | upstreams."netdata".extraConfig = '' | ||
30 | keepalive 64; | ||
31 | ''; | ||
32 | virtualHosts."status.immae.eu" = { | ||
33 | acmeRoot = config.security.acme.defaults.webroot; | ||
34 | useACMEHost = name; | ||
35 | forceSSL = true; | ||
36 | locations."/".proxyPass = "http://unix:/run/naemon-status/socket.sock:/"; | ||
37 | |||
38 | locations."= /netdata".return = "301 /netdata/"; | ||
39 | locations."~ /netdata/(?<ndpath>.*)".extraConfig = '' | ||
40 | proxy_redirect off; | ||
41 | proxy_set_header Host $host; | ||
42 | |||
43 | proxy_set_header X-Forwarded-Host $host; | ||
44 | proxy_set_header X-Forwarded-Server $host; | ||
45 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||
46 | proxy_http_version 1.1; | ||
47 | proxy_pass_request_headers on; | ||
48 | proxy_set_header Connection "keep-alive"; | ||
49 | proxy_store off; | ||
50 | proxy_pass http://netdata/$ndpath$is_args$args; | ||
51 | |||
52 | gzip on; | ||
53 | gzip_proxied any; | ||
54 | gzip_types *; | ||
55 | ''; | ||
56 | }; | ||
57 | }; | ||
58 | security.acme.certs."${name}" = { | ||
59 | extraDomainNames = [ "status.immae.eu" ]; | ||
60 | group = config.services.nginx.group; | ||
61 | }; | ||
62 | |||
63 | networking.firewall.allowedTCPPorts = [ 80 443 ]; | ||
64 | systemd.services.naemon-status = { | ||
65 | description = "Naemon status"; | ||
66 | after = [ "network.target" ]; | ||
67 | wantedBy = [ "multi-user.target" ]; | ||
68 | |||
69 | serviceConfig = { | ||
70 | EnvironmentFile = config.secrets.fullPaths."naemon-status/environment"; | ||
71 | Type = "simple"; | ||
72 | WorkingDirectory = "${./status}"; | ||
73 | ExecStart = let | ||
74 | python = pkgs.python3.withPackages (p: [ p.gunicorn p.flask p.flask_login ]); | ||
75 | in | ||
76 | "${python}/bin/gunicorn -w4 --bind unix:/run/naemon-status/socket.sock app:app"; | ||
77 | User = "naemon"; | ||
78 | RuntimeDirectory = "naemon-status"; | ||
79 | StandardOutput = "journal"; | ||
80 | StandardError = "inherit"; | ||
81 | }; | ||
82 | }; | ||
83 | }; | ||
84 | } | ||
diff --git a/systems/monitoring-1/status/app.py b/systems/monitoring-1/status/app.py new file mode 100755 index 0000000..ff92891 --- /dev/null +++ b/systems/monitoring-1/status/app.py | |||
@@ -0,0 +1,414 @@ | |||
1 | from flask import Flask, request, render_template_string, jsonify, make_response | ||
2 | from flask_login import LoginManager, UserMixin, login_required | ||
3 | import socket | ||
4 | import json | ||
5 | import time | ||
6 | import os | ||
7 | |||
8 | login_manager = LoginManager() | ||
9 | app = Flask(__name__) | ||
10 | login_manager.init_app(app) | ||
11 | |||
12 | STATUS = [ | ||
13 | "ok", | ||
14 | "warning", | ||
15 | "error", | ||
16 | "unknown" | ||
17 | ] | ||
18 | |||
19 | HOST_STATUS = [ | ||
20 | "up", | ||
21 | "down", | ||
22 | "unreachable", | ||
23 | ] | ||
24 | |||
25 | #### Push | ||
26 | AUTHORIZED_KEYS = os.environ.get("TOKENS", "").split() | ||
27 | COMMAND_FILE = "/var/run/naemon/naemon.cmd" | ||
28 | |||
29 | ERROR_NO_REQUEST_HANDLER="NO REQUEST HANDLER" | ||
30 | ERROR_NO_TOKEN_SUPPLIED="NO TOKEN" | ||
31 | ERROR_BAD_TOKEN_SUPPLIED="BAD TOKEN" | ||
32 | |||
33 | ERROR_BAD_COMMAND_FILE="BAD COMMAND FILE" | ||
34 | ERROR_COMMAND_FILE_OPEN_WRITE="COMMAND FILE UNWRITEABLE" | ||
35 | ERROR_COMMAND_FILE_OPEN="CANNOT OPEN COMMAND FILE" | ||
36 | ERROR_BAD_WRITE="WRITE ERROR" | ||
37 | |||
38 | ERROR_BAD_DATA="BAD DATA" | ||
39 | ERROR_BAD_JSON="BAD JSON" | ||
40 | |||
41 | ERROR_NO_CORRECT_STATUS="NO STATUS WAS CORRECT" | ||
42 | #### /Push | ||
43 | |||
44 | def get_lq(request): | ||
45 | # https://mathias-kettner.de/checkmk_livestatus.html | ||
46 | socket_path="/var/run/naemon/live" | ||
47 | s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||
48 | s.connect(socket_path) | ||
49 | s.send(request.encode()) | ||
50 | s.shutdown(socket.SHUT_WR) | ||
51 | chunks = [] | ||
52 | while len(chunks) == 0 or len(chunks[-1]) > 0: | ||
53 | chunks.append(s.recv(4096)) | ||
54 | s.close() | ||
55 | return b"".join(chunks).decode() | ||
56 | |||
57 | class Host: | ||
58 | def __init__(self, name, alias, status, webname, vhost): | ||
59 | self.name = name | ||
60 | self.alias = alias | ||
61 | self.webname = webname or alias | ||
62 | self.vhost = vhost | ||
63 | self.status = status | ||
64 | self.services = [] | ||
65 | |||
66 | @classmethod | ||
67 | def parse_hosts(cls, payload, vhost): | ||
68 | parsed = filter(lambda x: x.vhost == vhost, [cls.parse(p) for p in json.loads(payload)]) | ||
69 | return {p.name: p for p in parsed} | ||
70 | |||
71 | @classmethod | ||
72 | def parse(cls, payload): | ||
73 | return cls(payload[0], payload[1], HOST_STATUS[payload[2]], payload[3].get("WEBSTATUS_NAME"), payload[3].get("WEBSTATUS_VHOST")) | ||
74 | |||
75 | def __repr__(self): | ||
76 | return "Host {}: {} ({})".format(self.name, self.alias, self.webname) | ||
77 | |||
78 | @classmethod | ||
79 | def query(cls, vhost): | ||
80 | answer = get_lq("""GET hosts | ||
81 | Filter: groups >= webstatus-hosts | ||
82 | Columns: name alias state custom_variables | ||
83 | OutputFormat: json | ||
84 | """) | ||
85 | return cls.parse_hosts(answer, vhost) | ||
86 | |||
87 | def fill_services(self, services): | ||
88 | self.services = [service for service in services if service.host == self.name] | ||
89 | |||
90 | class ServiceGroup: | ||
91 | def __init__(self, name, alias): | ||
92 | self.name = name | ||
93 | self.alias = alias | ||
94 | self.services = [] | ||
95 | |||
96 | @classmethod | ||
97 | def parse_groups(cls, payload): | ||
98 | parsed = [cls.parse(p) for p in json.loads(payload)] | ||
99 | return {p.name: p for p in parsed} | ||
100 | |||
101 | @classmethod | ||
102 | def parse(cls, payload): | ||
103 | return cls(payload[0], payload[1]) | ||
104 | |||
105 | @classmethod | ||
106 | def query(cls): | ||
107 | answer = get_lq("""GET servicegroups | ||
108 | Filter: name ~ ^webstatus- | ||
109 | Columns: name alias custom_variables | ||
110 | OutputFormat: json | ||
111 | """) | ||
112 | return cls.parse_groups(answer) | ||
113 | |||
114 | def fill_services(self, services, hosts): | ||
115 | self.services = [service for service in services if any([group == self.name for group in service.groups]) and service.host in hosts] | ||
116 | |||
117 | def __repr__(self): | ||
118 | return "ServiceGroup {}: {}".format(self.name, self.alias) | ||
119 | |||
120 | class Service: | ||
121 | def __init__(self, name, host, groups, status, webname, url, description, infos): | ||
122 | self.name = name | ||
123 | self.host = host | ||
124 | self.groups = groups | ||
125 | self.status = status | ||
126 | self.webname = webname | ||
127 | self.url = url | ||
128 | self.description = description | ||
129 | self.infos = infos | ||
130 | |||
131 | @classmethod | ||
132 | def parse_services(cls, payload): | ||
133 | parsed = json.loads(payload) | ||
134 | return [cls.parse(p) for p in parsed if cls.valid(p[2])] | ||
135 | |||
136 | @staticmethod | ||
137 | def valid(groups): | ||
138 | return any([b.startswith("webstatus-") for b in groups]) | ||
139 | |||
140 | @classmethod | ||
141 | def parse(cls, payload): | ||
142 | return cls(payload[0], | ||
143 | payload[1], | ||
144 | payload[2], | ||
145 | STATUS[payload[3]], | ||
146 | payload[4].get("WEBSTATUS_NAME"), | ||
147 | payload[4].get("WEBSTATUS_URL"), | ||
148 | payload[5], | ||
149 | payload[6]) | ||
150 | |||
151 | @classmethod | ||
152 | def query(cls): | ||
153 | answer = get_lq("""GET services | ||
154 | Columns: display_name host_name groups state custom_variables description plugin_output | ||
155 | OutputFormat: json | ||
156 | """) | ||
157 | return cls.parse_services(answer) | ||
158 | |||
159 | def __repr__(self): | ||
160 | return "Service {}: {}".format(self.name, self.webname) | ||
161 | |||
162 | def get_infos(vhost): | ||
163 | hosts = Host.query(vhost) | ||
164 | servicegroups = ServiceGroup.query() | ||
165 | services = Service.query() | ||
166 | |||
167 | for host in hosts: | ||
168 | hosts[host].fill_services(services) | ||
169 | for group in servicegroups: | ||
170 | servicegroups[group].fill_services(services, hosts) | ||
171 | return (hosts, servicegroups, services) | ||
172 | |||
173 | TEMPLATE='''<?xml version="1.0" encoding="UTF-8"?> | ||
174 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | ||
175 | <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> | ||
176 | <head> | ||
177 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||
178 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
179 | <title>Status</title> | ||
180 | <meta name="referrer" content="no-referrer" /> | ||
181 | <style type="text/css"> | ||
182 | ul { | ||
183 | list-style: none; | ||
184 | margin: 0px; | ||
185 | } | ||
186 | ul li:nth-child(2n) { | ||
187 | background-color: rgb(240, 240, 240); | ||
188 | } | ||
189 | li.resource, li.service { | ||
190 | margin: 1px 0px; | ||
191 | } | ||
192 | span.status { | ||
193 | display: inline-block; | ||
194 | width: 150px; | ||
195 | text-align: center; | ||
196 | margin-right: 5px; | ||
197 | font-variant: small-caps; | ||
198 | font-size: 1.2em; | ||
199 | } | ||
200 | .status_ok,.status_up { | ||
201 | background-color: rgba(0, 255, 0, 0.5);; | ||
202 | } | ||
203 | .status_warning { | ||
204 | background-color: rgba(255, 255, 0, 0.5);; | ||
205 | } | ||
206 | .status_error,.status_down { | ||
207 | background-color: rgba(255, 0, 0, 0.5);; | ||
208 | } | ||
209 | .status_unknown,.status_unreachable { | ||
210 | background-color: rgba(0, 0, 255, 0.5);; | ||
211 | } | ||
212 | .infos { | ||
213 | margin-left: 40px; | ||
214 | color: rgb(100, 100, 100); | ||
215 | } | ||
216 | div#services { | ||
217 | column-count: auto; | ||
218 | column-width: 36em; | ||
219 | } | ||
220 | div.servicegroup { | ||
221 | -webkit-column-break-inside: avoid; | ||
222 | break-inside: avoid; | ||
223 | } | ||
224 | h3.servicegroup_title, h3.host_title { | ||
225 | margin: 1px 0px; | ||
226 | } | ||
227 | span.service_host, span.infos { | ||
228 | float: right; | ||
229 | display: inline-block; | ||
230 | color: rgb(100, 100, 100); | ||
231 | } | ||
232 | </style> | ||
233 | </head> | ||
234 | <body> | ||
235 | <h2>Hosts</h2> | ||
236 | {%- for host in hosts.values() %} | ||
237 | <h3 class="host_title"> | ||
238 | <span class="status status_{{ host.status }}">{{ host.status }}</span> | ||
239 | <span class="host">{{ host.webname }}</span> | ||
240 | </h3> | ||
241 | {%- for service in servicegroups["webstatus-resources"].services if service.host == host.name -%} | ||
242 | {%- if loop.first %} | ||
243 | <ul class="resources"> | ||
244 | {% endif %} | ||
245 | |||
246 | <li class="resource"> | ||
247 | <span class="status status_{{ service.status }}">{{ service.status }}</span> | ||
248 | <span class="description">{{ service.description }}</span> | ||
249 | <span class="infos">{{ service.infos }}</span> | ||
250 | </li> | ||
251 | |||
252 | {%- if loop.last %} | ||
253 | </ul> | ||
254 | {% endif %} | ||
255 | {% endfor %} | ||
256 | {%- endfor %} | ||
257 | |||
258 | {%- for group in servicegroups.values() if group.services and group.name != "webstatus-resources" %} | ||
259 | {%- if loop.first %} | ||
260 | <h2>Services</h2> | ||
261 | <div id="services"> | ||
262 | {%- endif %} | ||
263 | <div class="servicegroup"> | ||
264 | <h3 class="servicegroup_title">{{ group.alias }}</h3> | ||
265 | {%- for service in group.services if service.host in hosts -%} | ||
266 | {%- if loop.first %} | ||
267 | <ul class="services"> | ||
268 | {% endif %} | ||
269 | |||
270 | <li class="service" title="{{ service.infos }}"> | ||
271 | <span class="status status_{{ service.status }}">{{ service.status }}</span> | ||
272 | <span class="description"> | ||
273 | {% if service.url and service.url.startswith("https://") %} | ||
274 | <a href="{{ service.url }}">{{ service.webname or service.description }}</a> | ||
275 | {% else %} | ||
276 | {{ service.webname or service.description }} | ||
277 | {% endif %} | ||
278 | </span> | ||
279 | <span class="service_host">{{ hosts[service.host].webname }}</span> | ||
280 | </li> | ||
281 | |||
282 | {%- if loop.last %} | ||
283 | </ul> | ||
284 | {% endif %} | ||
285 | {%- endfor -%} | ||
286 | </div> | ||
287 | {%- if loop.last %} | ||
288 | </div> | ||
289 | {% endif %} | ||
290 | {%- endfor %} | ||
291 | </body> | ||
292 | </html> | ||
293 | ''' | ||
294 | |||
295 | @login_manager.request_loader | ||
296 | def load_user_from_request(request): | ||
297 | api_key = request.headers.get('Token') | ||
298 | if api_key in AUTHORIZED_KEYS: | ||
299 | return UserMixin() | ||
300 | content = request.get_json(force=True, silent=True) | ||
301 | if content is not None and content.get("token") in AUTHORIZED_KEYS: | ||
302 | return UserMixin() | ||
303 | |||
304 | @app.route("/live", methods=["POST"]) | ||
305 | @login_required | ||
306 | def live(): | ||
307 | query = request.get_data() | ||
308 | result = get_lq(query.decode() + "\n") | ||
309 | resp = make_response(result) | ||
310 | resp.content_type = "text/plain" | ||
311 | return resp | ||
312 | |||
313 | @app.route("/", methods=["GET"]) | ||
314 | def get(): | ||
315 | (hosts, servicegroups, services) = get_infos(request.host) | ||
316 | resp = make_response(render_template_string(TEMPLATE, hosts=hosts, servicegroups=servicegroups)) | ||
317 | resp.content_type = "text/html" | ||
318 | return resp | ||
319 | |||
320 | @app.route("/", methods=["POST"]) | ||
321 | @login_required | ||
322 | def push(): | ||
323 | content = request.get_json(force=True, silent=True) | ||
324 | if content is None: | ||
325 | return ERROR_BAD_JSON | ||
326 | if content.get("cmd") != "submitcheck": | ||
327 | return render_error(ERROR_NO_REQUEST_HANDLER) | ||
328 | if "checkresult" not in content or not isinstance(content["checkresult"], list): | ||
329 | return render_error(ERROR_BAD_DATA) | ||
330 | |||
331 | checks = 0 | ||
332 | errors = 0 | ||
333 | for check in map(lambda x: CheckResult.from_json(x), content["checkresult"]): | ||
334 | if check is None: | ||
335 | errors += 1 | ||
336 | continue | ||
337 | try: | ||
338 | write_check_output(check) | ||
339 | except Exception as e: | ||
340 | return render_error(str(e)) | ||
341 | checks += 1 | ||
342 | return render_response(checks, errors) | ||
343 | |||
344 | def write_check_output(check): | ||
345 | if check.type== "service": | ||
346 | command = "[{time}] PROCESS_SERVICE_CHECK_RESULT;{hostname};{servicename};{state};{output}"; | ||
347 | else: | ||
348 | command = "[{time}] PROCESS_HOST_CHECK_RESULT;{hostname};{state};{output}"; | ||
349 | formatted = command.format( | ||
350 | time=int(time.time()), | ||
351 | hostname=check.hostname, | ||
352 | state=check.state, | ||
353 | output=check.output, | ||
354 | servicename=check.servicename, | ||
355 | ) | ||
356 | |||
357 | if not os.path.exists(COMMAND_FILE): | ||
358 | raise Exception(ERROR_BAD_COMMAND_FILE) | ||
359 | if not os.access(COMMAND_FILE, os.W_OK): | ||
360 | raise Exception(ERROR_COMMAND_FILE_OPEN_WRITE) | ||
361 | if not os.access(COMMAND_FILE, os.W_OK): | ||
362 | raise Exception(ERROR_COMMAND_FILE_OPEN_WRITE) | ||
363 | try: | ||
364 | with open(COMMAND_FILE, "w") as c: | ||
365 | c.write(formatted + "\n") | ||
366 | except Exception as e: | ||
367 | raise Exception(ERROR_BAD_WRITE) | ||
368 | |||
369 | def render_error(error): | ||
370 | return jsonify({ | ||
371 | "status": "error", | ||
372 | "message": error, | ||
373 | }) | ||
374 | |||
375 | def render_response(checks, errors): | ||
376 | if checks > 0: | ||
377 | return jsonify({ | ||
378 | "status": "ok", | ||
379 | "result": { | ||
380 | "checks": checks, | ||
381 | "errors": errors, | ||
382 | } | ||
383 | }) | ||
384 | else: | ||
385 | return jsonify({ | ||
386 | "status": "error", | ||
387 | "message": ERROR_NO_CORRECT_STATUS, | ||
388 | }) | ||
389 | |||
390 | class CheckResult: | ||
391 | def __init__(self, hostname, state, output, servicename, checktype): | ||
392 | self.hostname = hostname | ||
393 | self.state = state | ||
394 | self.output = output | ||
395 | self.servicename = servicename | ||
396 | self.type = checktype | ||
397 | |||
398 | @classmethod | ||
399 | def from_json(klass, j): | ||
400 | if not isinstance(j, dict): | ||
401 | return None | ||
402 | for key in ["hostname", "state", "output"]: | ||
403 | if key not in j or not isinstance(j[key], str): | ||
404 | return None | ||
405 | for key in ["servicename", "type"]: | ||
406 | if key in j and not isinstance(j[key], str): | ||
407 | return None | ||
408 | return klass( | ||
409 | j["hostname"], | ||
410 | j["state"], | ||
411 | j["output"], | ||
412 | j.get("servicename", ""), | ||
413 | j.get("type", "host")) | ||
414 | |||
diff --git a/systems/monitoring-1/status_engine.nix b/systems/monitoring-1/status_engine.nix new file mode 100644 index 0000000..fc6afc0 --- /dev/null +++ b/systems/monitoring-1/status_engine.nix | |||
@@ -0,0 +1,123 @@ | |||
1 | { config, pkgs, lib, name, ... }: | ||
2 | let | ||
3 | package = pkgs.status-engine-worker.override { config_file = config.secrets.fullPaths."status_engine"; }; | ||
4 | env = config.myEnv.tools.status_engine; | ||
5 | in | ||
6 | { | ||
7 | config = lib.mkIf config.myServices.status.enable { | ||
8 | systemd.services.gearmand = { | ||
9 | description = "Gearman daemon"; | ||
10 | after = [ "network.target" ]; | ||
11 | wantedBy = [ "multi-user.target" ]; | ||
12 | serviceConfig = { | ||
13 | DynamicUser = true; | ||
14 | User = "gearmand"; | ||
15 | Type = "simple"; | ||
16 | ExecStart = "${pkgs.gearmand}/bin/gearmand --syslog -L 127.0.0.1 -q libsqlite3 --libsqlite3-db /var/lib/gearmand/gearmand.db --store-queue-on-shutdown -l stderr -P /run/gearmand/gearmand.pid"; | ||
17 | RuntimeDirectory = "gearmand"; | ||
18 | StateDirectory = "gearmand"; | ||
19 | }; | ||
20 | }; | ||
21 | |||
22 | secrets.keys."status_engine" = { | ||
23 | permissions = "0400"; | ||
24 | user = "naemon"; | ||
25 | group = "naemon"; | ||
26 | text = '' | ||
27 | node_name: ${name} | ||
28 | use_gearman: 1 | ||
29 | gearman: | ||
30 | address: 127.0.0.1 | ||
31 | port: 4730 | ||
32 | timeout: 1000 | ||
33 | use_rabbitmq: 0 | ||
34 | use_redis: 1 | ||
35 | redis: | ||
36 | address: 127.0.0.1 | ||
37 | port: 6379 | ||
38 | db: 0 | ||
39 | store_live_data_in_archive_backend: 1 | ||
40 | use_mysql: 1 | ||
41 | mysql: | ||
42 | host: ${env.mysql.remoteHost} | ||
43 | port: ${builtins.toString env.mysql.port} | ||
44 | username: ${env.mysql.user} | ||
45 | password: ${env.mysql.password} | ||
46 | database: ${env.mysql.database} | ||
47 | use_crate: 0 | ||
48 | number_of_bulk_records: 100 | ||
49 | max_bulk_delay: 5 | ||
50 | number_servicestatus_worker: 1 | ||
51 | number_hoststatus_worker: 1 | ||
52 | number_logentry_worker: 1 | ||
53 | number_statechange_worker: 1 | ||
54 | number_hostcheck_worker: 1 | ||
55 | number_servicecheck_worker: 1 | ||
56 | number_misc_worker: 1 | ||
57 | |||
58 | process_perfdata: 1 | ||
59 | number_perfdata_worker: 1 | ||
60 | perfdata_backend: | ||
61 | - mysql | ||
62 | |||
63 | check_for_commands: 1 | ||
64 | command_check_interval: 15 | ||
65 | external_command_file: /run/naemon/naemon.cmd | ||
66 | query_handler: /run/naemon/naemon.qh | ||
67 | submit_method: qh | ||
68 | |||
69 | syslog_enabled: 1 | ||
70 | syslog_tag: statusengine-worker | ||
71 | |||
72 | # Archive age | ||
73 | age_hostchecks: 5 | ||
74 | age_host_acknowledgements: 60 | ||
75 | age_host_notifications: 60 | ||
76 | age_host_statehistory: 365 | ||
77 | age_host_downtimes: 60 | ||
78 | age_servicechecks: 5 | ||
79 | age_service_acknowledgements: 60 | ||
80 | age_service_notifications: 60 | ||
81 | age_service_statehistory: 365 | ||
82 | age_service_downtimes: 60 | ||
83 | age_logentries: 5 | ||
84 | age_tasks: 1 | ||
85 | age_perfdata: 90 | ||
86 | |||
87 | disable_http_proxy: 1 | ||
88 | ''; | ||
89 | }; | ||
90 | |||
91 | services.redis.servers."" = rec { | ||
92 | enable = true; | ||
93 | bind = "127.0.0.1"; | ||
94 | }; | ||
95 | |||
96 | services.cron = { | ||
97 | mailto = "cron@immae.eu"; | ||
98 | systemCronJobs = [ | ||
99 | "0 0 * * * naemon cd ${package} && ./bin/Console.php cleanup" | ||
100 | ]; | ||
101 | }; | ||
102 | |||
103 | environment.systemPackages = [ | ||
104 | pkgs.gearmand | ||
105 | (pkgs.writeScriptBin "status-engine-worker" '' | ||
106 | #! ${pkgs.stdenv.shell} | ||
107 | cd ${package} | ||
108 | exec sudo -E -u naemon ./bin/Console.php "$@" | ||
109 | '') | ||
110 | ]; | ||
111 | systemd.services.status_engine_worker = { | ||
112 | description = "Status engine worker"; | ||
113 | after = [ "network.target" ]; | ||
114 | wantedBy = [ "multi-user.target" ]; | ||
115 | serviceConfig = { | ||
116 | Type = "simple"; | ||
117 | Restart = "on-failure"; | ||
118 | User = "naemon"; | ||
119 | ExecStart = "${package}/bin/StatusengineWorker.php"; | ||
120 | }; | ||
121 | }; | ||
122 | }; | ||
123 | } | ||