1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2018 Sou Bunnbu <iyzsong@member.fsf.org>
3 ;;; Copyright © 2018 Gábor Boskovits <boskovits@gmail.com>
4 ;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
6 ;;; This file is part of GNU Guix.
8 ;;; GNU Guix is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
13 ;;; GNU Guix is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;;; GNU General Public License for more details.
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21 (define-module (gnu services monitoring)
22 #:use-module (gnu services)
23 #:use-module (gnu services configuration)
24 #:use-module (gnu services shepherd)
25 #:use-module (gnu services web)
26 #:use-module (gnu packages admin)
27 #:use-module (gnu packages monitoring)
28 #:use-module (gnu system shadow)
29 #:use-module (guix gexp)
30 #:use-module (guix packages)
31 #:use-module (guix records)
32 #:use-module ((guix ui) #:select (display-hint))
33 #:use-module (ice-9 match)
34 #:use-module (ice-9 rdelim)
35 #:use-module (srfi srfi-26)
36 #:use-module (srfi srfi-35)
37 #:export (darkstat-configuration
38 prometheus-node-exporter-configuration
40 prometheus-node-exporter-service-type
42 zabbix-server-configuration
43 zabbix-server-service-type
44 zabbix-agent-configuration
45 zabbix-agent-service-type
46 zabbix-front-end-configuration
47 zabbix-front-end-service-type
48 %zabbix-front-end-configuration-nginx))
55 (define-record-type* <darkstat-configuration>
56 darkstat-configuration make-darkstat-configuration darkstat-configuration?
57 (package darkstat-configuration-package
59 (interface darkstat-configuration-interface)
60 (port darkstat-configuration-port
62 (bind-address darkstat-configuration-bind-address
63 (default "127.0.0.1"))
64 (base darkstat-configuration-base
67 (define %darkstat-accounts
72 (comment "darkstat daemon user")
73 (home-directory "/var/lib/darkstat")
74 (shell (file-append shadow "/sbin/nologin")))
79 (define darkstat-shepherd-service
81 (($ <darkstat-configuration>
82 package interface port bind-address base)
84 (documentation "Network statistics gatherer.")
85 (provision '(darkstat))
86 (requirement '(networking))
87 (start #~(make-forkexec-constructor
88 (list #$(file-append package "/sbin/darkstat")
93 "--syslog" "--no-daemon"
94 "--chroot" "/var/lib/darkstat"
96 "--import" "darkstat.db"
97 "--export" "darkstat.db")))
98 (stop #~(make-kill-destructor))))))
100 (define darkstat-service-type
104 "Run @command{darkstat} to serve network traffic statictics reports over
107 (list (service-extension account-service-type
108 (const %darkstat-accounts))
109 (service-extension shepherd-root-service-type
110 (compose list darkstat-shepherd-service))))))
112 (define-record-type* <prometheus-node-exporter-configuration>
113 prometheus-node-exporter-configuration
114 make-prometheus-node-exporter-configuration
115 prometheus-node-exporter-configuration?
116 (package prometheus-node-exporter-configuration-package
117 (default go-github-com-prometheus-node-exporter))
118 (web-listen-address prometheus-node-exporter-web-listen-address
121 (define prometheus-node-exporter-shepherd-service
123 (( $ <prometheus-node-exporter-configuration>
124 package web-listen-address)
126 (documentation "Prometheus node exporter.")
127 (provision '(prometheus-node-exporter))
128 (requirement '(networking))
129 (start #~(make-forkexec-constructor
130 (list #$(file-append package "/bin/node_exporter")
131 "--web.listen-address" #$web-listen-address)))
132 (stop #~(make-kill-destructor))))))
134 (define prometheus-node-exporter-service-type
136 (name 'prometheus-node-exporter)
138 "Run @command{node_exporter} to serve hardware and OS metrics to
141 (list (service-extension
142 shepherd-root-service-type
143 (compose list prometheus-node-exporter-shepherd-service))))))
150 (define (uglify-field-name field-name)
153 (if (member (string->symbol str) '(ca db ssl))
155 (string-capitalize str)))
156 (string-split (string-delete #\?
157 (symbol->string field-name))
160 (define (serialize-field field-name val)
161 (format #t "~a=~a~%" (uglify-field-name field-name) val))
163 (define (serialize-number field-name val)
164 (serialize-field field-name (number->string val)))
166 (define (serialize-list field-name val)
167 (if (null? val) "" (serialize-field field-name (string-join val ","))))
169 (define (serialize-string field-name val)
170 (if (and (string? val) (string=? val ""))
172 (serialize-field field-name val)))
174 (define group? string?)
176 (define serialize-group
179 (define include-files? list?)
181 (define (serialize-include-files field-name val)
182 (if (null? val) "" (for-each (cut serialize-field 'include <>) val)))
184 (define extra-options? string?)
186 (define (serialize-extra-options field-name val)
187 (if (null? val) "" (display val)))
189 (define (nginx-server-configuration-list? val)
190 (and (list? val) (and-map nginx-server-configuration? val)))
192 (define (serialize-nginx-server-configuration-list field-name val)
195 (define-configuration zabbix-server-configuration
197 (package zabbix-server)
198 "The zabbix-server package.")
201 "User who will run the Zabbix server.")
202 (group ;for zabbix-server-account procedure
204 "Group who will run the Zabbix server.")
207 "Database host name.")
216 "Database password. Please, use @code{include-files} with
217 @code{DBPassword=SECRET} inside a specified file instead.")
223 "Specifies where log messages are written to:
225 @item @code{system} - syslog.
226 @item @code{file} - file specified with @code{log-file} parameter.
227 @item @code{console} - standard output.
230 (string "/var/log/zabbix/server.log")
231 "Log file name for @code{log-type} @code{file} parameter.")
233 (string "/var/run/zabbix/zabbix_server.pid")
236 (string "/etc/ssl/certs/ca-certificates.crt")
237 "The location of certificate authority (CA) files for SSL server
238 certificate verification.")
240 (string "/etc/ssl/certs")
241 "Location of SSL client certificates.")
244 "Extra options will be appended to Zabbix server configuration file.")
247 "You may include individual files or all files in a directory in the
248 configuration file."))
250 (define (zabbix-server-account config)
251 "Return the user accounts and user groups for CONFIG."
252 (let ((zabbix-user (zabbix-server-configuration-user config))
253 (zabbix-group (zabbix-server-configuration-group config)))
254 (list (user-group (name zabbix-group) (system? #t))
259 (comment "zabbix privilege separation user")
260 (home-directory (string-append "/var/run/" zabbix-user))
261 (shell (file-append shadow "/sbin/nologin"))))))
263 (define (zabbix-server-config-file config)
264 "Return the zabbix-server configuration file corresponding to CONFIG."
268 (call-with-output-file #$output
270 (display "# Generated by 'zabbix-server-service'.\n" port)
271 (display #$(with-output-to-string
273 (serialize-configuration
274 config zabbix-server-configuration-fields)))
278 (define (zabbix-server-activation config)
279 "Return the activation gexp for CONFIG."
280 (with-imported-modules '((guix build utils)
283 (use-modules (guix build utils)
285 (let ((user (getpw #$(zabbix-server-configuration-user config))))
286 (for-each (lambda (file)
287 (let ((directory (dirname file)))
289 (chown directory (passwd:uid user) (passwd:gid user))
290 (chmod directory #o755)))
291 (list #$(zabbix-server-configuration-log-file config)
292 #$(zabbix-server-configuration-pid-file config)
293 "/etc/zabbix/maintenance.inc.php"))))))
295 (define (zabbix-server-shepherd-service config)
296 "Return a <shepherd-service> for Zabbix server with CONFIG."
297 (list (shepherd-service
298 (provision '(zabbix-server))
299 (documentation "Run Zabbix server daemon.")
300 (start #~(make-forkexec-constructor
301 (list #$(file-append (zabbix-server-configuration-zabbix-server config)
302 "/sbin/zabbix_server")
303 "--config" #$(zabbix-server-config-file config)
305 #:user #$(zabbix-server-configuration-user config)
306 #:group #$(zabbix-server-configuration-group config)
307 #:pid-file #$(zabbix-server-configuration-pid-file config)
308 #:environment-variables
309 (list "SSL_CERT_DIR=/run/current-system/profile\
311 "SSL_CERT_FILE=/run/current-system/profile\
312 /etc/ssl/certs/ca-certificates.crt")))
313 (stop #~(make-kill-destructor)))))
315 (define zabbix-server-service-type
317 (name 'zabbix-server)
319 (list (service-extension shepherd-root-service-type
320 zabbix-server-shepherd-service)
321 (service-extension account-service-type
322 zabbix-server-account)
323 (service-extension activation-service-type
324 zabbix-server-activation)))
325 (default-value (zabbix-server-configuration))))
327 (define (generate-zabbix-server-documentation)
328 (generate-documentation
329 `((zabbix-server-configuration
330 ,zabbix-server-configuration-fields))
331 'zabbix-server-configuration))
333 (define-configuration zabbix-agent-configuration
335 (package zabbix-agentd)
336 "The zabbix-agent package.")
339 "User who will run the Zabbix agent.")
342 "Group who will run the Zabbix agent.")
344 (string "Zabbix server")
345 "Unique, case sensitive hostname which is required for active checks and
346 must match hostname as configured on the server.")
349 "Specifies where log messages are written to:
351 @item @code{system} - syslog.
352 @item @code{file} - file specified with @code{log-file} parameter.
353 @item @code{console} - standard output.
356 (string "/var/log/zabbix/agent.log")
357 "Log file name for @code{log-type} @code{file} parameter.")
359 (string "/var/run/zabbix/zabbix_agent.pid")
362 (list '("127.0.0.1"))
363 "List of IP addresses, optionally in CIDR notation, or hostnames of Zabbix
364 servers and Zabbix proxies. Incoming connections will be accepted only from
365 the hosts listed here.")
367 (list '("127.0.0.1"))
368 "List of IP:port (or hostname:port) pairs of Zabbix servers and Zabbix
369 proxies for active checks. If port is not specified, default port is used.
370 If this parameter is not specified, active checks are disabled.")
373 "Extra options will be appended to Zabbix server configuration file.")
376 "You may include individual files or all files in a directory in the
377 configuration file."))
379 (define (zabbix-agent-account config)
380 "Return the user accounts and user groups for CONFIG."
381 (let ((zabbix-user "zabbix")
382 (zabbix-group "zabbix"))
383 (list (user-group (name zabbix-group) (system? #t))
388 (comment "zabbix privilege separation user")
389 (home-directory (string-append "/var/run/" zabbix-user))
390 (shell (file-append shadow "/sbin/nologin"))))))
392 (define (zabbix-agent-activation config)
393 "Return the activation gexp for CONFIG."
394 (with-imported-modules '((guix build utils)
397 (use-modules (guix build utils)
400 (getpw #$(zabbix-agent-configuration-user config))))
401 (for-each (lambda (file)
402 (let ((directory (dirname file)))
404 (chown directory (passwd:uid user) (passwd:gid user))
405 (chmod directory #o755)))
406 (list #$(zabbix-agent-configuration-log-file config)
407 #$(zabbix-agent-configuration-pid-file config)))))))
409 (define (zabbix-agent-config-file config)
410 "Return the zabbix-agent configuration file corresponding to CONFIG."
414 (call-with-output-file #$output
416 (display "# Generated by 'zabbix-agent-service'.\n" port)
417 (display #$(with-output-to-string
419 (serialize-configuration
420 config zabbix-agent-configuration-fields)))
424 (define (zabbix-agent-shepherd-service config)
425 "Return a <shepherd-service> for Zabbix agent with CONFIG."
426 (list (shepherd-service
427 (provision '(zabbix-agent))
428 (documentation "Run Zabbix agent daemon.")
429 (start #~(make-forkexec-constructor
430 (list #$(file-append (zabbix-agent-configuration-zabbix-agent config)
431 "/sbin/zabbix_agentd")
432 "--config" #$(zabbix-agent-config-file config)
434 #:user #$(zabbix-agent-configuration-user config)
435 #:group #$(zabbix-agent-configuration-group config)
436 #:pid-file #$(zabbix-agent-configuration-pid-file config)
437 #:environment-variables
438 (list "SSL_CERT_DIR=/run/current-system/profile\
440 "SSL_CERT_FILE=/run/current-system/profile\
441 /etc/ssl/certs/ca-certificates.crt")))
442 (stop #~(make-kill-destructor)))))
444 (define zabbix-agent-service-type
448 (list (service-extension shepherd-root-service-type
449 zabbix-agent-shepherd-service)
450 (service-extension account-service-type
451 zabbix-agent-account)
452 (service-extension activation-service-type
453 zabbix-agent-activation)))
454 (default-value (zabbix-agent-configuration))))
456 (define (generate-zabbix-agent-documentation)
457 (generate-documentation
458 `((zabbix-agent-configuration
459 ,zabbix-agent-configuration-fields))
460 'zabbix-agent-configuration))
462 (define %zabbix-front-end-configuration-nginx
463 (nginx-server-configuration
464 (root #~(string-append #$zabbix-server:front-end "/share/zabbix/php"))
465 (index '("index.php"))
467 (let ((php-location (nginx-php-location)))
468 (list (nginx-location-configuration
469 (inherit php-location)
470 (body (append (nginx-location-configuration-body php-location)
472 fastcgi_param PHP_VALUE \"post_max_size = 16M
473 max_execution_time = 300\";
476 (define-configuration zabbix-front-end-configuration
477 ;; TODO: Specify zabbix front-end package.
479 ;; (package zabbix-front-end)
480 ;; "The zabbix-front-end package.")
482 (nginx-server-configuration-list
483 (list %zabbix-front-end-configuration-nginx))
484 "NGINX configuration.")
487 "Database host name.")
499 "Database password. Please, use @code{db-secret-file} instead.")
502 "Secret file which will be appended to @file{zabbix.conf.php} file. This
503 file contains credentials for use by Zabbix front-end. You are expected to
504 create it manually.")
507 "Zabbix server hostname.")
510 "Zabbix server port."))
512 (define zabbix-front-end-config
514 (($ <zabbix-front-end-configuration>
515 _ db-host db-port db-name db-user db-password db-secret-file
516 zabbix-host zabbix-port)
517 (mixed-text-file "zabbix.conf.php"
520 // Zabbix GUI configuration file.
523 $DB['TYPE'] = 'POSTGRESQL';
524 $DB['SERVER'] = '" db-host "';
525 $DB['PORT'] = '" (number->string db-port) "';
526 $DB['DATABASE'] = '" db-name "';
527 $DB['USER'] = '" db-user "';
528 $DB['PASSWORD'] = '" (if (string-null? db-password)
529 (if (string-null? db-secret-file)
533 you must provide either 'db-secret-file' or 'db-password'"))))
535 (with-input-from-file db-secret-file
539 Consider using @code{db-secret-file} instead of @code{db-password} and unset
540 @code{db-password} for security in @code{zabbix-front-end-configuration}.")
543 // Schema name. Used for IBM DB2 and PostgreSQL.
546 $ZBX_SERVER = '" zabbix-host "';
547 $ZBX_SERVER_PORT = '" (number->string zabbix-port) "';
548 $ZBX_SERVER_NAME = '';
550 $IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
553 (define %maintenance.inc.php
554 ;; Empty php file to allow us move zabbix-frontend configs to ‘/etc/zabbix’
555 ;; directory. See ‘install-front-end’ phase in
556 ;; (@ (gnu packages monitoring) zabbix-server) package.
561 (define (zabbix-front-end-activation config)
562 "Return the activation gexp for CONFIG."
564 (use-modules (guix build utils))
565 (mkdir-p "/etc/zabbix")
566 (call-with-output-file "/etc/zabbix/maintenance.inc.php"
568 (display #$%maintenance.inc.php port)))
569 (copy-file #$(zabbix-front-end-config config)
570 "/etc/zabbix/zabbix.conf.php")))
572 (define zabbix-front-end-service-type
574 (name 'zabbix-front-end)
576 (list (service-extension activation-service-type
577 zabbix-front-end-activation)
578 (service-extension nginx-service-type
579 zabbix-front-end-configuration-nginx)
580 ;; Make sure php-fpm is instantiated.
581 (service-extension php-fpm-service-type
583 (default-value (zabbix-front-end-configuration))
585 "Run the zabbix-front-end web interface, which allows users to interact
586 with Zabbix server.")))
588 (define (generate-zabbix-front-end-documentation)
589 (generate-documentation
590 `((zabbix-front-end-configuration
591 ,zabbix-front-end-configuration-fields))
592 'zabbix-front-end-configuration))