aboutsummaryrefslogtreecommitdiff
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2023 Efraim Flashner <efraim@flashner.co.il>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu home services gnupg)
  #:use-module (guix gexp)
  #:use-module (guix modules)
  #:use-module ((guix records) #:select (match-record))
  #:use-module (gnu services)
  #:use-module (gnu services configuration)
  #:use-module (gnu home services)
  #:use-module (gnu home services shepherd)
  #:autoload   (gnu packages gnupg) (gnupg pinentry parcimonie)
  #:export (home-gpg-agent-configuration
            home-gpg-agent-configuration?
            home-gpg-agent-configuration-gnupg
            home-gpg-agent-configuration-pinentry-program
            home-gpg-agent-configuration-ssh-support?
            home-gpg-agent-configuration-default-cache-ttl
            home-gpg-agent-configuration-max-cache-ttl
            home-gpg-agent-configuration-max-cache-ttl-ssh
            home-gpg-agent-configuration-extra-content

            home-gpg-agent-service-type

            home-parcimonie-configuration
            home-parcimonie-configuration?
            home-parcimonie-configuration-parcimonie
            home-parcimonie-configuration-gnupg-already-torified?
            home-parcimonie-configuration-refresh-guix-keyrings?
            home-parcimonie-configuration-extra-content

            home-parcimonie-service-type))

(define raw-configuration-string? string?)

