admin.scm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
  3. ;;; Copyright © 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  7. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  8. ;;; under the terms of the GNU General Public License as published by
  9. ;;; the Free Software Foundation; either version 3 of the License, or (at
  10. ;;; your option) any later version.
  11. ;;;
  12. ;;; GNU Guix is distributed in the hope that it will be useful, but
  13. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;;; GNU General Public License for more details.
  16. ;;;
  17. ;;; You should have received a copy of thye GNU General Public License
  18. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  19. (define-module (gnu services admin)
  20. #:use-module (gnu packages admin)
  21. #:use-module (gnu packages base)
  22. #:use-module (gnu packages logging)
  23. #:use-module (gnu services)
  24. #:use-module (gnu services mcron)
  25. #:use-module (gnu services shepherd)
  26. #:use-module (gnu services web)
  27. #:use-module (gnu system shadow)
  28. #:use-module (guix gexp)
  29. #:use-module (guix store)
  30. #:use-module (guix packages)
  31. #:use-module (guix records)
  32. #:use-module (srfi srfi-1)
  33. #:use-module (ice-9 vlist)
  34. #:use-module (ice-9 match)
  35. #:export (%default-rotations
  36. %rotated-files
  37. log-rotation
  38. log-rotation?
  39. log-rotation-frequency
  40. log-rotation-files
  41. log-rotation-options
  42. log-rotation-post-rotate
  43. rottlog-configuration
  44. rottlog-configuration?
  45. rottlog-service
  46. rottlog-service-type
  47. <tailon-configuration-file>
  48. tailon-configuration-file
  49. tailon-configuration-file?
  50. tailon-configuration-file-files
  51. tailon-configuration-file-bind
  52. tailon-configuration-file-relative-root
  53. tailon-configuration-file-allow-transfers?
  54. tailon-configuration-file-follow-names?
  55. tailon-configuration-file-tail-lines
  56. tailon-configuration-file-allowed-commands
  57. tailon-configuration-file-debug?
  58. tailon-configuration-file-http-auth
  59. tailon-configuration-file-users
  60. <tailon-configuration>
  61. tailon-configuration
  62. tailon-configuration?
  63. tailon-configuration-config-file
  64. tailon-configuration-package
  65. tailon-service-type))
  66. ;;; Commentary:
  67. ;;;
  68. ;;; This module implements configuration of rottlog by writing
  69. ;;; /etc/rottlog/{rc,hourly|daily|weekly}. Example usage
  70. ;;;
  71. ;;; (mcron-service)
  72. ;;; (service rottlog-service-type)
  73. ;;;
  74. ;;; Code:
  75. (define-record-type* <log-rotation> log-rotation make-log-rotation
  76. log-rotation?
  77. (files log-rotation-files) ;list of strings
  78. (frequency log-rotation-frequency ;symbol
  79. (default 'weekly))
  80. (post-rotate log-rotation-post-rotate ;#f | gexp
  81. (default #f))
  82. (options log-rotation-options ;list of strings
  83. (default '())))
  84. (define %rotated-files
  85. ;; Syslog files subject to rotation.
  86. '("/var/log/messages" "/var/log/secure" "/var/log/maillog"))
  87. (define %default-rotations
  88. (list (log-rotation ;syslog files
  89. (files %rotated-files)
  90. ;; Restart syslogd after rotation.
  91. (options '("sharedscripts"))
  92. (post-rotate #~(let ((pid (call-with-input-file "/var/run/syslog.pid"
  93. read)))
  94. (kill pid SIGHUP))))
  95. (log-rotation
  96. (files '("/var/log/shepherd.log" "/var/log/guix-daemon.log")))))
  97. (define (log-rotation->config rotation)
  98. "Return a string-valued gexp representing the rottlog configuration snippet
  99. for ROTATION."
  100. (define post-rotate
  101. (let ((post (log-rotation-post-rotate rotation)))
  102. (and post
  103. (program-file "rottlog-post-rotate.scm" post))))
  104. #~(let ((post #$post-rotate))
  105. (string-append (string-join '#$(log-rotation-files rotation) ",")
  106. " {"
  107. #$(string-join (log-rotation-options rotation)
  108. "\n " 'prefix)
  109. (if post
  110. (string-append "\n postrotate\n " post
  111. "\n endscript\n")
  112. "")
  113. "\n}\n")))
  114. (define (log-rotations->/etc-entries rotations)
  115. "Return the list of /etc entries for ROTATIONS, a list of <log-rotation>."
  116. (define (frequency-file frequency rotations)
  117. (computed-file (string-append "rottlog." (symbol->string frequency))
  118. #~(call-with-output-file #$output
  119. (lambda (port)
  120. (for-each (lambda (str)
  121. (display str port))
  122. (list #$@(map log-rotation->config
  123. rotations)))))))
  124. (let* ((frequencies (delete-duplicates
  125. (map log-rotation-frequency rotations)))
  126. (table (fold (lambda (rotation table)
  127. (vhash-consq (log-rotation-frequency rotation)
  128. rotation table))
  129. vlist-null
  130. rotations)))
  131. (map (lambda (frequency)
  132. `(,(symbol->string frequency)
  133. ,(frequency-file frequency
  134. (vhash-foldq* cons '() frequency table))))
  135. frequencies)))
  136. (define (default-jobs rottlog)
  137. (list #~(job '(next-hour '(0)) ;midnight
  138. (lambda ()
  139. (system* #$(file-append rottlog "/sbin/rottlog"))))
  140. #~(job '(next-hour '(12)) ;noon
  141. (lambda ()
  142. (system* #$(file-append rottlog "/sbin/rottlog"))))))
  143. (define-record-type* <rottlog-configuration>
  144. rottlog-configuration make-rottlog-configuration
  145. rottlog-configuration?
  146. (rottlog rottlog-rottlog ;package
  147. (default rottlog))
  148. (rc-file rottlog-rc-file ;file-like
  149. (default (file-append rottlog "/etc/rc")))
  150. (rotations rottlog-rotations ;list of <log-rotation>
  151. (default %default-rotations))
  152. (jobs rottlog-jobs ;list of <mcron-job>
  153. (default #f)))
  154. (define (rottlog-etc config)
  155. `(("rottlog"
  156. ,(file-union "rottlog"
  157. (cons `("rc" ,(rottlog-rc-file config))
  158. (log-rotations->/etc-entries
  159. (rottlog-rotations config)))))))
  160. (define (rottlog-jobs-or-default config)
  161. (or (rottlog-jobs config)
  162. (default-jobs (rottlog-rottlog config))))
  163. (define rottlog-service-type
  164. (service-type
  165. (name 'rottlog)
  166. (description
  167. "Periodically rotate log files using GNU@tie{}Rottlog and GNU@tie{}mcron.
  168. Old log files are removed or compressed according to the configuration.")
  169. (extensions (list (service-extension etc-service-type rottlog-etc)
  170. (service-extension mcron-service-type
  171. rottlog-jobs-or-default)
  172. ;; Add Rottlog to the global profile so users can access
  173. ;; the documentation.
  174. (service-extension profile-service-type
  175. (compose list rottlog-rottlog))))
  176. (compose concatenate)
  177. (extend (lambda (config rotations)
  178. (rottlog-configuration
  179. (inherit config)
  180. (rotations (append (rottlog-rotations config)
  181. rotations)))))
  182. (default-value (rottlog-configuration))))
  183. ;;;
  184. ;;; Tailon
  185. ;;;
  186. (define-record-type* <tailon-configuration-file>
  187. tailon-configuration-file make-tailon-configuration-file
  188. tailon-configuration-file?
  189. (files tailon-configuration-file-files
  190. (default '("/var/log")))
  191. (bind tailon-configuration-file-bind
  192. (default "localhost:8080"))
  193. (relative-root tailon-configuration-file-relative-root
  194. (default #f))
  195. (allow-transfers? tailon-configuration-file-allow-transfers?
  196. (default #t))
  197. (follow-names? tailon-configuration-file-follow-names?
  198. (default #t))
  199. (tail-lines tailon-configuration-file-tail-lines
  200. (default 200))
  201. (allowed-commands tailon-configuration-file-allowed-commands
  202. (default '("tail" "grep" "awk")))
  203. (debug? tailon-configuration-file-debug?
  204. (default #f))
  205. (wrap-lines tailon-configuration-file-wrap-lines
  206. (default #t))
  207. (http-auth tailon-configuration-file-http-auth
  208. (default #f))
  209. (users tailon-configuration-file-users
  210. (default #f)))
  211. (define (tailon-configuration-files-string files)
  212. (string-append
  213. "\n"
  214. (string-join
  215. (map
  216. (lambda (x)
  217. (string-append
  218. " - "
  219. (cond
  220. ((string? x)
  221. (simple-format #f "'~A'" x))
  222. ((list? x)
  223. (string-join
  224. (cons (simple-format #f "'~A':" (car x))
  225. (map
  226. (lambda (x) (simple-format #f " - '~A'" x))
  227. (cdr x)))
  228. "\n"))
  229. (else (error x)))))
  230. files)
  231. "\n")))
  232. (define-gexp-compiler (tailon-configuration-file-compiler
  233. (file <tailon-configuration-file>) system target)
  234. (match file
  235. (($ <tailon-configuration-file> files bind relative-root
  236. allow-transfers? follow-names?
  237. tail-lines allowed-commands debug?
  238. wrap-lines http-auth users)
  239. (text-file
  240. "tailon-config.yaml"
  241. (string-concatenate
  242. (filter-map
  243. (match-lambda
  244. ((key . #f) #f)
  245. ((key . value) (string-append key ": " value "\n")))
  246. `(("files" . ,(tailon-configuration-files-string files))
  247. ("bind" . ,bind)
  248. ("relative-root" . ,relative-root)
  249. ("allow-transfers" . ,(if allow-transfers? "true" "false"))
  250. ("follow-names" . ,(if follow-names? "true" "false"))
  251. ("tail-lines" . ,(number->string tail-lines))
  252. ("commands" . ,(string-append "["
  253. (string-join allowed-commands ", ")
  254. "]"))
  255. ("debug" . ,(if debug? "true" #f))
  256. ("wrap-lines" . ,(if wrap-lines "true" "false"))
  257. ("http-auth" . ,http-auth)
  258. ("users" . ,(if users
  259. (string-concatenate
  260. (cons "\n"
  261. (map (match-lambda
  262. ((user . pass)
  263. (string-append
  264. " " user ":" pass)))
  265. users)))
  266. #f)))))))))
  267. (define-record-type* <tailon-configuration>
  268. tailon-configuration make-tailon-configuration
  269. tailon-configuration?
  270. (config-file tailon-configuration-config-file
  271. (default (tailon-configuration-file)))
  272. (package tailon-configuration-package
  273. (default tailon)))
  274. (define tailon-shepherd-service
  275. (match-lambda
  276. (($ <tailon-configuration> config-file package)
  277. (list (shepherd-service
  278. (provision '(tailon))
  279. (documentation "Run the tailon daemon.")
  280. (start #~(make-forkexec-constructor
  281. `(,(string-append #$package "/bin/tailon")
  282. "-c" ,#$config-file)
  283. #:user "tailon"
  284. #:group "tailon"))
  285. (stop #~(make-kill-destructor)))))))
  286. (define %tailon-accounts
  287. (list (user-group (name "tailon") (system? #t))
  288. (user-account
  289. (name "tailon")
  290. (group "tailon")
  291. (system? #t)
  292. (comment "tailon")
  293. (home-directory "/var/empty")
  294. (shell (file-append shadow "/sbin/nologin")))))
  295. (define tailon-service-type
  296. (service-type
  297. (name 'tailon)
  298. (description
  299. "Run Tailon, a Web application for monitoring, viewing, and searching log
  300. files.")
  301. (extensions
  302. (list (service-extension shepherd-root-service-type
  303. tailon-shepherd-service)
  304. (service-extension account-service-type
  305. (const %tailon-accounts))))
  306. (compose concatenate)
  307. (extend (lambda (parameter files)
  308. (tailon-configuration
  309. (inherit parameter)
  310. (config-file
  311. (let ((old-config-file
  312. (tailon-configuration-config-file parameter)))
  313. (tailon-configuration-file
  314. (inherit old-config-file)
  315. (files (append (tailon-configuration-file-files old-config-file)
  316. files))))))))
  317. (default-value (tailon-configuration))))
  318. ;;; admin.scm ends here