aboutsummaryrefslogtreecommitdiff
path: root/gnu/services
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2015-12-12 11:42:12 +0100
committerLudovic Courtès <ludo@gnu.org>2015-12-12 11:48:46 +0100
commite82e55e58c67b0215e768c4612ca542bc670f633 (patch)
tree856c4512fa1fbde59c1d9845c5a763ef8c4a14b4 /gnu/services
parent98bd851ee891ca4a84e061fe1e78ba78c292b096 (diff)
parente35dff973375266db253747140ddf25084ecddc2 (diff)
downloadguix-e82e55e58c67b0215e768c4612ca542bc670f633.tar
guix-e82e55e58c67b0215e768c4612ca542bc670f633.tar.gz
Merge branch 'master' into core-updates
Diffstat (limited to 'gnu/services')
-rw-r--r--gnu/services/avahi.scm35
-rw-r--r--gnu/services/base.scm222
-rw-r--r--gnu/services/dbus.scm105
-rw-r--r--gnu/services/desktop.scm258
-rw-r--r--gnu/services/dmd.scm143
-rw-r--r--gnu/services/networking.scm221
-rw-r--r--gnu/services/ssh.scm7
-rw-r--r--gnu/services/xorg.scm66
8 files changed, 821 insertions, 236 deletions
diff --git a/gnu/services/avahi.scm b/gnu/services/avahi.scm
index 18131fe561..49a737f090 100644
--- a/gnu/services/avahi.scm
+++ b/gnu/services/avahi.scm
@@ -107,19 +107,24 @@
(stop #~(make-kill-destructor))))))
(define avahi-service-type
- (service-type (name 'avahi)
- (extensions
- (list (service-extension dmd-root-service-type
- avahi-dmd-service)
- (service-extension dbus-root-service-type
- (compose list
- avahi-configuration-avahi))
- (service-extension account-service-type
- (const %avahi-accounts))
- (service-extension activation-service-type
- (const %avahi-activation))
- (service-extension nscd-service-type
- (const (list nss-mdns)))))))
+ (let ((avahi-package (compose list avahi-configuration-avahi)))
+ (service-type (name 'avahi)
+ (extensions
+ (list (service-extension dmd-root-service-type
+ avahi-dmd-service)
+ (service-extension dbus-root-service-type
+ avahi-package)
+ (service-extension account-service-type
+ (const %avahi-accounts))
+ (service-extension activation-service-type
+ (const %avahi-activation))
+ (service-extension nscd-service-type
+ (const (list nss-mdns)))
+
+ ;; Provide 'avahi-browse', 'avahi-resolve', etc. in
+ ;; the system profile.
+ (service-extension profile-service-type
+ avahi-package))))))
(define* (avahi-service #:key (avahi avahi)
host-name
@@ -132,7 +137,9 @@ mDNS/DNS-SD responder that allows for service discovery and
\"zero-configuration\" host name lookups (see @uref{http://avahi.org/}), and
extends the name service cache daemon (nscd) so that it can resolve
@code{.local} host names using
-@uref{http://0pointer.de/lennart/projects/nss-mdns/, nss-mdns}.
+@uref{http://0pointer.de/lennart/projects/nss-mdns/, nss-mdns}. Additionally,
+add the @var{avahi} package to the system profile so that commands such as
+@command{avahi-browse} are directly usable.
If @var{host-name} is different from @code{#f}, use that as the host name to
publish for this machine; otherwise, use the machine's actual host name.
diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 336cc4dec9..a86e8e04c7 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -2,6 +2,7 @@
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -23,12 +24,12 @@
#:use-module (gnu services)
#:use-module (gnu services dmd)
#:use-module (gnu services networking)
+ #:use-module (gnu system pam)
#:use-module (gnu system shadow) ; 'user-account', etc.
- #:use-module (gnu system linux) ; 'pam-service', etc.
#:use-module (gnu system file-systems) ; 'file-system', etc.
#:use-module (gnu packages admin)
#:use-module ((gnu packages linux)
- #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda))
+ #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda gpm))
#:use-module ((gnu packages base)
#:select (canonical-package glibc))
#:use-module (gnu packages package-management)
@@ -48,15 +49,23 @@
device-mapping-service
swap-service
user-processes-service
+ session-environment-service
+ session-environment-service-type
host-name-service
console-keymap-service
console-font-service
+
+ udev-configuration
+ udev-configuration?
+ udev-configuration-rules
udev-service-type
udev-service
+ udev-rule
mingetty-configuration
mingetty-configuration?
mingetty-service
+ mingetty-service-type
%nscd-default-caches
%nscd-default-configuration
@@ -74,6 +83,13 @@
guix-configuration
guix-configuration?
guix-service
+ guix-service-type
+ guix-publish-configuration
+ guix-publish-configuration?
+ guix-publish-service
+ guix-publish-service-type
+ gpm-service-type
+ gpm-service
%base-services))
@@ -142,6 +158,18 @@ FILE-SYSTEM."
(symbol-append 'file-system-
(string->symbol (file-system-mount-point file-system))))
+(define (mapped-device->dmd-service-name md)
+ "Return the symbol that denotes the dmd service of MD, a <mapped-device>."
+ (symbol-append 'device-mapping-
+ (string->symbol (mapped-device-target md))))
+
+(define dependency->dmd-service-name
+ (match-lambda
+ ((? mapped-device? md)
+ (mapped-device->dmd-service-name md))
+ ((? file-system? fs)
+ (file-system->dmd-service-name fs))))
+
(define file-system-service-type
;; TODO(?): Make this an extensible service that takes <file-system> objects
;; and returns a list of <dmd-service>.
@@ -158,7 +186,7 @@ FILE-SYSTEM."
(dmd-service
(provision (list (file-system->dmd-service-name file-system)))
(requirement `(root-file-system
- ,@(map file-system->dmd-service-name dependencies)))
+ ,@(map dependency->dmd-service-name dependencies)))
(documentation "Check, mount, and unmount the given file system.")
(start #~(lambda args
;; FIXME: Use or factorize with 'mount-file-system'.
@@ -198,7 +226,14 @@ FILE-SYSTEM."
(chdir "/")
(umount #$target)
- #f)))))))
+ #f))
+
+ ;; We need an additional module.
+ (modules `(((gnu build file-systems)
+ #:select (check-file-system canonicalize-device-spec))
+ ,@%default-modules))
+ (imported-modules `((gnu build file-systems)
+ ,@%default-imported-modules)))))))
(define* (file-system-service file-system)
"Return a service that mounts @var{file-system}, a @code{<file-system>}
@@ -336,6 +371,39 @@ stopped before 'kill' is called."
;;;
+;;; System-wide environment variables.
+;;;
+
+(define (environment-variables->environment-file vars)
+ "Return a file for pam_env(8) that contains environment variables VARS."
+ (apply mixed-text-file "environment"
+ (append-map (match-lambda
+ ((key . value)
+ (list key "=" value "\n")))
+ vars)))
+
+(define session-environment-service-type
+ (service-type
+ (name 'session-environment)
+ (extensions
+ (list (service-extension
+ etc-service-type
+ (lambda (vars)
+ (list `("environment"
+ ,(environment-variables->environment-file vars)))))))
+ (compose concatenate)
+ (extend append)))
+
+(define (session-environment-service vars)
+ "Return a service that builds the @file{/etc/environment}, which can be read
+by PAM-aware applications to set environment variables for sessions.
+
+VARS should be an association list in which both the keys and the values are
+strings or string-valued gexps."
+ (service session-environment-service-type vars))
+
+
+;;;
;;; Console & co.
;;;
@@ -691,6 +759,11 @@ If configuration file name @var{config-file} is not specified, use some
reasonable default settings."
(service syslog-service-type config-file))
+
+;;;
+;;; Guix services.
+;;;
+
(define* (guix-build-accounts count #:key
(group "guixbuild")
(first-uid 30001)
@@ -751,6 +824,8 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
(default #t))
(use-substitutes? guix-configuration-use-substitutes? ;Boolean
(default #t))
+ (substitute-urls guix-configuration-substitute-urls ;list of strings
+ (default %default-substitute-urls))
(extra-options guix-configuration-extra-options ;list of strings
(default '()))
(lsof guix-configuration-lsof ;<package>
@@ -765,7 +840,8 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
"Return a <dmd-service> for the Guix daemon service with CONFIG."
(match config
(($ <guix-configuration> guix build-group build-accounts authorize-key?
- use-substitutes? extra-options lsof lsh)
+ use-substitutes? substitute-urls extra-options
+ lsof lsh)
(list (dmd-service
(documentation "Run the Guix daemon.")
(provision '(guix-daemon))
@@ -777,6 +853,7 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
#$@(if use-substitutes?
'()
'("--no-substitutes"))
+ "--substitute-urls" #$(string-join substitute-urls)
#$@extra-options)
;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
@@ -824,6 +901,58 @@ failed to register hydra.gnu.org public key: ~a~%" status))))))))
@var{config}."
(service guix-service-type config))
+
+(define-record-type* <guix-publish-configuration>
+ guix-publish-configuration make-guix-publish-configuration
+ guix-publish-configuration?
+ (guix guix-publish-configuration-guix ;package
+ (default guix))
+ (port guix-publish-configuration-port ;number
+ (default 80))
+ (host guix-publish-configuration-host ;string
+ (default "localhost")))
+
+(define guix-publish-dmd-service
+ (match-lambda
+ (($ <guix-publish-configuration> guix port host)
+ (list (dmd-service
+ (provision '(guix-publish))
+ (requirement '(guix-daemon))
+ (start #~(make-forkexec-constructor
+ (list (string-append #$guix "/bin/guix")
+ "publish" "-u" "guix-publish"
+ "-p" #$(number->string port)
+ (string-append "--listen=" #$host))))
+ (stop #~(make-kill-destructor)))))))
+
+(define %guix-publish-accounts
+ (list (user-group (name "guix-publish") (system? #t))
+ (user-account
+ (name "guix-publish")
+ (group "guix-publish")
+ (system? #t)
+ (comment "guix publish user")
+ (home-directory "/var/empty")
+ (shell #~(string-append #$shadow "/sbin/nologin")))))
+
+(define guix-publish-service-type
+ (service-type (name 'guix-publish)
+ (extensions
+ (list (service-extension dmd-root-service-type
+ guix-publish-dmd-service)
+ (service-extension account-service-type
+ (const %guix-publish-accounts))))))
+
+(define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
+ "Return a service that runs @command{guix publish} listening on @var{host}
+and @var{port} (@pxref{Invoking guix publish}).
+
+This assumes that @file{/etc/guix} already contains a signing key pair as
+created by @command{guix archive --generate-key} (@pxref{Invoking guix
+archive}). If that is not the case, the service will fail to start."
+ (service guix-publish-service-type
+ (guix-publish-configuration (guix guix) (port port) (host host))))
+
;;;
;;; Udev.
@@ -864,12 +993,9 @@ item of @var{packages}."
#:modules '((guix build union)
(guix build utils))))
-(define* (kvm-udev-rule)
- "Return a directory with a udev rule that changes the group of
-@file{/dev/kvm} to \"kvm\" and makes it #o660."
- ;; Apparently QEMU-KVM used to ship this rule, but now we have to add it by
- ;; ourselves.
- (computed-file "kvm-udev-rules"
+(define (udev-rule file-name contents)
+ "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
+ (computed-file file-name
#~(begin
(use-modules (guix build utils))
@@ -878,20 +1004,26 @@ item of @var{packages}."
(mkdir-p rules.d)
(call-with-output-file
- (string-append rules.d "/90-kvm.rules")
+ (string-append rules.d "/" #$file-name)
(lambda (port)
- ;; Build users are part of the "kvm" group, so we
- ;; can fearlessly make /dev/kvm 660 (see
- ;; <http://bugs.gnu.org/18994>, for background.)
- (display "\
-KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n" port))))
+ (display #$contents port))))
#:modules '((guix build utils))))
+(define kvm-udev-rule
+ ;; Return a directory with a udev rule that changes the group of /dev/kvm to
+ ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
+ ;; but now we have to add it by ourselves.
+
+ ;; Build users are part of the "kvm" group, so we can fearlessly make
+ ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
+ (udev-rule "90-kvm.rules"
+ "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
+
(define udev-dmd-service
;; Return a <dmd-service> for UDEV with RULES.
(match-lambda
(($ <udev-configuration> udev rules)
- (let* ((rules (udev-rules-union (cons* udev (kvm-udev-rule) rules)))
+ (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
(udev.conf (computed-file "udev.conf"
#~(call-with-output-file #$output
(lambda (port)
@@ -1034,6 +1166,60 @@ gexp, to open it, and evaluate @var{close} to close it."
"Return a service that uses @var{device} as a swap device."
(service swap-service-type device))
+
+(define-record-type* <gpm-configuration>
+ gpm-configuration make-gpm-configuration gpm-configuration?
+ (gpm gpm-configuration-gpm) ;package
+ (options gpm-configuration-options)) ;list of strings
+
+(define gpm-dmd-service
+ (match-lambda
+ (($ <gpm-configuration> gpm options)
+ (list (dmd-service
+ (requirement '(udev))
+ (provision '(gpm))
+ (start #~(lambda ()
+ ;; 'gpm' runs in the background and sets a PID file.
+ ;; Note that it requires running as "root".
+ (false-if-exception (delete-file "/var/run/gpm.pid"))
+ (fork+exec-command (list (string-append #$gpm "/sbin/gpm")
+ #$@options))
+
+ ;; Wait for the PID file to appear; declare failure if
+ ;; it doesn't show up.
+ (let loop ((i 3))
+ (or (file-exists? "/var/run/gpm.pid")
+ (if (zero? i)
+ #f
+ (begin
+ (sleep 1)
+ (loop (1- i))))))))
+
+ (stop #~(lambda (_)
+ ;; Return #f if successfully stopped.
+ (not (zero? (system* (string-append #$gpm "/sbin/gpm")
+ "-k"))))))))))
+
+(define gpm-service-type
+ (service-type (name 'gpm)
+ (extensions
+ (list (service-extension dmd-root-service-type
+ gpm-dmd-service)))))
+
+(define* (gpm-service #:key (gpm gpm)
+ (options '("-m" "/dev/input/mice" "-t" "ps2")))
+ "Run @var{gpm}, the general-purpose mouse daemon, with the given
+command-line @var{options}. GPM allows users to use the mouse in the console,
+notably to select, copy, and paste text. The default value of @var{options}
+uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
+
+This service is not part of @var{%base-services}."
+ ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
+ ;; "info mice" and "mouse_set X" to use the right mouse.
+ (service gpm-service-type
+ (gpm-configuration (gpm gpm) (options options))))
+
+
(define %base-services
;; Convenience variable holding the basic services.
(let ((motd (plain-file "motd" "
diff --git a/gnu/services/dbus.scm b/gnu/services/dbus.scm
index e4ecd961c5..9b0d198683 100644
--- a/gnu/services/dbus.scm
+++ b/gnu/services/dbus.scm
@@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -20,7 +21,7 @@
#:use-module (gnu services)
#:use-module (gnu services dmd)
#:use-module (gnu system shadow)
- #:use-module (gnu packages glib)
+ #:use-module ((gnu packages glib) #:select (dbus/activation))
#:use-module (gnu packages admin)
#:use-module (guix gexp)
#:use-module (guix records)
@@ -37,13 +38,38 @@
dbus-configuration make-dbus-configuration
dbus-configuration?
(dbus dbus-configuration-dbus ;<package>
- (default dbus))
+ (default dbus/activation))
(services dbus-configuration-services ;list of <package>
(default '())))
-(define (dbus-configuration-directory dbus services)
- "Return a configuration directory for @var{dbus} that includes the
-@code{etc/dbus-1/system.d} directories of each package listed in
+(define (system-service-directory services)
+ "Return the system service directory, containing @code{.service} files for
+all the services that may be activated by the daemon."
+ (computed-file "dbus-system-services"
+ #~(begin
+ (use-modules (guix build utils)
+ (srfi srfi-1))
+
+ (define files
+ (append-map (lambda (service)
+ (find-files (string-append
+ service
+ "/share/dbus-1/system-services")
+ "\\.service$"))
+ (list #$@services)))
+
+ (mkdir #$output)
+ (for-each (lambda (file)
+ (symlink file
+ (string-append #$output "/"
+ (basename file))))
+ files)
+ #t)
+ #:modules '((guix build utils))))
+
+(define (dbus-configuration-directory services)
+ "Return a directory contains the @code{system-local.conf} file for DBUS that
+includes the @code{etc/dbus-1/system.d} directories of each package listed in
@var{services}."
(define build
#~(begin
@@ -53,24 +79,27 @@
(define (services->sxml services)
;; Return the SXML 'includedir' clauses for DIRS.
`(busconfig
+ (servicehelper "/run/setuid-programs/dbus-daemon-launch-helper")
+
+ ;; First, the '.service' files of services subject to activation.
+ ;; We use a fixed location under /etc because the setuid helper
+ ;; looks for them in that location and nowhere else. See
+ ;; <https://bugs.freedesktop.org/show_bug.cgi?id=92458>.
+ (servicedir "/etc/dbus-1/system-services")
+
,@(append-map (lambda (dir)
`((includedir
,(string-append dir "/etc/dbus-1/system.d"))
- (servicedir ;for '.service' files
- ,(string-append dir "/share/dbus-1/services"))
- (servicedir ;likewise, for auto-activation
- ,(string-append
- dir
- "/share/dbus-1/system-services"))))
+ (servicedir ;for '.service' files
+ ,(string-append dir "/share/dbus-1/services"))))
services)))
(mkdir #$output)
- (copy-file (string-append #$dbus "/etc/dbus-1/system.conf")
- (string-append #$output "/system.conf"))
- ;; The default 'system.conf' has an <includedir> clause for
- ;; 'system.d', so create it.
- (mkdir (string-append #$output "/system.d"))
+ ;; Provide /etc/dbus-1/system-services, which is where the setuid
+ ;; helper looks for system service files.
+ (symlink #$(system-service-directory services)
+ (string-append #$output "/system-services"))
;; 'system-local.conf' is automatically included by the default
;; 'system.conf', so this is where we stuff our own things.
@@ -81,6 +110,12 @@
(computed-file "dbus-configuration" build))
+(define (dbus-etc-files config)
+ "Return a list of FILES for @var{etc-service-type} to build the
+@code{/etc/dbus-1} directory."
+ (list `("dbus-1" ,(dbus-configuration-directory
+ (dbus-configuration-services config)))))
+
(define %dbus-accounts
;; Accounts used by the system bus.
(list (user-group (name "messagebus") (system? #t))
@@ -92,6 +127,12 @@
(home-directory "/var/run/dbus")
(shell #~(string-append #$shadow "/sbin/nologin")))))
+(define dbus-setuid-programs
+ ;; Return the file name of the setuid program that we need.
+ (match-lambda
+ (($ <dbus-configuration> dbus services)
+ (list #~(string-append #$dbus "/libexec/dbus-daemon-launch-helper")))))
+
(define (dbus-activation config)
"Return an activation gexp for D-Bus using @var{config}."
#~(begin
@@ -120,18 +161,15 @@
(define dbus-dmd-service
(match-lambda
- (($ <dbus-configuration> dbus services)
- (let ((conf (dbus-configuration-directory dbus services)))
- (list (dmd-service
- (documentation "Run the D-Bus system daemon.")
- (provision '(dbus-system))
- (requirement '(user-processes))
- (start #~(make-forkexec-constructor
- (list (string-append #$dbus "/bin/dbus-daemon")
- "--nofork"
- (string-append "--config-file=" #$conf
- "/system.conf"))))
- (stop #~(make-kill-destructor))))))))
+ (($ <dbus-configuration> dbus)
+ (list (dmd-service
+ (documentation "Run the D-Bus system daemon.")
+ (provision '(dbus-system))
+ (requirement '(user-processes))
+ (start #~(make-forkexec-constructor
+ (list (string-append #$dbus "/bin/dbus-daemon")
+ "--nofork" "--system")))
+ (stop #~(make-kill-destructor)))))))
(define dbus-root-service-type
(service-type (name 'dbus)
@@ -140,14 +178,15 @@
dbus-dmd-service)
(service-extension activation-service-type
dbus-activation)
+ (service-extension etc-service-type
+ dbus-etc-files)
(service-extension account-service-type
- (const %dbus-accounts))))
+ (const %dbus-accounts))
+ (service-extension setuid-program-service-type
+ dbus-setuid-programs)))
;; Extensions consist of lists of packages (representing D-Bus
;; services) that we just concatenate.
- ;;
- ;; FIXME: We need 'dbus-daemon-launch-helper' to be
- ;; setuid-root for auto-activation to work.
(compose concatenate)
;; The service's parameters field is extended by augmenting
@@ -159,7 +198,7 @@
(append (dbus-configuration-services config)
services)))))))
-(define* (dbus-service #:key (dbus dbus) (services '()))
+(define* (dbus-service #:key (dbus dbus/activation) (services '()))
"Return a service that runs the \"system bus\", using @var{dbus}, with
support for @var{services}.
diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index 69edc6d9bb..694a8eda7e 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -27,13 +27,15 @@
#:use-module (gnu services xorg)
#:use-module (gnu services networking)
#:use-module (gnu system shadow)
- #:use-module (gnu system linux) ; unix-pam-service
+ #:use-module (gnu system pam)
#:use-module (gnu packages glib)
#:use-module (gnu packages admin)
#:use-module (gnu packages freedesktop)
#:use-module (gnu packages gnome)
#:use-module (gnu packages avahi)
#:use-module (gnu packages polkit)
+ #:use-module (gnu packages xdisorg)
+ #:use-module (gnu packages suckless)
#:use-module (guix records)
#:use-module (guix packages)
#:use-module (guix store)
@@ -41,6 +43,7 @@
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
#:export (upower-service
+ udisks-service
colord-service
geoclue-application
%standard-geoclue-applications
@@ -224,65 +227,6 @@ levels, with the given configuration settings. It implements the
;;;
-;;; Colord D-Bus service.
-;;;
-
-(define %colord-activation
- #~(begin
- (use-modules (guix build utils))
- (mkdir-p "/var/lib/colord")
- (let ((user (getpwnam "colord")))
- (chown "/var/lib/colord"
- (passwd:uid user) (passwd:gid user)))))
-
-(define %colord-accounts
- (list (user-group (name "colord") (system? #t))
- (user-account
- (name "colord")
- (group "colord")
- (system? #t)
- (comment "colord daemon user")
- (home-directory "/var/empty")
- (shell #~(string-append #$shadow "/sbin/nologin")))))
-
-(define (colord-dmd-service colord)
- "Return a dmd service for COLORD."
- ;; TODO: Remove when D-Bus activation works.
- (list (dmd-service
- (documentation "Run the colord color management service.")
- (provision '(colord-daemon))
- (requirement '(dbus-system udev))
- (start #~(make-forkexec-constructor
- (list (string-append #$colord "/libexec/colord"))))
- (stop #~(make-kill-destructor)))))
-
-(define colord-service-type
- (service-type (name 'colord)
- (extensions
- (list (service-extension account-service-type
- (const %colord-accounts))
- (service-extension activation-service-type
- (const %colord-activation))
- (service-extension dmd-root-service-type
- colord-dmd-service)
-
- ;; Colord is a D-Bus service that dbus-daemon can
- ;; activate.
- (service-extension dbus-root-service-type list)
-
- ;; Colord provides "color device" rules for udev.
- (service-extension udev-service-type list)))))
-
-(define* (colord-service #:key (colord colord))
- "Return a service that runs @command{colord}, a system service with a D-Bus
-interface to manage the color profiles of input and output devices such as
-screens and scanners. It is notably used by the GNOME Color Manager graphical
-tool. See @uref{http://www.freedesktop.org/software/colord/, the colord web
-site} for more information."
- (service colord-service-type colord))
-
-
-;;;
;;; GeoClue D-Bus service.
;;;
@@ -343,23 +287,6 @@ users are allowed."
"GEOCLUE_CONFIG_FILE"
(geoclue-configuration-file config))))
-(define (geoclue-dmd-service config)
- "Return a GeoClue dmd service for CONFIG."
- ;; TODO: Remove when D-Bus activation works.
- (let ((geoclue (geoclue-configuration-geoclue config))
- (config (geoclue-configuration-file config)))
- (list (dmd-service
- (documentation "Run the GeoClue location service.")
- (provision '(geoclue-daemon))
- (requirement '(dbus-system))
-
- (start #~(make-forkexec-constructor
- (list (string-append #$geoclue "/libexec/geoclue"))
- #:user "geoclue"
- #:environment-variables
- (list (string-append "GEOCLUE_CONFIG_FILE=" #$config))))
- (stop #~(make-kill-destructor))))))
-
(define %geoclue-accounts
(list (user-group (name "geoclue") (system? #t))
(user-account
@@ -375,8 +302,6 @@ users are allowed."
(extensions
(list (service-extension dbus-root-service-type
geoclue-dbus-service)
- (service-extension dmd-root-service-type
- geoclue-dmd-service)
(service-extension account-service-type
(const %geoclue-accounts))))))
@@ -413,6 +338,14 @@ site} for more information."
;;; Polkit privilege management service.
;;;
+(define-record-type* <polkit-configuration>
+ polkit-configuration make-polkit-configuration
+ polkit-configuration?
+ (polkit polkit-configuration-polkit ;<package>
+ (default polkit))
+ (actions polkit-configuration-actions ;list of <package>
+ (default '())))
+
(define %polkit-accounts
(list (user-group (name "polkitd") (system? #t))
(user-account
@@ -424,23 +357,34 @@ site} for more information."
(shell "/run/current-system/profile/sbin/nologin"))))
(define %polkit-pam-services
- (list (unix-pam-service "polkitd")))
+ (list (unix-pam-service "polkit-1")))
-(define (polkit-dmd-service polkit)
- "Return the <dmd-service> for POLKIT."
- ;; TODO: Remove when D-Bus activation works.
- (list (dmd-service
- (documentation "Run the polkit privilege management service.")
- (provision '(polkit-daemon))
- (requirement '(dbus-system))
+(define (polkit-directory packages)
+ "Return a directory containing an @file{actions} and possibly a
+@file{rules.d} sub-directory, for use as @file{/etc/polkit-1}."
+ (computed-file "etc-polkit-1"
+ #~(begin
+ (use-modules (guix build union) (srfi srfi-26))
+
+ (union-build #$output
+ (map (cut string-append <>
+ "/share/polkit-1")
+ (list #$@packages))))
+ #:modules '((guix build union))))
- (start #~(make-forkexec-constructor
- (list (string-append #$polkit "/lib/polkit-1/polkitd"))))
- (stop #~(make-kill-destructor)))))
+(define polkit-etc-files
+ (match-lambda
+ (($ <polkit-configuration> polkit packages)
+ `(("polkit-1" ,(polkit-directory packages))))))
+
+(define polkit-setuid-programs
+ (match-lambda
+ (($ <polkit-configuration> polkit)
+ (list #~(string-append #$polkit
+ "/lib/polkit-1/polkit-agent-helper-1")
+ #~(string-append #$polkit "/bin/pkexec")))))
(define polkit-service-type
- ;; TODO: Make it extensible so it can collect policy files from other
- ;; services.
(service-type (name 'polkit)
(extensions
(list (service-extension account-service-type
@@ -448,17 +392,118 @@ site} for more information."
(service-extension pam-root-service-type
(const %polkit-pam-services))
(service-extension dbus-root-service-type
- list)
- (service-extension dmd-root-service-type
- polkit-dmd-service)))))
+ (compose
+ list
+ polkit-configuration-polkit))
+ (service-extension etc-service-type
+ polkit-etc-files)
+ (service-extension setuid-program-service-type
+ polkit-setuid-programs)))
+
+ ;; Extensions are lists of packages that provide polkit rules
+ ;; or actions under share/polkit-1/{actions,rules.d}.
+ (compose concatenate)
+ (extend (lambda (config actions)
+ (polkit-configuration
+ (inherit config)
+ (actions
+ (append (polkit-configuration-actions config)
+ actions)))))))
(define* (polkit-service #:key (polkit polkit))
- "Return a service that runs the @command{polkit} privilege management
-service. By querying the @command{polkit} service, a privileged system
-component can know when it should grant additional capabilities to ordinary
-users. For example, an ordinary user can be granted the capability to suspend
-the system if the user is logged in locally."
- (service polkit-service-type polkit))
+ "Return a service that runs the
+@uref{http://www.freedesktop.org/wiki/Software/polkit/, Polkit privilege
+management service}, which allows system administrators to grant access to
+privileged operations in a structured way. By querying the Polkit service, a
+privileged system component can know when it should grant additional
+capabilities to ordinary users. For example, an ordinary user can be granted
+the capability to suspend the system if the user is logged in locally."
+ (service polkit-service-type
+ (polkit-configuration (polkit polkit))))
+
+
+;;;
+;;; Colord D-Bus service.
+;;;
+
+(define %colord-activation
+ #~(begin
+ (use-modules (guix build utils))
+ (mkdir-p "/var/lib/colord")
+ (let ((user (getpwnam "colord")))
+ (chown "/var/lib/colord"
+ (passwd:uid user) (passwd:gid user)))))
+
+(define %colord-accounts
+ (list (user-group (name "colord") (system? #t))
+ (user-account
+ (name "colord")
+ (group "colord")
+ (system? #t)
+ (comment "colord daemon user")
+ (home-directory "/var/empty")
+ (shell #~(string-append #$shadow "/sbin/nologin")))))
+
+(define colord-service-type
+ (service-type (name 'colord)
+ (extensions
+ (list (service-extension account-service-type
+ (const %colord-accounts))
+ (service-extension activation-service-type
+ (const %colord-activation))
+
+ ;; Colord is a D-Bus service that dbus-daemon can
+ ;; activate.
+ (service-extension dbus-root-service-type list)
+
+ ;; Colord provides "color device" rules for udev.
+ (service-extension udev-service-type list)
+
+ ;; It provides polkit "actions".
+ (service-extension polkit-service-type list)))))
+
+(define* (colord-service #:key (colord colord))
+ "Return a service that runs @command{colord}, a system service with a D-Bus
+interface to manage the color profiles of input and output devices such as
+screens and scanners. It is notably used by the GNOME Color Manager graphical
+tool. See @uref{http://www.freedesktop.org/software/colord/, the colord web
+site} for more information."
+ (service colord-service-type colord))
+
+
+;;;
+;;; UDisks.
+;;;
+
+(define-record-type* <udisks-configuration>
+ udisks-configuration make-udisks-configuration
+ udisks-configuration?
+ (udisks udisks-configuration-udisks
+ (default udisks)))
+
+(define udisks-service-type
+ (let ((udisks-package (lambda (config)
+ (list (udisks-configuration-udisks config)))))
+ (service-type (name 'udisks)
+ (extensions
+ (list (service-extension polkit-service-type
+ udisks-package)
+ (service-extension dbus-root-service-type
+ udisks-package)
+ (service-extension udev-service-type
+ udisks-package)
+
+ ;; Profile 'udisksctl' & co. in the system profile.
+ (service-extension profile-service-type
+ udisks-package))))))
+
+(define* (udisks-service #:key (udisks udisks))
+ "Return a service for @uref{http://udisks.freedesktop.org/docs/latest/,
+UDisks}, a @dfn{disk management} daemon that provides user interfaces with
+notifications and ways to mount/unmount disks. Programs that talk to UDisks
+include the @command{udisksctl} command, part of UDisks, and GNOME Disks."
+ (service udisks-service-type
+ (udisks-configuration (udisks udisks))))
;;;
@@ -601,6 +646,8 @@ the system if the user is logged in locally."
(define (elogind-dmd-service config)
"Return a dmd service for elogind, using @var{config}."
+ ;; TODO: We could probably rely on service activation but the '.service'
+ ;; file currently contains an erroneous 'Exec' line.
(let ((config-file (elogind-configuration-file config))
(elogind (elogind-package config)))
(list (dmd-service
@@ -623,7 +670,9 @@ the system if the user is logged in locally."
(compose list elogind-package))
(service-extension udev-service-type
(compose list elogind-package))
- ;; TODO: Extend polkit(?) and PAM.
+ (service-extension polkit-service-type
+ (compose list elogind-package))
+ ;; TODO: Extend PAM with pam_elogind.so.
))))
(define* (elogind-service #:key (config (elogind-configuration)))
@@ -643,9 +692,14 @@ when they log out."
;; List of services typically useful for a "desktop" use case.
(cons* (slim-service)
+ ;; Screen lockers are a pretty useful thing and these are small.
+ (screen-locker-service slock)
+ (screen-locker-service xlockmore "xlock")
+
;; The D-Bus clique.
(avahi-service)
(wicd-service)
+ (udisks-service)
(upower-service)
(colord-service)
(geoclue-service)
diff --git a/gnu/services/dmd.scm b/gnu/services/dmd.scm
index e87b9e4415..545087acc9 100644
--- a/gnu/services/dmd.scm
+++ b/gnu/services/dmd.scm
@@ -45,6 +45,11 @@
dmd-service-start
dmd-service-stop
dmd-service-auto-start?
+ dmd-service-modules
+ dmd-service-imported-modules
+
+ %default-imported-modules
+ %default-modules
dmd-service-back-edges))
@@ -99,6 +104,18 @@ service that extends DMD-ROOT-SERVICE-TYPE and nothing else."
(list (service-extension dmd-root-service-type
(compose list proc))))))
+(define %default-imported-modules
+ ;; Default set of modules imported for a service's consumption.
+ '((guix build utils)
+ (guix build syscalls)))
+
+(define %default-modules
+ ;; Default set of modules visible in a service's file.
+ `((dmd service)
+ (oop goops)
+ (guix build utils)
+ (guix build syscalls)))
+
(define-record-type* <dmd-service>
dmd-service make-dmd-service
dmd-service?
@@ -113,64 +130,106 @@ service that extends DMD-ROOT-SERVICE-TYPE and nothing else."
(stop dmd-service-stop ;g-expression (procedure)
(default #~(const #f)))
(auto-start? dmd-service-auto-start? ;Boolean
- (default #t)))
+ (default #t))
+ (modules dmd-service-modules ;list of module names
+ (default %default-modules))
+ (imported-modules dmd-service-imported-modules ;list of module names
+ (default %default-imported-modules)))
-(define (assert-no-duplicates services)
- "Raise an error if SERVICES provide the same dmd service more than once.
+(define (assert-valid-graph services)
+ "Raise an error if SERVICES does not define a valid dmd service graph, for
+instance if a service requires a nonexistent service, or if more than one
+service uses a given name.
-This is a constraint that dmd's 'register-service' verifies but we'd better
-verify it here statically than wait until PID 1 halts with an assertion
+These are constraints that dmd's 'register-service' verifies but we'd better
+verify them here statically than wait until PID 1 halts with an assertion
failure."
- (fold (lambda (service set)
- (define (assert-unique symbol)
- (when (set-contains? set symbol)
- (raise (condition
- (&message
- (message
- (format #f (_ "service '~a' provided more than once")
- symbol)))))))
-
- (for-each assert-unique (dmd-service-provision service))
- (fold set-insert set (dmd-service-provision service)))
- (setq)
- services))
+ (define provisions
+ ;; The set of provisions (symbols). Bail out if a symbol is given more
+ ;; than once.
+ (fold (lambda (service set)
+ (define (assert-unique symbol)
+ (when (set-contains? set symbol)
+ (raise (condition
+ (&message
+ (message
+ (format #f (_ "service '~a' provided more than once")
+ symbol)))))))
+
+ (for-each assert-unique (dmd-service-provision service))
+ (fold set-insert set (dmd-service-provision service)))
+ (setq 'dmd)
+ services))
+
+ (define (assert-satisfied-requirements service)
+ ;; Bail out if the requirements of SERVICE aren't satisfied.
+ (for-each (lambda (requirement)
+ (unless (set-contains? provisions requirement)
+ (raise (condition
+ (&message
+ (message
+ (format #f (_ "service '~a' requires '~a', \
+which is undefined")
+ (match (dmd-service-provision service)
+ ((head . _) head)
+ (_ service))
+ requirement)))))))
+ (dmd-service-requirement service)))
+
+ (for-each assert-satisfied-requirements services))
+
+(define (dmd-service-file-name service)
+ "Return the file name where the initialization code for SERVICE is to be
+stored."
+ (let ((provisions (string-join (map symbol->string
+ (dmd-service-provision service)))))
+ (string-append "dmd-"
+ (string-map (match-lambda
+ (#\/ #\-)
+ (chr chr))
+ provisions)
+ ".scm")))
+
+(define (dmd-service-file service)
+ "Return a file defining SERVICE."
+ (gexp->file (dmd-service-file-name service)
+ #~(begin
+ (use-modules #$@(dmd-service-modules service))
+
+ (make <service>
+ #:docstring '#$(dmd-service-documentation service)
+ #:provides '#$(dmd-service-provision service)
+ #:requires '#$(dmd-service-requirement service)
+ #:respawn? '#$(dmd-service-respawn? service)
+ #:start #$(dmd-service-start service)
+ #:stop #$(dmd-service-stop service)))))
(define (dmd-configuration-file services)
"Return the dmd configuration file for SERVICES."
(define modules
- ;; Extra modules visible to dmd.conf.
- '((guix build syscalls)
- (gnu build file-systems)
- (guix build utils)))
+ (delete-duplicates
+ (append-map dmd-service-imported-modules services)))
- (assert-no-duplicates services)
+ (assert-valid-graph services)
(mlet %store-monad ((modules (imported-modules modules))
- (compiled (compiled-modules modules)))
+ (compiled (compiled-modules modules))
+ (files (mapm %store-monad dmd-service-file services)))
(define config
#~(begin
(eval-when (expand load eval)
(set! %load-path (cons #$modules %load-path))
(set! %load-compiled-path
- (cons #$compiled %load-compiled-path)))
-
- (use-modules (ice-9 ftw)
- (guix build syscalls)
- (guix build utils)
- ((gnu build file-systems)
- #:select (check-file-system canonicalize-device-spec)))
-
- (register-services
- #$@(map (lambda (service)
- #~(make <service>
- #:docstring '#$(dmd-service-documentation service)
- #:provides '#$(dmd-service-provision service)
- #:requires '#$(dmd-service-requirement service)
- #:respawn? '#$(dmd-service-respawn? service)
- #:start #$(dmd-service-start service)
- #:stop #$(dmd-service-stop service)))
- services))
+ (cons #$compiled %load-compiled-path)))
+
+ (use-modules (system repl error-handling))
+
+ ;; Arrange to spawn a REPL if loading one of FILES fails. This is
+ ;; better than a kernel panic.
+ (call-with-error-handling
+ (lambda ()
+ (apply register-services (map primitive-load '#$files))))
;; guix-daemon 0.6 aborts if 'PATH' is undefined, so work around it.
(setenv "PATH" "/run/current-system/profile/bin")
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index 003d5a5010..ce21b1d9ff 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -22,15 +22,18 @@
#:use-module (gnu services dmd)
#:use-module (gnu services dbus)
#:use-module (gnu system shadow)
- #:use-module (gnu system linux) ;PAM
+ #:use-module (gnu system pam)
#:use-module (gnu packages admin)
#:use-module (gnu packages linux)
#:use-module (gnu packages tor)
#:use-module (gnu packages messaging)
#:use-module (gnu packages ntp)
#:use-module (gnu packages wicd)
+ #:use-module (gnu packages gnome)
#:use-module (guix gexp)
#:use-module (guix records)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-9)
#:use-module (srfi srfi-26)
#:use-module (ice-9 match)
#:export (%facebook-host-aliases
@@ -38,9 +41,11 @@
dhcp-client-service
%ntp-servers
ntp-service
+ tor-hidden-service
tor-service
bitlbee-service
- wicd-service))
+ wicd-service
+ network-manager-service))
;;; Commentary:
;;;
@@ -305,6 +310,15 @@ keep the system clock synchronized with that of @var{servers}."
;;; Tor.
;;;
+(define-record-type* <tor-configuration>
+ tor-configuration make-tor-configuration
+ tor-configuration?
+ (tor tor-configuration-tor
+ (default tor))
+ (config-file tor-configuration-config-file)
+ (hidden-services tor-configuration-hidden-services
+ (default '())))
+
(define %tor-accounts
;; User account and groups for Tor.
(list (user-group (name "tor") (system? #t))
@@ -316,20 +330,93 @@ keep the system clock synchronized with that of @var{servers}."
(home-directory "/var/empty")
(shell #~(string-append #$shadow "/sbin/nologin")))))
-(define (tor-dmd-service tor)
+(define-record-type <hidden-service>
+ (hidden-service name mapping)
+ hidden-service?
+ (name hidden-service-name) ;string
+ (mapping hidden-service-mapping)) ;list of port/address tuples
+
+(define (tor-configuration->torrc config)
+ "Return a 'torrc' file for CONFIG."
+ (match config
+ (($ <tor-configuration> tor config-file services)
+ (computed-file
+ "torrc"
+ #~(begin
+ (use-modules (guix build utils)
+ (ice-9 match))
+
+ (call-with-output-file #$output
+ (lambda (port)
+ (display "\
+# The beginning was automatically added.
+User tor
+DataDirectory /var/lib/tor
+Log notice syslog\n" port)
+
+ (for-each (match-lambda
+ ((service (ports hosts) ...)
+ (format port "\
+HiddenServiceDir /var/lib/tor/hidden-services/~a~%"
+ service)
+ (for-each (lambda (tcp-port host)
+ (format port "\
+HiddenServicePort ~a ~a~%"
+ tcp-port host))
+ ports hosts)))
+ '#$(map (match-lambda
+ (($ <hidden-service> name mapping)
+ (cons name mapping)))
+ services))
+
+ ;; Append the user's config file.
+ (call-with-input-file #$config-file
+ (lambda (input)
+ (dump-port input port)))
+ #t)))
+ #:modules '((guix build utils))))))
+
+(define (tor-dmd-service config)
"Return a <dmd-service> running TOR."
- (let ((torrc (plain-file "torrc" "User tor\n")))
- (list (dmd-service
- (provision '(tor))
+ (match config
+ (($ <tor-configuration> tor)
+ (let ((torrc (tor-configuration->torrc config)))
+ (list (dmd-service
+ (provision '(tor))
+
+ ;; Tor needs at least one network interface to be up, hence the
+ ;; dependency on 'loopback'.
+ (requirement '(user-processes loopback syslogd))
+
+ (start #~(make-forkexec-constructor
+ (list (string-append #$tor "/bin/tor") "-f" #$torrc)))
+ (stop #~(make-kill-destructor))
+ (documentation "Run the Tor anonymous network overlay.")))))))
+
+(define (tor-hidden-service-activation config)
+ "Return the activation gexp for SERVICES, a list of hidden services."
+ #~(begin
+ (use-modules (guix build utils))
+
+ (define %user
+ (getpw "tor"))
- ;; Tor needs at least one network interface to be up, hence the
- ;; dependency on 'loopback'.
- (requirement '(user-processes loopback))
+ (define (initialize service)
+ (let ((directory (string-append "/var/lib/tor/hidden-services/"
+ service)))
+ (mkdir-p directory)
+ (chown directory (passwd:uid %user) (passwd:gid %user))
- (start #~(make-forkexec-constructor
- (list (string-append #$tor "/bin/tor") "-f" #$torrc)))
- (stop #~(make-kill-destructor))
- (documentation "Run the Tor anonymous network overlay.")))))
+ ;; The daemon bails out if we give wider permissions.
+ (chmod directory #o700)))
+
+ (mkdir-p "/var/lib/tor")
+ (chown "/var/lib/tor" (passwd:uid %user) (passwd:gid %user))
+ (chmod "/var/lib/tor" #o700)
+
+ (for-each initialize
+ '#$(map hidden-service-name
+ (tor-configuration-hidden-services config)))))
(define tor-service-type
(service-type (name 'tor)
@@ -337,14 +424,59 @@ keep the system clock synchronized with that of @var{servers}."
(list (service-extension dmd-root-service-type
tor-dmd-service)
(service-extension account-service-type
- (const %tor-accounts))))))
+ (const %tor-accounts))
+ (service-extension activation-service-type
+ tor-hidden-service-activation)))
+
+ ;; This can be extended with hidden services.
+ (compose concatenate)
+ (extend (lambda (config services)
+ (tor-configuration
+ (inherit config)
+ (hidden-services
+ (append (tor-configuration-hidden-services config)
+ services)))))))
+
+(define* (tor-service #:optional
+ (config-file (plain-file "empty" ""))
+ #:key (tor tor))
+ "Return a service to run the @uref{https://torproject.org, Tor} anonymous
+networking daemon.
+
+The daemon runs as the @code{tor} unprivileged user. It is passed
+@var{config-file}, a file-like object, with an additional @code{User tor} line
+and lines for hidden services added via @code{tor-hidden-service}. Run
+@command{man tor} for information about the configuration file."
+ (service tor-service-type
+ (tor-configuration (tor tor)
+ (config-file config-file))))
+
+(define tor-hidden-service-type
+ ;; A type that extends Tor with hidden services.
+ (service-type (name 'tor-hidden-service)
+ (extensions
+ (list (service-extension tor-service-type list)))))
+
+(define (tor-hidden-service name mapping)
+ "Define a new Tor @dfn{hidden service} called @var{name} and implementing
+@var{mapping}. @var{mapping} is a list of port/host tuples, such as:
-(define* (tor-service #:key (tor tor))
- "Return a service to run the @uref{https://torproject.org,Tor} daemon.
+@example
+ '((22 \"127.0.0.1:22\")
+ (80 \"127.0.0.1:8080\"))
+@end example
-The daemon runs with the default settings (in particular the default exit
-policy) as the @code{tor} unprivileged user."
- (service tor-service-type tor))
+In this example, port 22 of the hidden service is mapped to local port 22, and
+port 80 is mapped to local port 8080.
+
+This creates a @file{/var/lib/tor/hidden-services/@var{name}} directory, where
+the @file{hostname} file contains the @code{.onion} host name for the hidden
+service.
+
+See @uref{https://www.torproject.org/docs/tor-hidden-service.html.en, the Tor
+project's documentation} for more information."
+ (service tor-hidden-service-type
+ (hidden-service name mapping)))
;;;
@@ -466,11 +598,58 @@ configuration file."
(service-extension dbus-root-service-type
list)
(service-extension activation-service-type
- (const %wicd-activation))))))
+ (const %wicd-activation))
+
+ ;; Add Wicd to the global profile.
+ (service-extension profile-service-type list)))))
(define* (wicd-service #:key (wicd wicd))
"Return a service that runs @url{https://launchpad.net/wicd,Wicd}, a network
-manager that aims to simplify wired and wireless networking."
+management daemon that aims to simplify wired and wireless networking.
+
+This service adds the @var{wicd} package to the global profile, providing
+several commands to interact with the daemon and configure networking:
+@command{wicd-client}, a graphical user interface, and the @command{wicd-cli}
+and @command{wicd-curses} user interfaces."
(service wicd-service-type wicd))
+
+;;;
+;;; NetworkManager
+;;;
+
+(define %network-manager-activation
+ ;; Activation gexp for NetworkManager.
+ #~(begin
+ (use-modules (guix build utils))
+ (mkdir-p "/etc/NetworkManager/system-connections")))
+
+(define (network-manager-dmd-service network-manager)
+ "Return a dmd service for NETWORK-MANAGER."
+ (list (dmd-service
+ (documentation "Run the NetworkManager.")
+ (provision '(networking))
+ (requirement '(user-processes dbus-system loopback))
+ (start #~(make-forkexec-constructor
+ (list (string-append #$network-manager
+ "/sbin/NetworkManager")
+ "--no-daemon")))
+ (stop #~(make-kill-destructor)))))
+
+(define network-manager-service-type
+ (service-type (name 'network-manager)
+ (extensions
+ (list (service-extension dmd-root-service-type
+ network-manager-dmd-service)
+ (service-extension dbus-root-service-type list)
+ (service-extension activation-service-type
+ (const %network-manager-activation))
+ ;; Add network-manager to the system profile.
+ (service-extension profile-service-type list)))))
+
+(define* (network-manager-service #:key (network-manager network-manager))
+ "Return a service that runs NetworkManager, a network connection manager
+that attempting to keep active network connectivity when available."
+ (service network-manager-service-type network-manager))
+
;;; networking.scm ends here
diff --git a/gnu/services/ssh.scm b/gnu/services/ssh.scm
index d3a6cfb33a..4b0380e8fd 100644
--- a/gnu/services/ssh.scm
+++ b/gnu/services/ssh.scm
@@ -21,8 +21,9 @@
#:use-module (guix records)
#:use-module (gnu services)
#:use-module (gnu services dmd)
- #:use-module (gnu system linux) ; 'pam-service'
+ #:use-module (gnu system pam)
#:use-module (gnu packages lsh)
+ #:use-module (srfi srfi-26)
#:export (lsh-service))
;;; Commentary:
@@ -142,8 +143,8 @@
"--tcpip-forward" "--no-tcpip-forward")
(if (null? interfaces)
'()
- (list (string-append "--interfaces="
- (string-join interfaces ",")))))))
+ (map (cut string-append "--interface=" <>)
+ interfaces)))))
(define requires
(if (and daemonic? (lsh-configuration-syslog-output? config))
diff --git a/gnu/services/xorg.scm b/gnu/services/xorg.scm
index 3a57891a96..7fea6829d5 100644
--- a/gnu/services/xorg.scm
+++ b/gnu/services/xorg.scm
@@ -21,7 +21,7 @@
#:use-module (gnu artwork)
#:use-module (gnu services)
#:use-module (gnu services dmd)
- #:use-module (gnu system linux) ; 'pam-service'
+ #:use-module (gnu system pam)
#:use-module ((gnu packages base) #:select (canonical-package))
#:use-module (gnu packages guile)
#:use-module (gnu packages xorg)
@@ -32,16 +32,23 @@
#:use-module (gnu packages bash)
#:use-module (guix gexp)
#:use-module (guix store)
+ #:use-module (guix packages)
#:use-module (guix derivations)
#:use-module (guix records)
#:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-9)
#:use-module (srfi srfi-26)
#:use-module (ice-9 match)
#:export (xorg-configuration-file
xorg-start-command
%default-slim-theme
%default-slim-theme-name
- slim-service))
+ slim-configuration
+ slim-service-type
+ slim-service
+
+ screen-locker-service-type
+ screen-locker-service))
;;; Commentary:
;;;
@@ -304,7 +311,12 @@ reboot_cmd " dmd "/sbin/reboot\n"
(list (service-extension dmd-root-service-type
slim-dmd-service)
(service-extension pam-root-service-type
- slim-pam-service)))))
+ slim-pam-service)
+
+ ;; Unconditionally add xterm to the system profile, to
+ ;; avoid bad surprises.
+ (service-extension profile-service-type
+ (const (list xterm)))))))
(define* (slim-service #:key (slim slim)
(allow-empty-passwords? #t) auto-login?
@@ -350,4 +362,52 @@ theme."
(auto-login-session auto-login-session)
(startx startx))))
+
+;;;
+;;; Screen lockers & co.
+;;;
+
+(define-record-type <screen-locker>
+ (screen-locker name program empty?)
+ screen-locker?
+ (name screen-locker-name) ;string
+ (program screen-locker-program) ;gexp
+ (empty? screen-locker-allows-empty-passwords?)) ;Boolean
+
+(define screen-locker-pam-services
+ (match-lambda
+ (($ <screen-locker> name _ empty?)
+ (list (unix-pam-service name
+ #:allow-empty-passwords? empty?)))))
+
+(define screen-locker-setuid-programs
+ (compose list screen-locker-program))
+
+(define screen-locker-service-type
+ (service-type (name 'screen-locker)
+ (extensions
+ (list (service-extension pam-root-service-type
+ screen-locker-pam-services)
+ (service-extension setuid-program-service-type
+ screen-locker-setuid-programs)))))
+
+(define* (screen-locker-service package
+ #:optional
+ (program (package-name package))
+ #:key allow-empty-passwords?)
+ "Add @var{package}, a package for a screen-locker or screen-saver whose
+command is @var{program}, to the set of setuid programs and add a PAM entry
+for it. For example:
+
+@lisp
+(screen-locker-service xlockmore \"xlock\")
+@end lisp
+
+makes the good ol' XlockMore usable."
+ (service screen-locker-service-type
+ (screen-locker program
+ #~(string-append #$package
+ #$(string-append "/bin/" program))
+ allow-empty-passwords?)))
+
;;; xorg.scm ends here