;; Configuration of 'gpg-agent'.
(define-configuration/no-serialization home-gpg-agent-configuration
  (gnupg
   (file-like gnupg)
   "The GnuPG package to use.")
  (pinentry-program
   (file-like (file-append pinentry "/bin/pinentry-curses"))
   "Pinentry program to use.  Pinentry is a small user interface that
@command{gpg-agent} delegates to anytime it needs user input for a passphrase
or @acronym{PIN, personal identification number} (@pxref{Top,,, pinentry,
Using the PIN-Entry}).")
  (ssh-support?
   (boolean #f)
   "Whether to enable @acronym{SSH, secure shell} support.  When true,
@command{gpg-agent} acts as a drop-in replacement for OpenSSH's
@command{ssh-agent} program, taking care of OpenSSH secret keys and directing
passphrase requests to the chosen Pinentry program.")
  (default-cache-ttl
    (integer 600)
    "Time a cache entry is valid, in seconds.")
  (max-cache-ttl
   (integer 7200)
   "Maximum time a cache entry is valid, in seconds.  After this time a cache
entry will be expired even if it has been accessed recently.")
  (default-cache-ttl-ssh
    (integer 1800)
    "Time a cache entry for SSH keys is valid, in seconds.")
  (max-cache-ttl-ssh
   (integer 7200)
   "Maximum time a cache entry for SSH keys is valid, in seconds.")
  (extra-content
   (raw-configuration-string "")
   "Raw content to add to the end of @file{~/.gnupg/gpg-agent.conf}."))

(define (home-gpg-agent-configuration-file config)
  "Return the @file{gpg-agent.conf} file for @var{config}."
  (match-record config <home-gpg-agent-configuration>
    (pinentry-program default-cache-ttl max-cache-ttl
                      default-cache-ttl-ssh max-cache-ttl-ssh
                      extra-content)
    (mixed-text-file "gpg-agent.conf"
                     "pinentry-program " pinentry-program "\n"
                     "default-cache-ttl "
                     (number->string default-cache-ttl) "\n"
                     "max-cache-ttl "
                     (number->string max-cache-ttl) "\n"
                     "default-cache-ttl-ssh "
                     (number->string default-cache-ttl-ssh) "\n"
                     "max-cache-ttl-ssh "
                     (number->string max-cache-ttl-ssh) "\n"
                     extra-content)))

(define (home-gpg-agent-shepherd-services config)
  "Return the possibly-empty list of Shepherd services for @var{config}."
  (match-record config <home-gpg-agent-configuration>
    (gnupg ssh-support?)
    ;; 'gpg-agent' is started on demand by GnuPG's programs, but it has to be
    ;; started explicitly when OpenSSH support is enabled (info "(gnupg) Agent
    ;; Options").
    (if ssh-support?
        (let ((endpoint (lambda (name socket)
                          #~(endpoint
                             (make-socket-address
                              AF_UNIX
                              (string-append %user-runtime-dir
                                             "/gnupg/" #$socket))
                             #:name #$name
                             #:socket-directory-permissions #o700))))
          (list (shepherd-service
                 (provision '(gpg-agent ssh-agent))
                 (modules '((shepherd support)))  ;for '%user-runtime-dir'
                 (start #~(make-systemd-constructor
                           (list #$(file-append gnupg "/bin/gpg-agent")
                                 "--supervised" "--enable-ssh-support")
                           (list #$(endpoint "ssh" "S.gpg-agent.ssh")
                                 #$(endpoint "browser" "S.gpg-agent.browser")
                                 #$(endpoint "extra" "S.gpg-agent.extra")
                                 ;; #$(endpoint "scdaemon" "S.scdaemon")
                                 #$(endpoint "std" "S.gpg-agent"))))
                 (stop #~(make-systemd-destructor))
                 (documentation "Start 'gpg-agent', the GnuPG passphrase
agent, with support for handling OpenSSH material."))))
        '())))

(define (home-gpg-agent-files config)
  `((".gnupg/gpg-agent.conf" ,(home-gpg-agent-configuration-file config))))

(define (home-gpg-agent-environment-variables config)
  "Return GnuPG environment variables needed for @var{config}."
  (if (home-gpg-agent-configuration-ssh-support? config)
      `(("SSH_AUTH_SOCK"
         . "$XDG_RUNTIME_DIR/gnupg/S.gpg-agent.ssh"))
      '()))

(define gpg-agent-activation
  (with-imported-modules (source-module-closure
                          '((gnu build activation)))
    #~(begin
        (use-modules (gnu build activation))

        ;; Make sure ~/.gnupg is #o700.
        (let* ((home (getenv "HOME"))
               (dot-ssh (string-append home "/.gnupg")))
          (mkdir-p/perms dot-ssh (getpw (getuid)) #o700)))))

(define home-gpg-agent-service-type
  (service-type
   (name 'home-gpg-agent)
   (extensions
    (list (service-extension home-files-service-type
                             home-gpg-agent-files)
          (service-extension home-shepherd-service-type
                             home-gpg-agent-shepherd-services)
          (service-extension home-activation-service-type
                             (const gpg-agent-activation))
          (service-extension home-environment-variables-service-type
                             home-gpg-agent-environment-variables)))
   (default-value (home-gpg-agent-configuration))
   (description
    "Configure GnuPG's agent, @command{gpg-agent}, which is responsible for
managing OpenPGP and optionally SSH private keys.  When SSH support is
enabled, @command{gpg-agent} acts as a drop-in replacement for OpenSSH's
@command{ssh-agent}.")))

(define-configuration/no-serialization home-parcimonie-configuration
  (parcimonie
    (file-like parcimonie)
    "The parcimonie package to use.")
  (verbose?
    (boolean #f)
    "Provide extra output to the log file.")
  (gnupg-already-torified?
    (boolean #f)
    "GnuPG is already configured to use tor and parcimonie won't attempt to use
tor directly.")
  (refresh-guix-keyrings?
    (boolean #f)
    "Also refresh any Guix keyrings found in the XDG_CONFIG_DIR.")
  (extra-content
    (raw-configuration-string "")
    "Raw content to add to the parcimonie service."))

(define (home-parcimonie-shepherd-service config)
  "Return a user service to run parcimonie."
  (match-record config <home-parcimonie-configuration>
    (parcimonie verbose? gnupg-already-torified?
                refresh-guix-keyrings? extra-content)
    (let ((log-file #~(string-append %user-log-dir "/parcimonie.log")))
      (list (shepherd-service
              (provision '(parcimonie))
              (modules '((shepherd support)   ;for '%user-log-dir'
                         (guix build utils)
                         (srfi srfi-1)))
              (start #~(make-forkexec-constructor
                         (cons*
                           #$(file-append parcimonie "/bin/parcimonie")
                           #$@(if verbose?
                                '("--verbose")
                                '())
                           #$@(if gnupg-already-torified?
                                '("--gnupg_already_torified")
                                '())
                           #$@(if (not (string=? extra-content ""))
                                (list extra-content)
                                '())
                           #$@(if refresh-guix-keyrings?
                                '((append-map
                                    (lambda (item)
                                      (list (string-append "--gnupg_extra_args="
                                                           "--keyring=" item)))
                                    (find-files
                                      (string-append (getenv "XDG_CONFIG_HOME") "/guix")
                                      "^trustedkeys\\.kbx$")))
                                '((list))))
                         #:log-file #$log-file))
              (stop #~(make-kill-destructor))
              (respawn? #t)
              (documentation "Incrementally refresh gnupg keyring over Tor"))))))

(define home-parcimonie-service-type
  (service-type
   (name 'home-parcimonie)
   (extensions
    (list (service-extension home-shepherd-service-type
                             home-parcimonie-shepherd-service)))
   (default-value (home-parcimonie-configuration))
   (description
    "Incrementally refresh GnuPG keyrings over Tor.")))
g.scm (prosody-configuration) (opaque-prosody-configuration): Likewise. * gnu/services/monitoring.scm (zabbix-server-configuration) (zabbix-agent-configuration): Likewise. * gnu/services/networking.scm (opendht-configuration): Likewise. * gnu/services/pm.scm (tlp-configuration): Likewise. * gnu/services/telephony.scm (jami-configuration): Likewise. * gnu/services/virtualization.scm (libvirt-configuration) (qemu-guest-agent-configuration): Likewise. * gnu/services/vpn.scm (openvpn-client-configuration): Likewise. Tobias Geerinckx-Rice 2021-11-12services: Add qemu-guest-agent service....* gnu/services/virtualization.scm (<qemu-guest-agent-configuration>): New record. (qemu-guest-agent-shepherd-service): New procedure. (qemu-guest-agent-service-type): New variable. * doc/guix.texi (Virtualization Services): Document it. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Timotej Lazar 2021-09-04services: libvirt: Change unix-sock-group default....When accessing libvrtd remotely, polkit can't be used unless you are logged as root. Instead allow libvirt groups member access to the control socket. * gnu/services/virtualization.scm (libvirt-configuration) [unix-sock-group]: Change default from "root" to "libvirt". Brice Waegeneire 2021-09-04services: libvirt: Add qemu field....* gnu/services/virtualization.scm (libvirt-configuration): Add 'qemu' field. (libvirt-service-type): Replace 'qemu' package with the one specified in the service configuration. Brice Waegeneire 2021-08-30services: hurd-vm: Use the new 'targets' field of <bootloader-configuration>....* gnu/services/virtualization.scm (%hurd-vm-operating-system): Use 'targets' instead of 'target' for the 'bootloader-configuration' field. Ludovic Courtès 2021-08-29services: Remove i486 qemu target....The i486 target has been removed from qemu since at least 5.2.0. * gnu/services/virtualization.scm (%i486): Remove variable. (%qemu-platforms): Remove it. Efraim Flashner 2021-07-10services: qemu-binfmt: Preserve argv[0] by default....Previously, argv[0] would be replaced by the absolute file name of the executable. This could cause discrepancies, for example in the Coreutils test suite: <https://issues.guix.gnu.org/49485>. * gnu/services/virtualization.scm (<qemu-platform>)[flags]: Default to "FP". Ludovic Courtès 2021-03-15services/qemu-binfmt: Use the F flag and the static output of QEMU....Fixes <https://issues.guix.gnu.org/36117>. Before this change, the 'binfmt_misc' entries registered for QEMU would not be usable in container contexts outside of guix-daemon (without manually bind mounting file names). For example: $ docker run --rm arm32v7/debian true standard_init_linux.go:207: exec user process caused "no such file or directory" After this change, any container can make use of the QEMU binfmt_misc registrations, as their corresponding QEMU static binaries are fully pre-loaded by the kernel. * gnu/services/virtualization.scm (<qemu-platform>): Define using 'define-record-type*'. [flags]: New field, which defaults to "F" (fix binary). (%i386, %i486, %alpha, %arm, %armeb, %sparc, %sparc32plus, %ppc, %ppc64) (%ppc64le, %m68k, %mips, %mipsel, %mipsn32, %mipsn32el, %mips64, %mips64el) (%riscv32, %riscv64, %sh4, %sh4eb, %s390x, %aarch64, %hppa): Adjust. (qemu-binfmt-guix-chroot): Remove variable. (qemu-binfmt-service-type): Remove the qemu-binfmt-guix-chroot extension. * gnu/services/qemu-binfmt (qemu-platform->binfmt): Use the static output of QEMU. * doc/contributing.texi (Submitting Patches): Update doc. * doc/guix.texi (Virtualization Services): Update doc. Maxim Cournoyer 2021-01-16services: qemu-binfmt: 'guix-support?' defaults to #t....* gnu/services/virtualization.scm (qemu-binfmt-service-type)[guix-support?]: Change the default from #f to #t. * doc/guix.texi (Transparent Emulation with QEMU): Change the default of ‘guix-support?’ from #f to #t. Describe the implication of setting it to #f. Co-authored-by: Ludovic Courtès <ludo@gnu.org> Stefan 2021-01-14services: hurd-vm: Respect hurd-vm-configuration's disk-size....This is a follow-up to commit 859b362f81598830d7ff276b96a8724aee3c4db7. * gnu/services/virtualization.scm (hurd-vm-disk-image): Use diks-size from config to set image's size. Jan (janneke) Nieuwenhuizen 2020-12-07services: hurd-vm: Avoid circular dependency with (gnu system images hurd)....* gnu/services/virtualization.scm (hurd-vm-disk-image): Use 'lookup-image-type-by-name' instead of referring to 'hurd-disk-image' from (gnu system images hurd). Ludovic Courtès 2020-10-25services: guix: Make /etc/guix/acl really declarative by default....Fixes <https://bugs.gnu.org/39819>. Reported by Maxim Cournoyer <maxim.cournoyer@gmail.com>. * gnu/services/base.scm (substitute-key-authorization): Symlink DEFAULT-ACL to /etc/guix/acl unconditionally. Add code to optionally back up /etc/guix/acl if it was possibly modified by hand. * doc/guix.texi (Base Services): Clarify the effect of setting 'authorize-keys?' to true. Mention the backup. Give an example showing how to authorize substitutes from another server. Ludovic Courtès 2020-10-09services: hurd-vm: Add 'gdb-minimal' to the default OS....* gnu/services/virtualization.scm (%hurd-vm-operating-system)[packages]: New field. Ludovic Courtès 2020-09-30services: hurd-vm: Add childhurd user to kvm group....This is a follow-up to commit d692ebf98077d6b651d426aba92bf2a38599c4dc. * gnu/services/virtualization.scm (%hurd-vm-accounts)[supplementary-groups]: Add ’kvm’. * gnu/services/virtualization.scm (hurd-vm-shepherd-service): Use #:group "kvm" Jan (janneke) Nieuwenhuizen 2020-09-30services: virtualization: Use a compressed qcow2 hurd disk-image....* gnu/services/virtualization.scm (hurd-vm-disk-image): Use 'compressed-qcow2 format. Mathieu Othacehe 2020-09-29services: secret-service: Add initial client/server handshake....This allows the client running on the host to know when it's actually connect to the server running in the guest. Failing that, the client would connect right away to QEMU and send secrets even though the server is not running yet in the guest, which is unreliable. * gnu/build/secret-service.scm (secret-service-send-secrets): Add #:handshake-timeout. Read from SOCK an initial message from the server. Return #f on error. (secret-service-receive-secrets): Send 'secret-service-server' message to the client. Close SOCK upon timeout. * gnu/services/virtualization.scm (hurd-vm-shepherd-service): 'start' method returns #f when 'secret-service-send-secrets' returns #f. Ludovic Courtès 2020-09-29services: secret-service: Move instance last in the list of services....* gnu/services/virtualization.scm (secret-service-operating-system): Add the SECRET-SERVICE-TYPE instance to the end of the list. Ludovic Courtès 2020-09-29services: hurd-vm: Pass "-no-reboot" when spawning the Hurd VM....* gnu/services/virtualization.scm (hurd-vm-shepherd-service)[vm-command]: Add "--no-reboot". Ludovic Courtès 2020-09-29services: hurd-vm: Initialize the guest's SSH/Guix keys at activation time....* gnu/services/virtualization.scm (initialize-hurd-vm-substitutes) (hurd-vm-activation): New procedures. (hurd-vm-service-type)[extensions]: Add ACTIVATION-SERVICE-TYPE extension. * doc/guix.texi (Transparent Emulation with QEMU): Mention GNU/Hurd. (The Hurd in a Virtual Machine): Explain which files are automatically installed and mention offloading. Ludovic Courtès 2020-09-29services: hurd-vm: Check whether /dev/kvm exists at run time....This change allows a childhurd to run within Guix System in a VM. * gnu/services/virtualization.scm (hurd-vm-shepherd-service)[vm-command]: Stage the 'file-exists?' call. Ludovic Courtès 2020-09-29services: childhurd: Tweak description....* gnu/services/virtualization.scm (hurd-vm-service-type)[description]: Mention "childhurd". Ludovic Courtès 2020-09-29services: hurd-vm: Run QEMU as an unprivileged user....Until qemu was running as "root", which is unnecessary. * gnu/services/virtualization.scm (%hurd-vm-accounts): New variable. (hurd-vm-service-type)[extensions]: Add ACCOUNT-SERVICE-TYPE extension. Ludovic Courtès 2020-09-02services: childhurd: Always include the secret-service....* gnu/services/virtualization.scm (secret-service-operating-system): New procedure. (hurd-vm-disk-image): Use it to ensure a Childhurd always includes the secret-service. (%hurd-vm-operating-system): Remove secret-service. Co-authored-by: Ludovic Courtès <ludo@gnu.org> Jan (janneke) Nieuwenhuizen 2020-09-01services: childhurd: Support installing secrets from the host....* gnu/services/virtualization.scm (%hurd-vm-operating-system): Add secret-service. (hurd-vm-shepherd-service): Use it to install secrets. * doc/guix.texi (The Hurd in a Virtual Machine): Document it. Jan (janneke) Nieuwenhuizen 2020-09-01services: Add secret-service-type....This adds a "secret-service" that can be added to a Childhurd VM to receive out-of-band secrets (keys) sent from the host. Co-authored-by: Ludovic Courtès <ludo@gnu.org> * gnu/services/virtualization.scm (secret-service-activation): New procedure. (secret-service-type): New variable. * gnu/build/secret-service.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. Jan (janneke) Nieuwenhuizen 2020-06-28services: virtualization: Export hurd-vm-configuration accessors....* gnu/services/virtualization.scm (hurd-vm-id, hurd-vm-options): Rename export to ... (hurd-vm-configuration-id, hurd-vm-configuration-options): ... these correct accessor names. (hurd-vm-configuration?, hurd-vm-configuration-os, hurd-vm-configuration-qemu, hurd-vm-configuration-image, hurd-vm-configuration-disk-size, hurd-vm-configuration-memory-size, hurd-vm-configuration-options, hurd-vm-configuration-id, hurd-vm-configuration-net-options): Export record predicate and accessors. Jan (janneke) Nieuwenhuizen 2020-06-25services: childhurd: Adjust for hurd-disk-image move....This is a follow-up to commit b904b59ce592c89dfb4675a8c06757afed6738a0. * gnu/services/virtualization.scm: Import (gnu system images hurd). Marius Bakke 2020-06-21services: childhurd: Support more than one instance....* gnu/services/virtualization.scm (<hurd-vm-configuration>)[options]: Remove "--hda" option. [id,net-options]: New fields. (hurd-vm-net-options): New procedure. Parameterize port forwarding with ID. * gnu/services/virtualization.scm (hurd-vm-shepherd-service): Use them. Parameterize provision with ID, if set. Hardcode "--hda" option for image. * doc/guix.texi (Virtualization Services): Document new fields. Update for hardcoding of "--hda". Jan (janneke) Nieuwenhuizen 2020-06-14services: Add 'hurd-vm service-type'....* gnu/services/virtualization.scm (hurd-vm-shepherd-service, hurd-vm-disk-image): New procedures. (%hurd-vm-operating-system, hurd-vm-service-type): New variables. (<hurd-vm-configuration>): New record type. * doc/guix.texi (Virtualization Services): Document it. * gnu/services/shepherd.scm (scm->go): Use let-system, remove FIXME. Fixes fixes cross-building of shepherd modules for the Hurd image. Jan (janneke) Nieuwenhuizen 2020-04-12services: libvirt-configuration: Fix grammar of "allows to select" to "allows...selecting". * gnu/services/virtualization (libvirt-configuration): Fix grammar. Vagrant Cascadian 2020-02-01services: virtualization: Add riscv32 and riscv64 to qemu platforms....* gnu/services/virtualization (%riscv32): New variable. (%riscv64): New variable. (%qemu-platforms): Add riscv32 and riscv64. Vagrant Cascadian