admin.scm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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. (extensions (list (service-extension etc-service-type rottlog-etc)
  167. (service-extension mcron-service-type
  168. rottlog-jobs-or-default)
  169. ;; Add Rottlog to the global profile so users can access
  170. ;; the documentation.
  171. (service-extension profile-service-type
  172. (compose list rottlog-rottlog))))
  173. (compose concatenate)
  174. (extend (lambda (config rotations)
  175. (rottlog-configuration
  176. (inherit config)
  177. (rotations (append (rottlog-rotations config)
  178. rotations)))))
  179. (default-value (rottlog-configuration))))
  180. ;;;
  181. ;;; Tailon
  182. ;;;
  183. (define-record-type* <tailon-configuration-file>
  184. tailon-configuration-file make-tailon-configuration-file
  185. tailon-configuration-file?
  186. (files tailon-configuration-file-files
  187. (default '("/var/log")))
  188. (bind tailon-configuration-file-bind
  189. (default "localhost:8080"))
  190. (relative-root tailon-configuration-file-relative-root
  191. (default #f))
  192. (allow-transfers? tailon-configuration-file-allow-transfers?
  193. (default #t))
  194. (follow-names? tailon-configuration-file-follow-names?
  195. (default #t))
  196. (tail-lines tailon-configuration-file-tail-lines
  197. (default 200))
  198. (allowed-commands tailon-configuration-file-allowed-commands
  199. (default '("tail" "grep" "awk")))
  200. (debug? tailon-configuration-file-debug?
  201. (default #f))
  202. (wrap-lines tailon-configuration-file-wrap-lines
  203. (default #t))
  204. (http-auth tailon-configuration-file-http-auth
  205. (default #f))
  206. (users tailon-configuration-file-users
  207. (default #f)))
  208. (define (tailon-configuration-files-string files)
  209. (string-append
  210. "\n"
  211. (string-join
  212. (map
  213. (lambda (x)
  214. (string-append
  215. " - "
  216. (cond
  217. ((string? x)
  218. (simple-format #f "'~A'" x))
  219. ((list? x)
  220. (string-join
  221. (cons (simple-format #f "'~A':" (car x))
  222. (map
  223. (lambda (x) (simple-format #f " - '~A'" x))
  224. (cdr x)))
  225. "\n"))
  226. (else (error x)))))
  227. files)
  228. "\n")))
  229. (define-gexp-compiler (tailon-configuration-file-compiler
  230. (file <tailon-configuration-file>) system target)
  231. (match file
  232. (($ <tailon-configuration-file> files bind relative-root
  233. allow-transfers? follow-names?
  234. tail-lines allowed-commands debug?
  235. wrap-lines http-auth users)
  236. (text-file
  237. "tailon-config.yaml"
  238. (string-concatenate
  239. (filter-map
  240. (match-lambda
  241. ((key . #f) #f)
  242. ((key . value) (string-append key ": " value "\n")))
  243. `(("files" . ,(tailon-configuration-files-string files))
  244. ("bind" . ,bind)
  245. ("relative-root" . ,relative-root)
  246. ("allow-transfers" . ,(if allow-transfers? "true" "false"))
  247. ("follow-names" . ,(if follow-names? "true" "false"))
  248. ("tail-lines" . ,(number->string tail-lines))
  249. ("commands" . ,(string-append "["
  250. (string-join allowed-commands ", ")
  251. "]"))
  252. ("debug" . ,(if debug? "true" #f))
  253. ("wrap-lines" . ,(if wrap-lines "true" "false"))
  254. ("http-auth" . ,http-auth)
  255. ("users" . ,(if users
  256. (string-concatenate
  257. (cons "\n"
  258. (map (match-lambda
  259. ((user . pass)
  260. (string-append
  261. " " user ":" pass)))
  262. users)))
  263. #f)))))))))
  264. (define-record-type* <tailon-configuration>
  265. tailon-configuration make-tailon-configuration
  266. tailon-configuration?
  267. (config-file tailon-configuration-config-file
  268. (default (tailon-configuration-file)))
  269. (package tailon-configuration-package
  270. (default tailon)))
  271. (define tailon-shepherd-service
  272. (match-lambda
  273. (($ <tailon-configuration> config-file package)
  274. (list (shepherd-service
  275. (provision '(tailon))
  276. (documentation "Run the tailon daemon.")
  277. (start #~(make-forkexec-constructor
  278. `(,(string-append #$package "/bin/tailon")
  279. "-c" ,#$config-file)
  280. #:user "tailon"
  281. #:group "tailon"))
  282. (stop #~(make-kill-destructor)))))))
  283. (define %tailon-accounts
  284. (list (user-group (name "tailon") (system? #t))
  285. (user-account
  286. (name "tailon")
  287. (group "tailon")
  288. (system? #t)
  289. (comment "tailon")
  290. (home-directory "/var/empty")
  291. (shell (file-append shadow "/sbin/nologin")))))
  292. (define tailon-service-type
  293. (service-type
  294. (name 'tailon)
  295. (extensions
  296. (list (service-extension shepherd-root-service-type
  297. tailon-shepherd-service)
  298. (service-extension account-service-type
  299. (const %tailon-accounts))))
  300. (compose concatenate)
  301. (extend (lambda (parameter files)
  302. (tailon-configuration
  303. (inherit parameter)
  304. (config-file
  305. (let ((old-config-file
  306. (tailon-configuration-config-file parameter)))
  307. (tailon-configuration-file
  308. (inherit old-config-file)
  309. (files (append (tailon-configuration-file-files old-config-file)
  310. files))))))))
  311. (default-value (tailon-configuration))))
  312. ;;; admin.scm ends here