monitoring.scm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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>
  5. ;;;
  6. ;;; This file is part of GNU Guix.
  7. ;;;
  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.
  12. ;;;
  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.
  17. ;;;
  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/>.
  20. (define-module (gnu services monitoring)
  21. #:use-module (gnu services)
  22. #:use-module (gnu services configuration)
  23. #:use-module (gnu services shepherd)
  24. #:use-module (gnu services web)
  25. #:use-module (gnu packages admin)
  26. #:use-module (gnu packages monitoring)
  27. #:use-module (gnu system shadow)
  28. #:use-module (guix gexp)
  29. #:use-module (guix packages)
  30. #:use-module (guix records)
  31. #:use-module ((guix ui) #:select (display-hint))
  32. #:use-module (ice-9 match)
  33. #:use-module (ice-9 rdelim)
  34. #:use-module (srfi srfi-26)
  35. #:use-module (srfi srfi-35)
  36. #:export (darkstat-configuration
  37. prometheus-node-exporter-configuration
  38. darkstat-service-type
  39. prometheus-node-exporter-service-type
  40. zabbix-server-configuration
  41. zabbix-server-service-type
  42. zabbix-agent-configuration
  43. zabbix-agent-service-type
  44. zabbix-front-end-configuration
  45. zabbix-front-end-service-type
  46. %zabbix-front-end-configuration-nginx))
  47. ;;;
  48. ;;; darkstat
  49. ;;;
  50. (define-record-type* <darkstat-configuration>
  51. darkstat-configuration make-darkstat-configuration darkstat-configuration?
  52. (package darkstat-configuration-package
  53. (default darkstat))
  54. (interface darkstat-configuration-interface)
  55. (port darkstat-configuration-port
  56. (default "667"))
  57. (bind-address darkstat-configuration-bind-address
  58. (default "127.0.0.1"))
  59. (base darkstat-configuration-base
  60. (default "/")))
  61. (define %darkstat-accounts
  62. (list (user-account
  63. (name "darkstat")
  64. (group "darkstat")
  65. (system? #t)
  66. (comment "darkstat daemon user")
  67. (home-directory "/var/lib/darkstat")
  68. (shell (file-append shadow "/sbin/nologin")))
  69. (user-group
  70. (name "darkstat")
  71. (system? #t))))
  72. (define darkstat-shepherd-service
  73. (match-lambda
  74. (($ <darkstat-configuration>
  75. package interface port bind-address base)
  76. (shepherd-service
  77. (documentation "Network statistics gatherer.")
  78. (provision '(darkstat))
  79. (requirement '(networking))
  80. (start #~(make-forkexec-constructor
  81. (list #$(file-append package "/sbin/darkstat")
  82. "-i" #$interface
  83. "-p" #$port
  84. "-b" #$bind-address
  85. "--base" #$base
  86. "--syslog" "--no-daemon"
  87. "--chroot" "/var/lib/darkstat"
  88. "--user" "darkstat"
  89. "--import" "darkstat.db"
  90. "--export" "darkstat.db")))
  91. (stop #~(make-kill-destructor))))))
  92. (define darkstat-service-type
  93. (service-type
  94. (name 'darkstat)
  95. (description
  96. "Run @command{darkstat} to serve network traffic statictics reports over
  97. HTTP.")
  98. (extensions
  99. (list (service-extension account-service-type
  100. (const %darkstat-accounts))
  101. (service-extension shepherd-root-service-type
  102. (compose list darkstat-shepherd-service))))))
  103. (define-record-type* <prometheus-node-exporter-configuration>
  104. prometheus-node-exporter-configuration
  105. make-prometheus-node-exporter-configuration
  106. prometheus-node-exporter-configuration?
  107. (package prometheus-node-exporter-configuration-package
  108. (default go-github-com-prometheus-node-exporter))
  109. (web-listen-address prometheus-node-exporter-web-listen-address
  110. (default ":9100")))
  111. (define prometheus-node-exporter-shepherd-service
  112. (match-lambda
  113. (( $ <prometheus-node-exporter-configuration>
  114. package web-listen-address)
  115. (shepherd-service
  116. (documentation "Prometheus node exporter.")
  117. (provision '(prometheus-node-exporter))
  118. (requirement '(networking))
  119. (start #~(make-forkexec-constructor
  120. (list #$(file-append package "/bin/node_exporter")
  121. "--web.listen-address" #$web-listen-address)))
  122. (stop #~(make-kill-destructor))))))
  123. (define prometheus-node-exporter-service-type
  124. (service-type
  125. (name 'prometheus-node-exporter)
  126. (description
  127. "Run @command{node_exporter} to serve hardware and OS metrics to
  128. prometheus.")
  129. (extensions
  130. (list (service-extension
  131. shepherd-root-service-type
  132. (compose list prometheus-node-exporter-shepherd-service))))))
  133. ;;;
  134. ;;; Zabbix server
  135. ;;;
  136. (define (uglify-field-name field-name)
  137. (apply string-append
  138. (map (lambda (str)
  139. (if (member (string->symbol str) '(ca db ssl))
  140. (string-upcase str)
  141. (string-capitalize str)))
  142. (string-split (string-delete #\?
  143. (symbol->string field-name))
  144. #\-))))
  145. (define (serialize-field field-name val)
  146. (format #t "~a=~a~%" (uglify-field-name field-name) val))
  147. (define (serialize-number field-name val)
  148. (serialize-field field-name (number->string val)))
  149. (define (serialize-list field-name val)
  150. (if (null? val) "" (serialize-field field-name (string-join val ","))))
  151. (define (serialize-string field-name val)
  152. (if (and (string? val) (string=? val ""))
  153. ""
  154. (serialize-field field-name val)))
  155. (define group? string?)
  156. (define serialize-group
  157. (const ""))
  158. (define include-files? list?)
  159. (define (serialize-include-files field-name val)
  160. (if (null? val) "" (for-each (cut serialize-field 'include <>) val)))
  161. (define extra-options? string?)
  162. (define (serialize-extra-options field-name val)
  163. (if (null? val) "" (display val)))
  164. (define (nginx-server-configuration-list? val)
  165. (and (list? val) (and-map nginx-server-configuration? val)))
  166. (define (serialize-nginx-server-configuration-list field-name val)
  167. "")
  168. (define-configuration zabbix-server-configuration
  169. (zabbix-server
  170. (package zabbix-server)
  171. "The zabbix-server package.")
  172. (user
  173. (string "zabbix")
  174. "User who will run the Zabbix server.")
  175. (group ;for zabbix-server-account procedure
  176. (group "zabbix")
  177. "Group who will run the Zabbix server.")
  178. (db-host
  179. (string "127.0.0.1")
  180. "Database host name.")
  181. (db-name
  182. (string "zabbix")
  183. "Database name.")
  184. (db-user
  185. (string "zabbix")
  186. "Database user.")
  187. (db-password
  188. (string "")
  189. "Database password. Please, use @code{include-files} with
  190. @code{DBPassword=SECRET} inside a specified file instead.")
  191. (db-port
  192. (number 5432)
  193. "Database port.")
  194. (log-type
  195. (string "")
  196. "Specifies where log messages are written to:
  197. @itemize
  198. @item @code{system} - syslog.
  199. @item @code{file} - file specified with @code{log-file} parameter.
  200. @item @code{console} - standard output.
  201. @end itemize\n")
  202. (log-file
  203. (string "/var/log/zabbix/server.log")
  204. "Log file name for @code{log-type} @code{file} parameter.")
  205. (pid-file
  206. (string "/var/run/zabbix/zabbix_server.pid")
  207. "Name of PID file.")
  208. (ssl-ca-location
  209. (string "/etc/ssl/certs/ca-certificates.crt")
  210. "The location of certificate authority (CA) files for SSL server
  211. certificate verification.")
  212. (ssl-cert-location
  213. (string "/etc/ssl/certs")
  214. "Location of SSL client certificates.")
  215. (extra-options
  216. (extra-options "")
  217. "Extra options will be appended to Zabbix server configuration file.")
  218. (include-files
  219. (include-files '())
  220. "You may include individual files or all files in a directory in the
  221. configuration file."))
  222. (define (zabbix-server-account config)
  223. "Return the user accounts and user groups for CONFIG."
  224. (let ((zabbix-user (zabbix-server-configuration-user config))
  225. (zabbix-group (zabbix-server-configuration-group config)))
  226. (list (user-group (name zabbix-group) (system? #t))
  227. (user-account
  228. (name zabbix-user)
  229. (system? #t)
  230. (group zabbix-group)
  231. (comment "zabbix privilege separation user")
  232. (home-directory (string-append "/var/run/" zabbix-user))
  233. (shell #~(string-append #$shadow "/sbin/nologin"))))))
  234. (define (zabbix-server-config-file config)
  235. "Return the zabbix-server configuration file corresponding to CONFIG."
  236. (computed-file
  237. "zabbix_server.conf"
  238. #~(begin
  239. (call-with-output-file #$output
  240. (lambda (port)
  241. (display "# Generated by 'zabbix-server-service'.\n" port)
  242. (display #$(with-output-to-string
  243. (lambda ()
  244. (serialize-configuration
  245. config zabbix-server-configuration-fields)))
  246. port)
  247. #t)))))
  248. (define (zabbix-server-activation config)
  249. "Return the activation gexp for CONFIG."
  250. (with-imported-modules '((guix build utils)
  251. (ice-9 rdelim))
  252. #~(begin
  253. (use-modules (guix build utils)
  254. (ice-9 rdelim))
  255. (let ((user (getpw #$(zabbix-server-configuration-user config))))
  256. (for-each (lambda (file)
  257. (let ((directory (dirname file)))
  258. (mkdir-p directory)
  259. (chown directory (passwd:uid user) (passwd:gid user))
  260. (chmod directory #o755)))
  261. (list #$(zabbix-server-configuration-log-file config)
  262. #$(zabbix-server-configuration-pid-file config)
  263. "/etc/zabbix/maintenance.inc.php"))))))
  264. (define (zabbix-server-shepherd-service config)
  265. "Return a <shepherd-service> for Zabbix server with CONFIG."
  266. (list (shepherd-service
  267. (provision '(zabbix-server))
  268. (documentation "Run Zabbix server daemon.")
  269. (start #~(make-forkexec-constructor
  270. (list #$(file-append (zabbix-server-configuration-zabbix-server config)
  271. "/sbin/zabbix_server")
  272. "--config" #$(zabbix-server-config-file config)
  273. "--foreground")
  274. #:user #$(zabbix-server-configuration-user config)
  275. #:group #$(zabbix-server-configuration-group config)
  276. #:pid-file #$(zabbix-server-configuration-pid-file config)
  277. #:environment-variables
  278. (list "SSL_CERT_DIR=/run/current-system/profile\
  279. /etc/ssl/certs"
  280. "SSL_CERT_FILE=/run/current-system/profile\
  281. /etc/ssl/certs/ca-certificates.crt")))
  282. (stop #~(make-kill-destructor)))))
  283. (define zabbix-server-service-type
  284. (service-type
  285. (name 'zabbix-server)
  286. (extensions
  287. (list (service-extension shepherd-root-service-type
  288. zabbix-server-shepherd-service)
  289. (service-extension account-service-type
  290. zabbix-server-account)
  291. (service-extension activation-service-type
  292. zabbix-server-activation)))
  293. (default-value (zabbix-server-configuration))))
  294. (define (generate-zabbix-server-documentation)
  295. (generate-documentation
  296. `((zabbix-server-configuration
  297. ,zabbix-server-configuration-fields))
  298. 'zabbix-server-configuration))
  299. (define-configuration zabbix-agent-configuration
  300. (zabbix-agent
  301. (package zabbix-agentd)
  302. "The zabbix-agent package.")
  303. (user
  304. (string "zabbix")
  305. "User who will run the Zabbix agent.")
  306. (group
  307. (group "zabbix")
  308. "Group who will run the Zabbix agent.")
  309. (hostname
  310. (string "Zabbix server")
  311. "Unique, case sensitive hostname which is required for active checks and
  312. must match hostname as configured on the server.")
  313. (log-type
  314. (string "")
  315. "Specifies where log messages are written to:
  316. @itemize
  317. @item @code{system} - syslog.
  318. @item @code{file} - file specified with @code{log-file} parameter.
  319. @item @code{console} - standard output.
  320. @end itemize\n")
  321. (log-file
  322. (string "/var/log/zabbix/agent.log")
  323. "Log file name for @code{log-type} @code{file} parameter.")
  324. (pid-file
  325. (string "/var/run/zabbix/zabbix_agent.pid")
  326. "Name of PID file.")
  327. (server
  328. (list '("127.0.0.1"))
  329. "List of IP addresses, optionally in CIDR notation, or hostnames of Zabbix
  330. servers and Zabbix proxies. Incoming connections will be accepted only from
  331. the hosts listed here.")
  332. (server-active
  333. (list '("127.0.0.1"))
  334. "List of IP:port (or hostname:port) pairs of Zabbix servers and Zabbix
  335. proxies for active checks. If port is not specified, default port is used.
  336. If this parameter is not specified, active checks are disabled.")
  337. (extra-options
  338. (extra-options "")
  339. "Extra options will be appended to Zabbix server configuration file.")
  340. (include-files
  341. (include-files '())
  342. "You may include individual files or all files in a directory in the
  343. configuration file."))
  344. (define (zabbix-agent-account config)
  345. "Return the user accounts and user groups for CONFIG."
  346. (let ((zabbix-user "zabbix")
  347. (zabbix-group "zabbix"))
  348. (list (user-group (name zabbix-group) (system? #t))
  349. (user-account
  350. (name zabbix-user)
  351. (system? #t)
  352. (group zabbix-group)
  353. (comment "zabbix privilege separation user")
  354. (home-directory (string-append "/var/run/" zabbix-user))
  355. (shell #~(string-append #$shadow "/sbin/nologin"))))))
  356. (define (zabbix-agent-activation config)
  357. "Return the activation gexp for CONFIG."
  358. (with-imported-modules '((guix build utils)
  359. (ice-9 rdelim))
  360. #~(begin
  361. (use-modules (guix build utils)
  362. (ice-9 rdelim))
  363. (let ((user
  364. (getpw #$(zabbix-agent-configuration-user config))))
  365. (for-each (lambda (file)
  366. (let ((directory (dirname file)))
  367. (mkdir-p directory)
  368. (chown directory (passwd:uid user) (passwd:gid user))
  369. (chmod directory #o755)))
  370. (list #$(zabbix-agent-configuration-log-file config)
  371. #$(zabbix-agent-configuration-pid-file config)))))))
  372. (define (zabbix-agent-config-file config)
  373. "Return the zabbix-agent configuration file corresponding to CONFIG."
  374. (computed-file
  375. "zabbix_agent.conf"
  376. #~(begin
  377. (call-with-output-file #$output
  378. (lambda (port)
  379. (display "# Generated by 'zabbix-agent-service'.\n" port)
  380. (display #$(with-output-to-string
  381. (lambda ()
  382. (serialize-configuration
  383. config zabbix-agent-configuration-fields)))
  384. port)
  385. #t)))))
  386. (define (zabbix-agent-shepherd-service config)
  387. "Return a <shepherd-service> for Zabbix agent with CONFIG."
  388. (list (shepherd-service
  389. (provision '(zabbix-agent))
  390. (documentation "Run Zabbix agent daemon.")
  391. (start #~(make-forkexec-constructor
  392. (list #$(file-append (zabbix-agent-configuration-zabbix-agent config)
  393. "/sbin/zabbix_agentd")
  394. "--config" #$(zabbix-agent-config-file config)
  395. "--foreground")
  396. #:user #$(zabbix-agent-configuration-user config)
  397. #:group #$(zabbix-agent-configuration-group config)
  398. #:pid-file #$(zabbix-agent-configuration-pid-file config)
  399. #:environment-variables
  400. (list "SSL_CERT_DIR=/run/current-system/profile\
  401. /etc/ssl/certs"
  402. "SSL_CERT_FILE=/run/current-system/profile\
  403. /etc/ssl/certs/ca-certificates.crt")))
  404. (stop #~(make-kill-destructor)))))
  405. (define zabbix-agent-service-type
  406. (service-type
  407. (name 'zabbix-agent)
  408. (extensions
  409. (list (service-extension shepherd-root-service-type
  410. zabbix-agent-shepherd-service)
  411. (service-extension account-service-type
  412. zabbix-agent-account)
  413. (service-extension activation-service-type
  414. zabbix-agent-activation)))
  415. (default-value (zabbix-agent-configuration))))
  416. (define (generate-zabbix-agent-documentation)
  417. (generate-documentation
  418. `((zabbix-agent-configuration
  419. ,zabbix-agent-configuration-fields))
  420. 'zabbix-agent-configuration))
  421. (define %zabbix-front-end-configuration-nginx
  422. (nginx-server-configuration
  423. (root #~(string-append #$zabbix-server:front-end "/share/zabbix/php"))
  424. (index '("index.php"))
  425. (locations
  426. (let ((php-location (nginx-php-location)))
  427. (list (nginx-location-configuration
  428. (inherit php-location)
  429. (body (append (nginx-location-configuration-body php-location)
  430. (list "
  431. fastcgi_param PHP_VALUE \"post_max_size = 16M
  432. max_execution_time = 300\";
  433. ")))))))))
  434. (define-configuration zabbix-front-end-configuration
  435. ;; TODO: Specify zabbix front-end package.
  436. ;; (zabbix-
  437. ;; (package zabbix-front-end)
  438. ;; "The zabbix-front-end package.")
  439. (nginx
  440. (nginx-server-configuration-list
  441. (list %zabbix-front-end-configuration-nginx))
  442. "NGINX configuration.")
  443. (db-host
  444. (string "localhost")
  445. "Database host name.")
  446. (db-port
  447. (number 5432)
  448. "Database port.")
  449. (db-name
  450. (string "zabbix")
  451. "Database name.")
  452. (db-user
  453. (string "zabbix")
  454. "Database user.")
  455. (db-password
  456. (string "")
  457. "Database password. Please, use @code{db-secret-file} instead.")
  458. (db-secret-file
  459. (string "")
  460. "Secret file which will be appended to @file{zabbix.conf.php} file. This
  461. file contains credentials for use by Zabbix front-end. You are expected to
  462. create it manually.")
  463. (zabbix-host
  464. (string "localhost")
  465. "Zabbix server hostname.")
  466. (zabbix-port
  467. (number 10051)
  468. "Zabbix server port."))
  469. (define zabbix-front-end-config
  470. (match-lambda
  471. (($ <zabbix-front-end-configuration>
  472. _ db-host db-port db-name db-user db-password db-secret-file
  473. zabbix-host zabbix-port)
  474. (mixed-text-file "zabbix.conf.php"
  475. "\
  476. <?php
  477. // Zabbix GUI configuration file.
  478. global $DB;
  479. $DB['TYPE'] = 'POSTGRESQL';
  480. $DB['SERVER'] = '" db-host "';
  481. $DB['PORT'] = '" (number->string db-port) "';
  482. $DB['DATABASE'] = '" db-name "';
  483. $DB['USER'] = '" db-user "';
  484. $DB['PASSWORD'] = '" (if (string-null? db-password)
  485. (if (string-null? db-secret-file)
  486. (raise (condition
  487. (&message
  488. (message "\
  489. you must provide either 'db-secret-file' or 'db-password'"))))
  490. (string-trim-both
  491. (with-input-from-file db-secret-file
  492. read-string)))
  493. (begin
  494. (display-hint "\
  495. Consider using @code{db-secret-file} instead of @code{db-password} and unset
  496. @code{db-password} for security in @code{zabbix-front-end-configuration}.")
  497. db-password)) "';
  498. // Schema name. Used for IBM DB2 and PostgreSQL.
  499. $DB['SCHEMA'] = '';
  500. $ZBX_SERVER = '" zabbix-host "';
  501. $ZBX_SERVER_PORT = '" (number->string zabbix-port) "';
  502. $ZBX_SERVER_NAME = '';
  503. $IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
  504. "))))
  505. (define %maintenance.inc.php
  506. ;; Empty php file to allow us move zabbix-frontend configs to ‘/etc/zabbix’
  507. ;; directory. See ‘install-front-end’ phase in
  508. ;; (@ (gnu packages monitoring) zabbix-server) package.
  509. "\
  510. <?php
  511. ")
  512. (define (zabbix-front-end-activation config)
  513. "Return the activation gexp for CONFIG."
  514. #~(begin
  515. (use-modules (guix build utils))
  516. (mkdir-p "/etc/zabbix")
  517. (call-with-output-file "/etc/zabbix/maintenance.inc.php"
  518. (lambda (port)
  519. (display #$%maintenance.inc.php port)))
  520. (copy-file #$(zabbix-front-end-config config)
  521. "/etc/zabbix/zabbix.conf.php")))
  522. (define zabbix-front-end-service-type
  523. (service-type
  524. (name 'zabbix-front-end)
  525. (extensions
  526. (list (service-extension activation-service-type
  527. zabbix-front-end-activation)
  528. (service-extension nginx-service-type
  529. zabbix-front-end-configuration-nginx)
  530. ;; Make sure php-fpm is instantiated.
  531. (service-extension php-fpm-service-type
  532. (const #t))))
  533. (default-value (zabbix-front-end-configuration))
  534. (description
  535. "Run the zabbix-front-end web interface, which allows users to interact
  536. with Zabbix server.")))
  537. (define (generate-zabbix-front-end-documentation)
  538. (generate-documentation
  539. `((zabbix-front-end-configuration
  540. ,zabbix-front-end-configuration-fields))
  541. 'zabbix-front-end-configuration))