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