services: dbus: Include each service's "share/dbus-1/system.d".
[jackhill/guix/guix.git] / gnu / services / dbus.scm
CommitLineData
0adfe95a 1;;; GNU Guix --- Functional package management for GNU
d429878d 2;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2019 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
89 (define (services->sxml services)
90 ;; Return the SXML 'includedir' clauses for DIRS.
91 `(busconfig
cde04021
LC
92 (servicehelper "/run/setuid-programs/dbus-daemon-launch-helper")
93
94 ;; First, the '.service' files of services subject to activation.
95 ;; We use a fixed location under /etc because the setuid helper
96 ;; looks for them in that location and nowhere else. See
97 ;; <https://bugs.freedesktop.org/show_bug.cgi?id=92458>.
98 (servicedir "/etc/dbus-1/system-services")
99
0adfe95a
LC
100 ,@(append-map (lambda (dir)
101 `((includedir
102 ,(string-append dir "/etc/dbus-1/system.d"))
33f9778b
LC
103 (includedir
104 ,(string-append dir "/share/dbus-1/system.d"))
cde04021
LC
105 (servicedir ;for '.service' files
106 ,(string-append dir "/share/dbus-1/services"))))
0adfe95a
LC
107 services)))
108
109 (mkdir #$output)
cde04021
LC
110
111 ;; Provide /etc/dbus-1/system-services, which is where the setuid
112 ;; helper looks for system service files.
113 (symlink #$(system-service-directory services)
114 (string-append #$output "/system-services"))
115
0adfe95a
LC
116 ;; 'system-local.conf' is automatically included by the default
117 ;; 'system.conf', so this is where we stuff our own things.
118 (call-with-output-file (string-append #$output "/system-local.conf")
119 (lambda (port)
120 (sxml->xml (services->sxml (list #$@services))
121 port)))))
122
123 (computed-file "dbus-configuration" build))
124
64643b90
SB
125(define (dbus-etc-files config)
126 "Return a list of FILES for @var{etc-service-type} to build the
127@code{/etc/dbus-1} directory."
128 (list `("dbus-1" ,(dbus-configuration-directory
129 (dbus-configuration-services config)))))
130
0adfe95a
LC
131(define %dbus-accounts
132 ;; Accounts used by the system bus.
133 (list (user-group (name "messagebus") (system? #t))
134 (user-account
135 (name "messagebus")
136 (group "messagebus")
137 (system? #t)
138 (comment "D-Bus system bus user")
139 (home-directory "/var/run/dbus")
9e41130b 140 (shell (file-append shadow "/sbin/nologin")))))
0adfe95a 141
cde04021
LC
142(define dbus-setuid-programs
143 ;; Return the file name of the setuid program that we need.
144 (match-lambda
145 (($ <dbus-configuration> dbus services)
9e41130b 146 (list (file-append dbus "/libexec/dbus-daemon-launch-helper")))))
cde04021 147
0adfe95a
LC
148(define (dbus-activation config)
149 "Return an activation gexp for D-Bus using @var{config}."
150 #~(begin
151 (use-modules (guix build utils))
152
153 (mkdir-p "/var/run/dbus")
154
155 (let ((user (getpwnam "messagebus")))
156 (chown "/var/run/dbus"
d429878d
LC
157 (passwd:uid user) (passwd:gid user))
158
159 ;; This directory contains the daemon's socket so it must be
160 ;; world-readable.
161 (chmod "/var/run/dbus" #o755))
0adfe95a
LC
162
163 (unless (file-exists? "/etc/machine-id")
164 (format #t "creating /etc/machine-id...~%")
165 (let ((prog (string-append #$(dbus-configuration-dbus config)
166 "/bin/dbus-uuidgen")))
167 ;; XXX: We can't use 'system' because the initrd's
168 ;; guile system(3) only works when 'sh' is in $PATH.
169 (let ((pid (primitive-fork)))
170 (if (zero? pid)
171 (call-with-output-file "/etc/machine-id"
172 (lambda (port)
173 (close-fdes 1)
174 (dup2 (port->fdes port) 1)
175 (execl prog)))
176 (waitpid pid)))))))
177
d4053c71 178(define dbus-shepherd-service
4a663ca4
LC
179 (match-lambda
180 (($ <dbus-configuration> dbus)
d4053c71 181 (list (shepherd-service
4a663ca4
LC
182 (documentation "Run the D-Bus system daemon.")
183 (provision '(dbus-system))
184 (requirement '(user-processes))
185 (start #~(make-forkexec-constructor
186 (list (string-append #$dbus "/bin/dbus-daemon")
b9bb50c6
LC
187 "--nofork" "--system")
188 #:pid-file "/var/run/dbus/pid"))
4a663ca4 189 (stop #~(make-kill-destructor)))))))
0adfe95a
LC
190
191(define dbus-root-service-type
192 (service-type (name 'dbus)
193 (extensions
d4053c71
AK
194 (list (service-extension shepherd-root-service-type
195 dbus-shepherd-service)
0adfe95a
LC
196 (service-extension activation-service-type
197 dbus-activation)
64643b90
SB
198 (service-extension etc-service-type
199 dbus-etc-files)
0adfe95a 200 (service-extension account-service-type
cde04021
LC
201 (const %dbus-accounts))
202 (service-extension setuid-program-service-type
203 dbus-setuid-programs)))
0adfe95a
LC
204
205 ;; Extensions consist of lists of packages (representing D-Bus
206 ;; services) that we just concatenate.
0adfe95a
LC
207 (compose concatenate)
208
209 ;; The service's parameters field is extended by augmenting
210 ;; its <dbus-configuration> 'services' field.
211 (extend (lambda (config services)
212 (dbus-configuration
213 (inherit config)
214 (services
215 (append (dbus-configuration-services config)
3e8d037b
LC
216 services)))))
217
218 (default-value (dbus-configuration))))
0adfe95a 219
f5a91039 220(define* (dbus-service #:key (dbus dbus) (services '()))
0adfe95a
LC
221 "Return a service that runs the \"system bus\", using @var{dbus}, with
222support for @var{services}.
223
224@uref{http://dbus.freedesktop.org/, D-Bus} is an inter-process communication
225facility. Its system bus is used to allow system services to communicate and
226be notified of system-wide events.
227
228@var{services} must be a list of packages that provide an
229@file{etc/dbus-1/system.d} directory containing additional D-Bus configuration
230and policy files. For example, to allow avahi-daemon to use the system bus,
231@var{services} must be equal to @code{(list avahi)}."
232 (service dbus-root-service-type
233 (dbus-configuration (dbus dbus)
234 (services services))))
235
aa071ca0 236(define (wrapped-dbus-service service program variables)
b68f6500 237 "Return a wrapper for @var{service}, a package containing a D-Bus service,
aa071ca0
LC
238where @var{program} is wrapped such that @var{variables}, a list of name/value
239tuples, are all set as environment variables when the bus daemon launches it."
b68f6500
LC
240 (define wrapper
241 (program-file (string-append (package-name service) "-program-wrapper")
242 #~(begin
aa071ca0
LC
243 (use-modules (ice-9 match))
244
245 (for-each (match-lambda
246 ((variable value)
247 (setenv variable value)))
248 '#$variables)
249
b68f6500
LC
250 (apply execl (string-append #$service "/" #$program)
251 (string-append #$service "/" #$program)
252 (cdr (command-line))))))
253
254 (define build
255 (with-imported-modules '((guix build utils))
256 #~(begin
257 (use-modules (guix build utils))
258
259 (define service-directory
260 "/share/dbus-1/system-services")
261
262 (mkdir-p (dirname (string-append #$output
263 service-directory)))
264 (copy-recursively (string-append #$service
265 service-directory)
266 (string-append #$output
267 service-directory))
268 (symlink (string-append #$service "/etc") ;for etc/dbus-1
269 (string-append #$output "/etc"))
270
271 (for-each (lambda (file)
272 (substitute* file
273 (("Exec[[:blank:]]*=[[:blank:]]*([[:graph:]]+)(.*)$"
274 _ original-program arguments)
275 (string-append "Exec=" #$wrapper arguments
276 "\n"))))
277 (find-files #$output "\\.service$")))))
278
279 (computed-file (string-append (package-name service) "-wrapper")
280 build))
281
2e328698
LC
282\f
283;;;
284;;; Polkit privilege management service.
285;;;
286
287(define-record-type* <polkit-configuration>
288 polkit-configuration make-polkit-configuration
289 polkit-configuration?
290 (polkit polkit-configuration-polkit ;<package>
291 (default polkit))
292 (actions polkit-configuration-actions ;list of <package>
293 (default '())))
294
295(define %polkit-accounts
296 (list (user-group (name "polkitd") (system? #t))
297 (user-account
298 (name "polkitd")
299 (group "polkitd")
300 (system? #t)
301 (comment "Polkit daemon user")
302 (home-directory "/var/empty")
303 (shell "/run/current-system/profile/sbin/nologin"))))
304
305(define %polkit-pam-services
306 (list (unix-pam-service "polkit-1")))
307
308(define (polkit-directory packages)
309 "Return a directory containing an @file{actions} and possibly a
310@file{rules.d} sub-directory, for use as @file{/etc/polkit-1}."
311 (with-imported-modules '((guix build union))
312 (computed-file "etc-polkit-1"
313 #~(begin
314 (use-modules (guix build union) (srfi srfi-26))
315
316 (union-build #$output
317 (map (cut string-append <>
318 "/share/polkit-1")
319 (list #$@packages)))))))
320
321(define polkit-etc-files
322 (match-lambda
323 (($ <polkit-configuration> polkit packages)
324 `(("polkit-1" ,(polkit-directory (cons polkit packages)))))))
325
326(define polkit-setuid-programs
327 (match-lambda
328 (($ <polkit-configuration> polkit)
329 (list (file-append polkit "/lib/polkit-1/polkit-agent-helper-1")
330 (file-append polkit "/bin/pkexec")))))
331
332(define polkit-service-type
333 (service-type (name 'polkit)
334 (extensions
335 (list (service-extension account-service-type
336 (const %polkit-accounts))
337 (service-extension pam-root-service-type
338 (const %polkit-pam-services))
339 (service-extension dbus-root-service-type
340 (compose
341 list
342 polkit-configuration-polkit))
343 (service-extension etc-service-type
344 polkit-etc-files)
345 (service-extension setuid-program-service-type
346 polkit-setuid-programs)))
347
348 ;; Extensions are lists of packages that provide polkit rules
349 ;; or actions under share/polkit-1/{actions,rules.d}.
350 (compose concatenate)
351 (extend (lambda (config actions)
352 (polkit-configuration
353 (inherit config)
354 (actions
355 (append (polkit-configuration-actions config)
3e8d037b
LC
356 actions)))))
357
358 (default-value (polkit-configuration))))
2e328698
LC
359
360(define* (polkit-service #:key (polkit polkit))
361 "Return a service that runs the
362@uref{http://www.freedesktop.org/wiki/Software/polkit/, Polkit privilege
363management service}, which allows system administrators to grant access to
364privileged operations in a structured way. By querying the Polkit service, a
365privileged system component can know when it should grant additional
366capabilities to ordinary users. For example, an ordinary user can be granted
367the capability to suspend the system if the user is logged in locally."
368 (service polkit-service-type
369 (polkit-configuration (polkit polkit))))
370
0adfe95a 371;;; dbus.scm ends here