services: science.scm: Add missing copyright headers.
[jackhill/guix/guix.git] / gnu / services / dbus.scm
CommitLineData
0adfe95a 1;;; GNU Guix --- Functional package management for GNU
dd0804c6 2;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
64643b90 3;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
0adfe95a
LC
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 the GNU General Public License
18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20(define-module (gnu services dbus)
21 #:use-module (gnu services)
0190c1c0 22 #:use-module (gnu services shepherd)
0adfe95a 23 #:use-module (gnu system shadow)
2e328698 24 #:use-module (gnu system pam)
f5a91039 25 #:use-module ((gnu packages glib) #:select (dbus))
2e328698 26 #:use-module (gnu packages polkit)
0adfe95a
LC
27 #:use-module (gnu packages admin)
28 #:use-module (guix gexp)
b68f6500 29 #:use-module ((guix packages) #:select (package-name))
0adfe95a
LC
30 #:use-module (guix records)
31 #:use-module (srfi srfi-1)
32 #:use-module (ice-9 match)
24e96431
33 #:export (dbus-configuration
34 dbus-configuration?
35 dbus-root-service-type
2e328698 36 dbus-service
b68f6500 37 wrapped-dbus-service
2e328698
LC
38
39 polkit-service-type
40 polkit-service))
0adfe95a
LC
41
42;;;
43;;; D-Bus.
44;;;
45
46(define-record-type* <dbus-configuration>
47 dbus-configuration make-dbus-configuration
48 dbus-configuration?
49 (dbus dbus-configuration-dbus ;<package>
f5a91039 50 (default dbus))
0adfe95a
LC
51 (services dbus-configuration-services ;list of <package>
52 (default '())))
53
cde04021
LC
54(define (system-service-directory services)
55 "Return the system service directory, containing @code{.service} files for
56all the services that may be activated by the daemon."
57 (computed-file "dbus-system-services"
4ee96a79
LC
58 (with-imported-modules '((guix build utils))
59 #~(begin
60 (use-modules (guix build utils)
61 (srfi srfi-1))
cde04021 62
4ee96a79
LC
63 (define files
64 (append-map (lambda (service)
65 (find-files
66 (string-append
67 service
6a2b9065 68 "/share/dbus-1/")
4ee96a79
LC
69 "\\.service$"))
70 (list #$@services)))
cde04021 71
4ee96a79
LC
72 (mkdir #$output)
73 (for-each (lambda (file)
74 (symlink file
75 (string-append #$output "/"
76 (basename file))))
77 files)
78 #t))))
cde04021 79
64643b90
SB
80(define (dbus-configuration-directory services)
81 "Return a directory contains the @code{system-local.conf} file for DBUS that
82includes the @code{etc/dbus-1/system.d} directories of each package listed in
0adfe95a
LC
83@var{services}."
84 (define build
85 #~(begin
86 (use-modules (sxml simple)
87 (srfi srfi-1))
88
27727b18
LC
89 (define-syntax directives
90 (syntax-rules ()
91 ;; Expand the given directives (SXML expressions) only if their
92 ;; key names a file that exists.
93 ((_ (name directory) rest ...)
94 (let ((dir directory))
95 (if (file-exists? dir)
96 `((name ,dir)
97 ,@(directives rest ...))
98 (directives rest ...))))
99 ((_)
100 '())))
101
0adfe95a
LC
102 (define (services->sxml services)
103 ;; Return the SXML 'includedir' clauses for DIRS.
104 `(busconfig
cde04021
LC
105 (servicehelper "/run/setuid-programs/dbus-daemon-launch-helper")
106
107 ;; First, the '.service' files of services subject to activation.
108 ;; We use a fixed location under /etc because the setuid helper
109 ;; looks for them in that location and nowhere else. See
110 ;; <https://bugs.freedesktop.org/show_bug.cgi?id=92458>.
111 (servicedir "/etc/dbus-1/system-services")
112
0adfe95a 113 ,@(append-map (lambda (dir)
27727b18
LC
114 (directives
115 (includedir
116 (string-append dir "/etc/dbus-1/system.d"))
117 (includedir
118 (string-append dir "/share/dbus-1/system.d"))
119 (servicedir ;for '.service' files
120 (string-append dir "/share/dbus-1/services"))))
0adfe95a
LC
121 services)))
122
123 (mkdir #$output)
cde04021
LC
124
125 ;; Provide /etc/dbus-1/system-services, which is where the setuid
126 ;; helper looks for system service files.
127 (symlink #$(system-service-directory services)
128 (string-append #$output "/system-services"))
129
0adfe95a
LC
130 ;; 'system-local.conf' is automatically included by the default
131 ;; 'system.conf', so this is where we stuff our own things.
132 (call-with-output-file (string-append #$output "/system-local.conf")
133 (lambda (port)
134 (sxml->xml (services->sxml (list #$@services))
135 port)))))
136
137 (computed-file "dbus-configuration" build))
138
64643b90
SB
139(define (dbus-etc-files config)
140 "Return a list of FILES for @var{etc-service-type} to build the
141@code{/etc/dbus-1} directory."
142 (list `("dbus-1" ,(dbus-configuration-directory
143 (dbus-configuration-services config)))))
144
0adfe95a
LC
145(define %dbus-accounts
146 ;; Accounts used by the system bus.
147 (list (user-group (name "messagebus") (system? #t))
148 (user-account
149 (name "messagebus")
150 (group "messagebus")
151 (system? #t)
152 (comment "D-Bus system bus user")
153 (home-directory "/var/run/dbus")
9e41130b 154 (shell (file-append shadow "/sbin/nologin")))))
0adfe95a 155
cde04021
LC
156(define dbus-setuid-programs
157 ;; Return the file name of the setuid program that we need.
158 (match-lambda
159 (($ <dbus-configuration> dbus services)
9e41130b 160 (list (file-append dbus "/libexec/dbus-daemon-launch-helper")))))
cde04021 161
0adfe95a
LC
162(define (dbus-activation config)
163 "Return an activation gexp for D-Bus using @var{config}."
164 #~(begin
165 (use-modules (guix build utils))
166
167 (mkdir-p "/var/run/dbus")
168
169 (let ((user (getpwnam "messagebus")))
170 (chown "/var/run/dbus"
d429878d
LC
171 (passwd:uid user) (passwd:gid user))
172
173 ;; This directory contains the daemon's socket so it must be
174 ;; world-readable.
175 (chmod "/var/run/dbus" #o755))
0adfe95a
LC
176
177 (unless (file-exists? "/etc/machine-id")
178 (format #t "creating /etc/machine-id...~%")
1f8ca28b
LC
179 (invoke (string-append #$(dbus-configuration-dbus config)
180 "/bin/dbus-uuidgen")
181 "--ensure=/etc/machine-id"))))
0adfe95a 182
d4053c71 183(define dbus-shepherd-service
4a663ca4
LC
184 (match-lambda
185 (($ <dbus-configuration> dbus)
d4053c71 186 (list (shepherd-service
4a663ca4
LC
187 (documentation "Run the D-Bus system daemon.")
188 (provision '(dbus-system))
7462a1de 189 (requirement '(user-processes syslogd))
4a663ca4
LC
190 (start #~(make-forkexec-constructor
191 (list (string-append #$dbus "/bin/dbus-daemon")
7462a1de 192 "--nofork" "--system" "--syslog-only")
b9bb50c6 193 #:pid-file "/var/run/dbus/pid"))
4a663ca4 194 (stop #~(make-kill-destructor)))))))
0adfe95a
LC
195
196(define dbus-root-service-type
197 (service-type (name 'dbus)
198 (extensions
d4053c71
AK
199 (list (service-extension shepherd-root-service-type
200 dbus-shepherd-service)
0adfe95a
LC
201 (service-extension activation-service-type
202 dbus-activation)
64643b90
SB
203 (service-extension etc-service-type
204 dbus-etc-files)
0adfe95a 205 (service-extension account-service-type
cde04021
LC
206 (const %dbus-accounts))
207 (service-extension setuid-program-service-type
208 dbus-setuid-programs)))
0adfe95a
LC
209
210 ;; Extensions consist of lists of packages (representing D-Bus
211 ;; services) that we just concatenate.
0adfe95a
LC
212 (compose concatenate)
213
214 ;; The service's parameters field is extended by augmenting
215 ;; its <dbus-configuration> 'services' field.
216 (extend (lambda (config services)
217 (dbus-configuration
218 (inherit config)
219 (services
220 (append (dbus-configuration-services config)
3e8d037b
LC
221 services)))))
222
a01d2e30
LC
223 (default-value (dbus-configuration))
224 (description "Run the system-wide D-Bus inter-process message
225bus. It allows programs and daemons to communicate and is also responsible
226for spawning (@dfn{activating}) D-Bus services on demand.")))
0adfe95a 227
f5a91039 228(define* (dbus-service #:key (dbus dbus) (services '()))
0adfe95a
LC
229 "Return a service that runs the \"system bus\", using @var{dbus}, with
230support for @var{services}.
231
232@uref{http://dbus.freedesktop.org/, D-Bus} is an inter-process communication
233facility. Its system bus is used to allow system services to communicate and
234be notified of system-wide events.
235
236@var{services} must be a list of packages that provide an
237@file{etc/dbus-1/system.d} directory containing additional D-Bus configuration
238and policy files. For example, to allow avahi-daemon to use the system bus,
239@var{services} must be equal to @code{(list avahi)}."
240 (service dbus-root-service-type
241 (dbus-configuration (dbus dbus)
242 (services services))))
243
aa071ca0 244(define (wrapped-dbus-service service program variables)
b68f6500 245 "Return a wrapper for @var{service}, a package containing a D-Bus service,
aa071ca0
LC
246where @var{program} is wrapped such that @var{variables}, a list of name/value
247tuples, are all set as environment variables when the bus daemon launches it."
b68f6500
LC
248 (define wrapper
249 (program-file (string-append (package-name service) "-program-wrapper")
250 #~(begin
aa071ca0
LC
251 (use-modules (ice-9 match))
252
253 (for-each (match-lambda
254 ((variable value)
255 (setenv variable value)))
256 '#$variables)
257
b68f6500
LC
258 (apply execl (string-append #$service "/" #$program)
259 (string-append #$service "/" #$program)
260 (cdr (command-line))))))
261
262 (define build
263 (with-imported-modules '((guix build utils))
264 #~(begin
265 (use-modules (guix build utils))
266
267 (define service-directory
268 "/share/dbus-1/system-services")
269
270 (mkdir-p (dirname (string-append #$output
271 service-directory)))
272 (copy-recursively (string-append #$service
273 service-directory)
274 (string-append #$output
275 service-directory))
276 (symlink (string-append #$service "/etc") ;for etc/dbus-1
277 (string-append #$output "/etc"))
278
279 (for-each (lambda (file)
280 (substitute* file
281 (("Exec[[:blank:]]*=[[:blank:]]*([[:graph:]]+)(.*)$"
282 _ original-program arguments)
283 (string-append "Exec=" #$wrapper arguments
284 "\n"))))
285 (find-files #$output "\\.service$")))))
286
287 (computed-file (string-append (package-name service) "-wrapper")
288 build))
289
2e328698
LC
290\f
291;;;
292;;; Polkit privilege management service.
293;;;
294
295(define-record-type* <polkit-configuration>
296 polkit-configuration make-polkit-configuration
297 polkit-configuration?
298 (polkit polkit-configuration-polkit ;<package>
299 (default polkit))
300 (actions polkit-configuration-actions ;list of <package>
301 (default '())))
302
303(define %polkit-accounts
304 (list (user-group (name "polkitd") (system? #t))
305 (user-account
306 (name "polkitd")
307 (group "polkitd")
308 (system? #t)
309 (comment "Polkit daemon user")
310 (home-directory "/var/empty")
311 (shell "/run/current-system/profile/sbin/nologin"))))
312
313(define %polkit-pam-services
314 (list (unix-pam-service "polkit-1")))
315
316(define (polkit-directory packages)
317 "Return a directory containing an @file{actions} and possibly a
318@file{rules.d} sub-directory, for use as @file{/etc/polkit-1}."
319 (with-imported-modules '((guix build union))
320 (computed-file "etc-polkit-1"
321 #~(begin
322 (use-modules (guix build union) (srfi srfi-26))
323
324 (union-build #$output
325 (map (cut string-append <>
326 "/share/polkit-1")
327 (list #$@packages)))))))
328
329(define polkit-etc-files
330 (match-lambda
331 (($ <polkit-configuration> polkit packages)
332 `(("polkit-1" ,(polkit-directory (cons polkit packages)))))))
333
334(define polkit-setuid-programs
335 (match-lambda
336 (($ <polkit-configuration> polkit)
337 (list (file-append polkit "/lib/polkit-1/polkit-agent-helper-1")
338 (file-append polkit "/bin/pkexec")))))
339
340(define polkit-service-type
341 (service-type (name 'polkit)
342 (extensions
343 (list (service-extension account-service-type
344 (const %polkit-accounts))
345 (service-extension pam-root-service-type
346 (const %polkit-pam-services))
347 (service-extension dbus-root-service-type
348 (compose
349 list
350 polkit-configuration-polkit))
351 (service-extension etc-service-type
352 polkit-etc-files)
353 (service-extension setuid-program-service-type
354 polkit-setuid-programs)))
355
356 ;; Extensions are lists of packages that provide polkit rules
357 ;; or actions under share/polkit-1/{actions,rules.d}.
358 (compose concatenate)
359 (extend (lambda (config actions)
360 (polkit-configuration
361 (inherit config)
362 (actions
363 (append (polkit-configuration-actions config)
3e8d037b
LC
364 actions)))))
365
dd0804c6
LC
366 (default-value (polkit-configuration))
367 (description
368 "Run the
369@uref{http://www.freedesktop.org/wiki/Software/polkit/, Polkit privilege
370management service}, which allows system administrators to grant access to
371privileged operations in a structured way. Polkit is a requirement for most
372desktop environments, such as GNOME.")))
2e328698
LC
373
374(define* (polkit-service #:key (polkit polkit))
375 "Return a service that runs the
376@uref{http://www.freedesktop.org/wiki/Software/polkit/, Polkit privilege
377management service}, which allows system administrators to grant access to
378privileged operations in a structured way. By querying the Polkit service, a
379privileged system component can know when it should grant additional
380capabilities to ordinary users. For example, an ordinary user can be granted
381the capability to suspend the system if the user is logged in locally."
382 (service polkit-service-type
383 (polkit-configuration (polkit polkit))))
384
0adfe95a 385;;; dbus.scm ends here