From d082312ef7adfea69c79d30ef947817b39832161 Mon Sep 17 00:00:00 2001 From: Tomas Volf Date: Thu, 11 Jan 2024 18:35:39 +0100 Subject: mapped-devices: Allow unlocking by a key file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Requiring the user to input their password in order to unlock a device is not always reasonable, so having an option to unlock the device using a key file is a nice quality of life change. * gnu/system/mapped-devices.scm (open-luks-device): Add #:key-file argument. (luks-device-mapping-with-options): New procedure. * doc/guix.texi (Mapped Devices): Describe the new procedure. Change-Id: I1de4e045f8c2c11f9a94f1656e839c785b0c11c4 Signed-off-by: Ludovic Courtès --- doc/guix.texi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 811edd0bf7..c216d1b4a6 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -123,6 +123,7 @@ Copyright @copyright{} 2023 Foundation Devices, Inc.@* Copyright @copyright{} 2023 Thomas Ieong@* Copyright @copyright{} 2023 Saku Laesvuori@* Copyright @copyright{} 2023 Graham James Addis@* +Copyright @copyright{} 2023 Tomas Volf@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -17992,6 +17993,30 @@ command from the package with the same name. It relies on the @code{dm-crypt} Linux kernel module. @end defvar +@deffn {Procedure} luks-device-mapping-with-options [#:key-file] +Return a @code{luks-device-mapping} object, which defines LUKS block +device encryption using the @command{cryptsetup} command from the +package with the same name. It relies on the @code{dm-crypt} Linux +kernel module. + +If @code{key-file} is provided, unlocking is first attempted using that +key file. This has an advantage of not requiring a password entry, so +it can be used (for example) to unlock RAID arrays automatically on +boot. If key file unlock fails, password unlock is attempted as well. +Key file is not stored in the store and needs to be available at the +given location at the time of the unlock attempt. + +@lisp +;; Following definition would be equivalent to running: +;; cryptsetup open --key-file /crypto.key /dev/sdb1 data +(mapped-device + (source "/dev/sdb1) + (target "data) + (type (luks-device-mapping-with-options + #:key-file "/crypto.key"))) +@end lisp +@end deffn + @defvar raid-device-mapping This defines a RAID device, which is assembled using the @code{mdadm} command from the package with the same name. It requires a Linux kernel -- cgit v1.2.3 From 086850e5b2b4a1744565fe83624d256524b64a49 Mon Sep 17 00:00:00 2001 From: Tomas Volf Date: Thu, 11 Jan 2024 18:35:40 +0100 Subject: bootloader: grub: Add support for loading an additional initrd. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be able to provide decryption keys for the LUKS device, they need to be available in the initial ram disk. However they cannot be stored inside the usual initrd, since it is stored in the store and being a world-readable (as files in the store are) is not a desired property for a initrd containing decryption keys. This commit adds an option to load additional initrd during the boot, one that is not stored inside the store and therefore can contain secrets. Since only grub supports encrypted /boot, only grub is modified to use the extra-initrd. There is no use case for the other bootloaders. * doc/guix.texi (Bootloader Configuration): Describe the new extra-initrd field. * gnu/bootloader.scm (): Add extra-initrd field. * gnu/bootloader/grub.scm (make-grub-configuration): Use the extra-initrd field. Signed-off-by: Ludovic Courtès Change-Id: I995989bb623bb594ccdafbf4a1a6de941bd4189f --- doc/guix.texi | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ gnu/bootloader.scm | 6 +++++- gnu/bootloader/grub.scm | 7 +++++-- 3 files changed, 59 insertions(+), 3 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index c216d1b4a6..a66005ee9d 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -41070,6 +41070,55 @@ This option in enabled by default. In some cases involving the @code{u-boot} bootloader, where the device tree has already been loaded in RAM, it can be handy to disable the option by setting it to @code{#f}. + +@item @code{extra-initrd} (default: @code{#f}) +File name of an additional initrd to load during the boot. It may or +may not point to a file in the store, but the main use case is for +out-of-store files containing secrets. + +In order to be able to provide decryption keys for the LUKS device, they +need to be available in the initial ram disk. However they cannot be +stored inside the usual initrd, since it is stored in the store and +being a world-readable (as files in the store are) is not a desired +property for a initrd containing decryption keys. You can therefore use +this field to instruct GRUB to also load a manually created initrd not +stored in the store. + +For any use case not involving secrets, you should use regular initrd +(@pxref{operating-system Reference, @code{initrd}}) instead. + +Suitable image can be created for example like this: + +@example +echo /key-file.bin | cpio -oH newc >/key-file.cpio +chmod 0000 /key-file.cpio +@end example + +After it is created, you can use it in this manner: + +@lisp +;; Operating system with encrypted boot partition +(operating-system + ... + (bootloader (bootloader-configuration + (bootloader grub-efi-bootloader) + (targets '("/boot/efi")) + ;; Load the initrd with a key file + (extra-initrd "/key-file.cpio"))) + (mapped-devices + (list (mapped-device + (source (uuid "12345678-1234-1234-1234-123456789abc")) + (target "my-root") + (type (luks-device-mapping-with-options + ;; And use it to unlock the root device + #:key-file "/key-file.bin")))))) +@end lisp + +Be careful when using this option, since pointing to a file that is not +readable by the grub while booting will cause the boot to fail and +require a manual edit of the initrd line in the grub menu. + +Currently only supported by GRUB. @end table @end deftp diff --git a/gnu/bootloader.scm b/gnu/bootloader.scm index ba06de7618..f32e90e79d 100644 --- a/gnu/bootloader.scm +++ b/gnu/bootloader.scm @@ -6,6 +6,7 @@ ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen ;;; Copyright © 2022 Josselin Poiret ;;; Copyright © 2022 Reza Alizadeh Majd +;;; Copyright © 2024 Tomas Volf <~@wolfsden.cz> ;;; ;;; This file is part of GNU Guix. ;;; @@ -77,6 +78,7 @@ (define-module (gnu bootloader) bootloader-configuration-serial-unit bootloader-configuration-serial-speed bootloader-configuration-device-tree-support? + bootloader-configuration-extra-initrd %bootloaders lookup-bootloader-by-name @@ -279,7 +281,9 @@ (define-record-type* (serial-speed bootloader-configuration-serial-speed (default #f)) ;integer | #f (device-tree-support? bootloader-configuration-device-tree-support? - (default #t))) ;boolean + (default #t)) ;boolean + (extra-initrd bootloader-configuration-extra-initrd + (default #f))) ;string | #f (define-deprecated (bootloader-configuration-target config) bootloader-configuration-targets diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm index 5f3fcd7074..2723eda5f4 100644 --- a/gnu/bootloader/grub.scm +++ b/gnu/bootloader/grub.scm @@ -9,6 +9,7 @@ ;;; Copyright © 2020 Stefan ;;; Copyright © 2022 Karl Hallsby ;;; Copyright © 2022 Denis 'GNUtoo' Carikli +;;; Copyright © 2024 Tomas Volf <~@wolfsden.cz> ;;; ;;; This file is part of GNU Guix. ;;; @@ -386,7 +387,8 @@ (define (menu-entry->gexp entry) store-directory-prefix)) (initrd (normalize-file (menu-entry-initrd entry) device-mount-point - store-directory-prefix))) + store-directory-prefix)) + (extra-initrd (bootloader-configuration-extra-initrd config))) ;; Here DEVICE is the store and DEVICE-MOUNT-POINT is its mount point. ;; Use the right file names for LINUX and INITRD in case ;; DEVICE-MOUNT-POINT is not "/", meaning that the store is on a @@ -397,11 +399,12 @@ (define (menu-entry->gexp entry) #~(format port "menuentry ~s { ~a linux ~a ~a - initrd ~a + initrd ~a ~a }~%" #$label #$(grub-root-search device linux) #$linux (string-join (list #$@arguments)) + (or #$extra-initrd "") #$initrd))) (multiboot-kernel (let* ((kernel (menu-entry-multiboot-kernel entry)) -- cgit v1.2.3 From cb3f833aaa5326e653b128bfd7b13d553f7c2a47 Mon Sep 17 00:00:00 2001 From: Efraim Flashner Date: Mon, 15 Jan 2024 12:15:46 +0200 Subject: doc: Fix mistakes in the manual. Recommended by Christian Miller. * doc/guix.texi (Packages with Multiple Outputs): Replace 'a packages' with 'a package'. (Invoking guix time-machine): Don't assume knowledge and give an explicit link to Back to the Future. (Invoking guix pack): Remove doubled word. (Build Systems): Same. (Debugging Build Failures): 'inspect' is not a command to be run. (Invoking guix import): Remove doubled word. (Invoking guix size): Remove stray word. (Invoking guix processes): Replace 'guix environment' with 'guix shell'. (Base Services): Add missing word. (Networking Setup): Adjust a/an usage. (Networking Services): Remove stray symbol. Add space between two words. (Desktop Services): Remove stray symbol from example. (Database Services): Document default postgresql version. (Web Services): Adjust indentation. (Audio Services): Add missing newline. (Miscellaneous Services): Switch 'get' to 'gets'. (Bootloader Configuration): Remove stray symbol. (Secure Shell): Remove marks around accepted values. (Installing Debugging Files): Replace 'is' with 'it'. (Full-Source Bootstrap): Remove doubled word. (Preparing to Use the Bootstrap Binaries): Same. Change-Id: Ifbf2677dff7642c6531384145363d7611286e48b --- doc/guix.texi | 64 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index a66005ee9d..ac17f91f7d 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -4355,7 +4355,7 @@ There are several such multiple-output packages in the GNU distribution. Other conventional output names include @code{lib} for libraries and possibly header files, @code{bin} for stand-alone programs, and @code{debug} for debugging information (@pxref{Installing Debugging -Files}). The outputs of a packages are listed in the third column of +Files}). The outputs of a package are listed in the third column of the output of @command{guix package --list-available} (@pxref{Invoking guix package}). @@ -5003,7 +5003,8 @@ environment} command to spawn an environment in a container running @command{guile} (@command{guix environment} has since been subsumed by @command{guix shell}; @pxref{Invoking guix shell}). It's like driving a DeLorean@footnote{If you don't know what a DeLorean is, consider -traveling back to the 1980's.}! The first @command{guix time-machine} +traveling back to the 1980's. (@uref{https://www.imdb.com/title/tt0088763/, +Back to the Future (1985)})}! The first @command{guix time-machine} invocation can be expensive: it may have to download or even build a large number of packages; the result is cached though and subsequent commands targeting the same commit are almost instantaneous. @@ -7162,7 +7163,7 @@ What if the recipient of your pack does not have root privileges on their machine, and thus cannot unpack it in the root file system? In that case, you will want to use the @option{--relocatable} option (see below). This option produces @dfn{relocatable binaries}, meaning they -they can be placed anywhere in the file system hierarchy: in the example +can be placed anywhere in the file system hierarchy: in the example above, users can unpack your tarball in their home directory and directly run @file{./opt/gnu/bin/guile}. @@ -10194,8 +10195,8 @@ It also generates font metrics (i.e., @file{.tfm} files) out of Metafont files whenever possible. Likewise, it can also create TeX formats (i.e., @file{.fmt} files) listed in the @code{#:create-formats} argument, and generate a symbolic link from @file{bin/} directory to any -script located in located in @file{texmf-dist/scripts/}, provided its -file name is listed in @code{#:link-scripts} argument. +script located in @file{texmf-dist/scripts/}, provided its file name is +listed in @code{#:link-scripts} argument. The build system adds @code{texlive-bin} from @code{(gnu packages tex)} to the native inputs. It can be overridden with the @@ -13916,8 +13917,8 @@ happen because the daemon runs builds in containers where, unlike in our environment above, network access is missing, @file{/bin/sh} does not exist, etc. (@pxref{Build Environment Setup}). -In such cases, you may need to run inspect the build process from within -a container similar to the one the build daemon creates: +In such cases, you may need to inspect the build process from within a +container similar to the one the build daemon creates: @example $ guix build -K foo @@ -14295,8 +14296,7 @@ should be checked closely. If Perl is available in the store, then the @code{corelist} utility will be used to filter core modules out of the list of dependencies. -The command command below imports metadata for the Acme::Boolean Perl -module: +The command below imports metadata for the Acme::Boolean Perl module: @example guix import cpan Acme::Boolean @@ -15689,7 +15689,7 @@ Coreutils}). When the given packages are @emph{not} in the store, @command{guix size} reports information based on the available substitutes -(@pxref{Substitutes}). This makes it possible it to profile disk usage of +(@pxref{Substitutes}). This makes it possible to profile the disk usage of store items that are not even on disk, only available remotely. You can also specify several package names: @@ -16793,7 +16793,7 @@ ChildCommand: guix offload x86_64-linux 7200 1 28800 @end example In this example we see that @command{guix-daemon} has three clients: -@command{guix environment}, @command{guix publish}, and the Cuirass continuous +@command{guix shell}, @command{guix publish}, and the Cuirass continuous integration tool; their process identifier (PID) is given by the @code{ClientPID} field. The @code{SessionPID} field gives the PID of the @command{guix-daemon} sub-process of this particular session. @@ -19956,7 +19956,7 @@ in users, including: Special variation of @code{pam-mount} to mount @code{XDG_RUNTIME_DIR} @end itemize -Here is example of switching from @code{mingetty-service-type} to +Here is an example of switching from @code{mingetty-service-type} to @code{greetd-service-type}, and how different terminals could be: @lisp @@ -20921,8 +20921,7 @@ package, which allows NetworkManager to manage VPNs @i{via} OpenVPN. This is the service type to run @url{https://01.org/connman,Connman}, a network connection manager. -Its value must be an -@code{connman-configuration} record as in this example: +Its value must be a @code{connman-configuration} record as in this example: @lisp (service connman-service-type @@ -21150,7 +21149,7 @@ The WiFi channel to use. @item @code{driver} (default: @code{"nl80211"}) The driver interface type. @code{"nl80211"} is used with all Linux mac80211 drivers. Use @code{"none"} if building hostapd as a standalone -RADIUS server that does # not control any wireless/wired driver. +RADIUS server that does not control any wireless/wired driver. @item @code{extra-settings} (default: @code{""}) Extra settings to append as-is to the hostapd configuration file. See @@ -22412,7 +22411,7 @@ private keys in it}. See the output of @code{yggdrasil -genconf} for a quick overview of valid keys and their default values. @item @code{autoconf?} (default: @code{#f}) -Whether to use automatic mode. Enabling it makes Yggdrasil use adynamic IP +Whether to use automatic mode. Enabling it makes Yggdrasil use a dynamic IP and peer with IPv6 neighbors. @item @code{log-level} (default: @code{'info}) @@ -24926,7 +24925,7 @@ List of possible UUIDs: @code{671b10b5-42c0-4696-9227-eb28d1b049d6}: BlueZ Experimental Simultaneous Central and Peripheral, @item -@code{"15c0a148-c273-11ea-b3de-0242ac130004}: BlueZ Experimental LL privacy, +@code{15c0a148-c273-11ea-b3de-0242ac130004}: BlueZ Experimental LL privacy, @item @code{330859bc-7506-492d-9370-9a6f0614037f}: BlueZ Experimental Bluetooth Quality Report, @@ -25588,7 +25587,7 @@ Data type representing the configuration for the @code{postgresql-service-type}. @table @asis -@item @code{postgresql} +@item @code{postgresql} (default: @code{postgresql-10}) PostgreSQL package to use for the service. @item @code{port} (default: @code{5432}) @@ -31071,7 +31070,7 @@ the configuration. (httpd-virtualhost "*:80" (list (string-join '("ServerName www.example.com" - "DocumentRoot /srv/http/www.example.com") + "DocumentRoot /srv/http/www.example.com") "\n"))))) @end lisp @end defvar @@ -35149,6 +35148,7 @@ Owner of the @command{mympd} process. The default @code{%mympd-user} is a system user with the name ``mympd'', who is a part of the group @var{group} (see below). + @item @code{group} (default: @code{%mympd-group}) (type: user-group) Owner group of the @command{mympd} process. @@ -40258,7 +40258,7 @@ Backend to use to detect changes in the @code{log-path}. The default is @file{/etc/fail2ban/jail.conf} file of the @code{fail2ban} package. @item @code{max-retry} (type: maybe-integer) -The number of failures before a host get banned (e.g. @code{(max-retry +The number of failures before a host gets banned (e.g. @code{(max-retry 5)}). @item @code{max-matches} (type: maybe-integer) @@ -41219,7 +41219,7 @@ Of course, these options can be combined: '("console=com0" "noide") @end lisp -+@item @code{multiboot-modules} (default: @code{'()}) +@item @code{multiboot-modules} (default: @code{'()}) The list of commands for loading Multiboot modules. For example: @lisp @@ -44638,19 +44638,19 @@ running on this machine, then it @emph{may} take this file into account: this is what @command{sshd} does by default, but be aware that it can also be configured to ignore it. -@item @code{add-keys-to-agent} (default: @code{``no''}) +@item @code{add-keys-to-agent} (default: @code{no}) This string specifies whether keys should be automatically added to a -running ssh-agent. If this option is set to @code{``yes''} and a key is +running ssh-agent. If this option is set to @code{yes} and a key is loaded from a file, the key and its passphrase are added to the agent with the default lifetime, as if by @code{ssh-add}. If this option is -set to @code{``ask''}, @code{ssh} will require confirmation. If this -option is set to @code{``confirm''}, each use of the key must be -confirmed. If this option is set to @code{``no''}, no keys are added to +set to @code{ask}, @code{ssh} will require confirmation. If this +option is set to @code{confirm}, each use of the key must be +confirmed. If this option is set to @code{no}, no keys are added to the agent. Alternately, this option may be specified as a time interval to specify the key's lifetime in @code{ssh-agent}, after which it will -automatically be removed. The argument must be @code{``no''}, -@code{``yes''}, @code{``confirm''} (optionally followed by a time -interval), @code{``ask''} or a time interval. +automatically be removed. The argument must be @code{no}, +@code{yes}, @code{confirm} (optionally followed by a time +interval), @code{ask} or a time interval. @end table @end deftp @@ -46726,7 +46726,7 @@ missing. @node Separate Debug Info @section Separate Debug Info -The problem with debugging information is that is takes up a fair amount +The problem with debugging information is that it takes up a fair amount of disk space. For example, debugging information for the GNU C Library weighs in at more than 60 MiB@. Thus, as a user, keeping all the debugging info of all the installed programs is usually not an option. @@ -47209,7 +47209,7 @@ traditional bootstrap of the rest of the Guix System. @c ./pre-inst-env guix graph -e '(@@ (gnu packages commencement) gcc-core-mesboot0)' | sed -re 's,((bootstrap-seeds|guile-bootstrap).*shape =) box,\1 ellipse,' > doc/images/gcc-core-mesboot0-graph.dot @image{images/gcc-core-mesboot0-graph,6in,,Dependency graph of gcc-core-mesboot0} -Work is ongoing to to bring these bootstraps to the @code{arm-linux} and +Work is ongoing to bring these bootstraps to the @code{arm-linux} and @code{aarch64-linux} architectures and to the Hurd. If you are interested, join us on @samp{#bootstrappable} on the Libera.Chat @@ -47380,7 +47380,7 @@ bootstrap GCC with a sequence of assemblers, interpreters, and compilers of increasing complexity, which could be built from source starting from a simple and auditable assembler. -Our first major achievement is the replacement of of GCC, the GNU C Library +Our first major achievement is the replacement of GCC, the GNU C Library and Binutils by MesCC-Tools (a simple hex linker and macro assembler) and Mes (@pxref{Top, GNU Mes Reference Manual,, mes, GNU Mes}, a Scheme interpreter and C compiler in Scheme). Neither MesCC-Tools nor Mes can be fully -- cgit v1.2.3 From 2a43692aa74a4428b908fd4e11b239c9eb2f6542 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 19 Jan 2024 14:54:40 +0100 Subject: guix: Add ork1-elf platform. * doc/guix.texi: Document or1k-elf platform. * guix/platforms/or1k.scm (or1k-elf): New variable. * Makefile.am (MODULES): Add guix/platforms/or1k.scm. Change-Id: I3f71a0fa97f1ebd2bbdbf6cd00a93b477a123648 --- Makefile.am | 1 + doc/guix.texi | 6 ++++++ guix/platforms/or1k.scm | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 guix/platforms/or1k.scm (limited to 'doc/guix.texi') diff --git a/Makefile.am b/Makefile.am index d3b9532c7a..bdc97498aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -140,6 +140,7 @@ MODULES = \ guix/platforms/arm.scm \ guix/platforms/avr.scm \ guix/platforms/mips.scm \ + guix/platforms/or1k.scm \ guix/platforms/powerpc.scm \ guix/platforms/riscv.scm \ guix/platforms/x86.scm \ diff --git a/doc/guix.texi b/doc/guix.texi index ac17f91f7d..df6ce91736 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -16903,6 +16903,7 @@ The available targets are: - i686-linux-gnu - i686-w64-mingw32 - mips64el-linux-gnu + - or1k-elf - powerpc-linux-gnu - powerpc64le-linux-gnu - riscv64-linux-gnu @@ -46167,6 +46168,11 @@ Platform targeting AVR CPUs without an operating system, with run-time support from AVR Libc. @end defvar +@defvar or1k-elf +Platform targeting OpenRISC 1000 CPU without an operating system and without a +C standard library. +@end defvar + @node System Images @chapter Creating System Images diff --git a/guix/platforms/or1k.scm b/guix/platforms/or1k.scm new file mode 100644 index 0000000000..bf983085c5 --- /dev/null +++ b/guix/platforms/or1k.scm @@ -0,0 +1,28 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2024 Foundation Devices, Inc. +;;; +;;; 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 . + +(define-module (guix platforms or1k) + #:use-module (guix platform) + #:use-module (guix records) + #:export (or1k-elf)) + +(define or1k-elf + (platform + (target "or1k-elf") + (system #f) + (glibc-dynamic-linker #f))) -- cgit v1.2.3 From 1bdeec5d66cfeea3a5fc5d69690dd32cb32ee104 Mon Sep 17 00:00:00 2001 From: muradm Date: Sun, 17 Dec 2023 15:49:21 +0300 Subject: services: connman: Add 'connman-general-configuration'. Currently connman has no main.conf as specified in 'man 5 connman.conf' which would allow setting NetworkInterfaceBalcklist and other useful options. This patch adds connman-general-configuration, serializes it and passes to connmad with --config= flag. All configuration fields are 'maybe-*' deliberately, to not disturb current users and not require supporting configuration changes for connmand. * gnu/services/networking.scm (): New configuration record to represent main.conf for connmand. ()[general-configuration]: New field. (connman-shepherd-service): Honor it. *doc/guix.texi (Networking Services): Add generated configuration. Change-Id: I5d78f49e8b2d5e0b3cbd7b8b604e8a254b6397e8 Signed-off-by: Maxim Cournoyer Modified-by: Maxim Cournoyer --- doc/guix.texi | 205 +++++++++++++++++++++++++++++++++++ gnu/services/networking.scm | 255 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 457 insertions(+), 3 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index df6ce91736..110853b98c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -20949,9 +20949,214 @@ networks. @item @code{disable-vpn?} (default: @code{#f}) When true, disable connman's vpn plugin. +@item @code{general-configuration} (default: @code{(connman-general-configuration)}) +Configuration serialized to @file{main.conf} and passed as @option{--config} +to @command{connmand}. + @end table @end deftp +@c %start of fragment + +@deftp {Data Type} connman-general-configuration +Available @code{connman-general-configuration} fields are: + +@table @asis +@item @code{input-request-timeout} (type: maybe-number) +Set input request timeout. Default is 120 seconds. The request for +inputs like passphrase will timeout after certain amount of time. Use +this setting to increase the value in case of different user interface +designs. + +@item @code{browser-launch-timeout} (type: maybe-number) +Set browser launch timeout. Default is 300 seconds. The request for +launching a browser for portal pages will timeout after certain amount +of time. Use this setting to increase the value in case of different +user interface designs. + +@item @code{background-scanning?} (type: maybe-boolean) +Enable background scanning. Default is true. If wifi is disconnected, +the background scanning will follow a simple back off mechanism from 3s +up to 5 minutes. Then, it will stay in 5 minutes unless user +specifically asks for scanning through a D-Bus call. If so, the +mechanism will start again from 3s. This feature activates also the +background scanning while being connected, which is required for roaming +on wifi. When @code{background-scanning?} is false, ConnMan will not +perform any scan regardless of wifi is connected or not, unless it is +requested by the user through a D-Bus call. + +@item @code{use-gateways-as-timeservers?} (type: maybe-boolean) +Assume that service gateways also function as timeservers. Default is +false. + +@item @code{fallback-timeservers} (type: maybe-list) +List of Fallback timeservers. These timeservers are used for NTP sync +when there are no timeservers set by the user or by the service, and +when @code{use-gateways-as-timeservers?} is @code{#f}. These can +contain a mixed combination of fully qualified domain names, IPv4 and +IPv6 addresses. + +@item @code{fallback-nameservers} (type: maybe-list) +List of fallback nameservers appended to the list of nameservers given +by the service. The nameserver entries must be in numeric format, host +names are ignored. + +@item @code{default-auto-connect-technologies} (type: maybe-list) +List of technologies that are marked autoconnectable by default. The +default value for this entry when empty is @code{"ethernet"}, +@code{"wifi"}, @code{"cellular"}. Services that are automatically +connected must have been set up and saved to storage beforehand. + +@item @code{default-favourite-technologies} (type: maybe-list) +List of technologies that are marked favorite by default. The default +value for this entry when empty is @code{"ethernet"}. Connects to +services from this technology even if not setup and saved to storage. + +@item @code{always-connected-technologies} (type: maybe-list) +List of technologies which are always connected regardless of +preferred-technologies setting (@code{auto-connect?} @code{#t}). The +default value is empty and this feature is disabled unless explicitly +enabled. + +@item @code{preferred-technologies} (type: maybe-list) +List of preferred technologies from the most preferred one to the least +preferred one. Services of the listed technology type will be tried one +by one in the order given, until one of them gets connected or they are +all tried. A service of a preferred technology type in state 'ready' +will get the default route when compared to another preferred type +further down the list with state 'ready' or with a non-preferred type; a +service of a preferred technology type in state 'online' will get the +default route when compared to either a non-preferred type or a +preferred type further down in the list. + +@item @code{network-interface-blacklist} (type: maybe-list) +List of blacklisted network interfaces. Found interfaces will be +compared to the list and will not be handled by ConnMan, if their first +characters match any of the list entries. Default value is +@code{"vmnet"}, @code{"vboxnet"}, @code{"virbr"}, @code{"ifb"}. + +@item @code{allow-hostname-updates?} (type: maybe-boolean) +Allow ConnMan to change the system hostname. This can happen for +example if we receive DHCP hostname option. Default value is @code{#t}. + +@item @code{allow-domainname-updates?} (type: maybe-boolean) +Allow connman to change the system domainname. This can happen for +example if we receive DHCP domainname option. Default value is +@code{#t}. + +@item @code{single-connected-technology?} (type: maybe-boolean) +Keep only a single connected technology at any time. When a new service +is connected by the user or a better one is found according to +preferred-technologies, the new service is kept connected and all the +other previously connected services are disconnected. With this setting +it does not matter whether the previously connected services are in +'online' or 'ready' states, the newly connected service is the only one +that will be kept connected. A service connected by the user will be +used until going out of network coverage. With this setting enabled +applications will notice more network breaks than normal. Note this +options can't be used with VPNs. Default value is @code{#f}. + +@item @code{tethering-technologies} (type: maybe-list) +List of technologies that are allowed to enable tethering. The default +value is @code{"wifi"}, @code{"bluetooth"}, @code{"gadget"}. Only those +technologies listed here are used for tethering. If one wants to tether +ethernet, then add @code{"ethernet"} in the list. Note that if ethernet +tethering is enabled, then a DHCP server is started on all ethernet +interfaces. Tethered ethernet should never be connected to corporate or +home network as it will disrupt normal operation of these networks. Due +to this ethernet is not tethered by default. Do not activate ethernet +tethering unless you really know what you are doing. + +@item @code{persistent-tethering-mode?} (type: maybe-boolean) +Restore earlier tethering status when returning from offline mode, +re-enabling a technology, and after restarts and reboots. Default value +is @code{#f}. + +@item @code{enable-6to4?} (type: maybe-boolean) +Automatically enable anycast 6to4 if possible. This is not recommended, +as the use of 6to4 will generally lead to a severe degradation of +connection quality. See RFC6343. Default value is @code{#f} (as +recommended by RFC6343 section 4.1). + +@item @code{vendor-class-id} (type: maybe-string) +Set DHCP option 60 (Vendor Class ID) to the given string. This option +can be used by DHCP servers to identify specific clients without having +to rely on MAC address ranges, etc. + +@item @code{enable-online-check?} (type: maybe-boolean) +Enable or disable use of HTTP GET as an online status check. When a +service is in a READY state, and is selected as default, ConnMan will +issue an HTTP GET request to verify that end-to-end connectivity is +successful. Only then the service will be transitioned to ONLINE state. +If this setting is false, the default service will remain in READY +state. Default value is @code{#t}. + +@item @code{online-check-ipv4-url} (type: maybe-string) +IPv4 URL used during the online status check. Please refer to the +README for more detailed information. Default value is +@uref{http://ipv4.connman.net/online/status.html}. + +@item @code{online-check-ipv6-url} (type: maybe-string) +IPv6 URL used during the online status check. Please refer to the +README for more detailed information. Default value is +@uref{http://ipv6.connman.net/online/status.html}. + +@item @code{online-check-initial-interval} (type: maybe-number) +Range of intervals between two online check requests. Please refer to +the README for more detailed information. Default value is @samp{1}. + +@item @code{online-check-max-interval} (type: maybe-number) +Range of intervals between two online check requests. Please refer to +the README for more detailed information. Default value is @samp{1}. + +@item @code{enable-online-to-ready-transition?} (type: maybe-boolean) +WARNING: This is an experimental feature. In addition to +@code{enable-online-check} setting, enable or disable use of HTTP GET to +detect the loss of end-to-end connectivity. If this setting is +@code{#f}, when the default service transitions to ONLINE state, the +HTTP GET request is no more called until next cycle, initiated by a +transition of the default service to DISCONNECT state. If this setting +is @code{#t}, the HTTP GET request keeps being called to guarantee that +end-to-end connectivity is still successful. If not, the default +service will transition to READY state, enabling another service to +become the default one, in replacement. Default value is @code{#f}. + +@item @code{auto-connect-roaming-services?} (type: maybe-boolean) +Automatically connect roaming services. This is not recommended unless +you know you won't have any billing problem. Default value is +@code{#f}. + +@item @code{address-conflict-detection?} (type: maybe-boolean) +Enable or disable the implementation of IPv4 address conflict detection +according to RFC5227. ConnMan will send probe ARP packets to see if an +IPv4 address is already in use before assigning the address to an +interface. If an address conflict occurs for a statically configured +address, an IPv4LL address will be chosen instead (according to +RFC3927). If an address conflict occurs for an address offered via +DHCP, ConnMan sends a DHCP DECLINE once and for the second conflict +resorts to finding an IPv4LL address. Default value is @code{#f}. + +@item @code{localtime} (type: maybe-string) +Path to localtime file. Defaults to @file{/etc/localtime}. + +@item @code{regulatory-domain-follows-timezone?} (type: maybe-boolean) +Enable regulatory domain to be changed along timezone changes. With +this option set to true each time the timezone changes the first present +ISO3166 country code is read from +@file{/usr/share/zoneinfo/zone1970.tab} and set as regulatory domain +value. Default value is @code{#f}. + +@item @code{resolv-conf} (type: maybe-string) +Path to resolv.conf file. If the file does not exist, but intermediate +directories exist, it will be created. If this option is not set, it +tries to write into @file{/var/run/connman/resolv.conf} if it fails +(@file{/var/run/connman} does not exist or is not writeable). If you do +not want to update resolv.conf, you can set @file{/dev/null}. + +@end table + +@end deftp + @cindex WPA Supplicant @defvar wpa-supplicant-service-type This is the service type to run @url{https://w1.fi/wpa_supplicant/,WPA diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm index 7c114fa53c..495d049728 100644 --- a/gnu/services/networking.scm +++ b/gnu/services/networking.scm @@ -21,6 +21,7 @@ ;;; Copyright © 2022, 2023 Andrew Tropin ;;; Copyright © 2023 Declan Tsien ;;; Copyright © 2023 Bruno Victal +;;; Copyright © 2023 muradm ;;; ;;; This file is part of GNU Guix. ;;; @@ -78,6 +79,7 @@ (define-module (gnu services networking) #:use-module (srfi srfi-26) #:use-module (srfi srfi-43) #:use-module (ice-9 match) + #:use-module (ice-9 string-fun) #:use-module (json) #:re-export (static-networking-service static-networking-service-type) @@ -171,6 +173,8 @@ (define-module (gnu services networking) network-manager-configuration-vpn-plugins network-manager-service-type + connman-general-configuration + connman-general-configuration? connman-configuration connman-configuration? connman-configuration-connman @@ -1326,6 +1330,241 @@ (define network-manager-service-type ;;; Connman ;;; +(define (connman-general-configuration-field-name field-name) + (let* ((str->camel (lambda (s) + (string-concatenate + (map string-capitalize (string-split s #\-))))) + (str (if (symbol? field-name) + (str->camel (symbol->string field-name)) + field-name))) + (cond + ((string-suffix? "?" str) (connman-general-configuration-field-name + (string-drop-right str 1))) + ((string-contains str "RegulatoryDomain") (connman-general-configuration-field-name + (string-replace-substring str "RegulatoryDomain" "Regdom"))) + ((string-contains str "Url") (connman-general-configuration-field-name + (string-replace-substring str "Url" "URL"))) + ((string-contains str "Ip") (connman-general-configuration-field-name + (string-replace-substring str "Ip" "IP"))) + ((string-contains str "6To4") (connman-general-configuration-field-name + (string-replace-substring str "6To4" "6to4"))) + (#t str)))) + +(define (connman-general-configuration-serialize-string field-name value) + (let ((param (connman-general-configuration-field-name field-name))) + #~(string-append #$param " = " #$value "\n"))) + +(define (connman-general-configuration-serialize-number field-name value) + (connman-general-configuration-serialize-string + field-name (number->string value))) + +(define (connman-general-configuration-serialize-list field-name value) + (connman-general-configuration-serialize-string + field-name (string-join value ","))) + +(define (connman-general-configuration-serialize-boolean field-name value) + (connman-general-configuration-serialize-string + field-name (if value "true" "false"))) + +(define-maybe boolean (prefix connman-general-configuration-)) +(define-maybe number (prefix connman-general-configuration-)) +(define-maybe string (prefix connman-general-configuration-)) +(define-maybe list (prefix connman-general-configuration-)) + +(define-configuration connman-general-configuration + (input-request-timeout + maybe-number + "Set input request timeout. Default is 120 seconds. The request for inputs +like passphrase will timeout after certain amount of time. Use this setting to +increase the value in case of different user interface designs.") + (browser-launch-timeout + maybe-number + "Set browser launch timeout. Default is 300 seconds. The request for +launching a browser for portal pages will timeout after certain amount of +time. Use this setting to increase the value in case of different user +interface designs.") + (background-scanning? + maybe-boolean + "Enable background scanning. Default is true. If wifi is disconnected, the +background scanning will follow a simple back off mechanism from 3s up to 5 +minutes. Then, it will stay in 5 minutes unless user specifically asks for +scanning through a D-Bus call. If so, the mechanism will start again from +3s. This feature activates also the background scanning while being connected, +which is required for roaming on wifi. When @code{background-scanning?} is false, +ConnMan will not perform any scan regardless of wifi is connected or not, +unless it is requested by the user through a D-Bus call.") + (use-gateways-as-timeservers? + maybe-boolean + "Assume that service gateways also function as timeservers. Default is false.") + (fallback-timeservers + maybe-list + "List of Fallback timeservers. These timeservers are used for NTP sync +when there are no timeservers set by the user or by the service, and when +@code{use-gateways-as-timeservers?} is @code{#f}. These can contain a mixed +combination of fully qualified domain names, IPv4 and IPv6 addresses.") + (fallback-nameservers + maybe-list + "List of fallback nameservers appended to the list of nameservers given +by the service. The nameserver entries must be in numeric format, +host names are ignored.") + (default-auto-connect-technologies + maybe-list + "List of technologies that are marked autoconnectable by default. The +default value for this entry when empty is @code{\"ethernet\"}, @code{\"wifi\"}, +@code{\"cellular\"}. Services that are automatically connected must have been +set up and saved to storage beforehand.") + (default-favourite-technologies + maybe-list + "List of technologies that are marked favorite by default. The default +value for this entry when empty is @code{\"ethernet\"}. Connects to services +from this technology even if not setup and saved to storage.") + (always-connected-technologies + maybe-list + "List of technologies which are always connected regardless of +preferred-technologies setting (@code{auto-connect?} @code{#t}). The default +value is empty and this feature is disabled unless explicitly enabled.") + (preferred-technologies + maybe-list + "List of preferred technologies from the most preferred one to the least +preferred one. Services of the listed technology type will be tried one by +one in the order given, until one of them gets connected or they are all +tried. A service of a preferred technology type in state 'ready' will get +the default route when compared to another preferred type further down the +list with state 'ready' or with a non-preferred type; a service of a +preferred technology type in state 'online' will get the default route when +compared to either a non-preferred type or a preferred type further down +in the list.") + (network-interface-blacklist + maybe-list + "List of blacklisted network interfaces. Found interfaces will be +compared to the list and will not be handled by ConnMan, if their first +characters match any of the list entries. Default value is @code{\"vmnet\"}, +@code{\"vboxnet\"}, @code{\"virbr\"}, @code{\"ifb\"}.") + (allow-hostname-updates? + maybe-boolean + "Allow ConnMan to change the system hostname. This can happen for +example if we receive DHCP hostname option. Default value is @code{#t}.") + (allow-domainname-updates? + maybe-boolean + "Allow connman to change the system domainname. This can happen for +example if we receive DHCP domainname option. Default value is @code{#t}.") + (single-connected-technology? + maybe-boolean + "Keep only a single connected technology at any time. When a new +service is connected by the user or a better one is found according to +preferred-technologies, the new service is kept connected and all the +other previously connected services are disconnected. With this setting +it does not matter whether the previously connected services are +in 'online' or 'ready' states, the newly connected service is the only +one that will be kept connected. A service connected by the user will +be used until going out of network coverage. With this setting enabled +applications will notice more network breaks than normal. Note this +options can't be used with VPNs. Default value is @code{#f}.") + (tethering-technologies + maybe-list + "List of technologies that are allowed to enable tethering. The +default value is @code{\"wifi\"}, @code{\"bluetooth\"}, +@code{\"gadget\"}. Only those technologies listed here are used for +tethering. If one wants to tether ethernet, then add @code{\"ethernet\"} +in the list. Note that if ethernet tethering is enabled, then a DHCP +server is started on all ethernet interfaces. Tethered ethernet should +never be connected to corporate or home network as it will disrupt normal +operation of these networks. Due to this ethernet is not tethered by +default. Do not activate ethernet tethering unless you really know +what you are doing.") + (persistent-tethering-mode? + maybe-boolean + "Restore earlier tethering status when returning from offline mode, +re-enabling a technology, and after restarts and reboots. Default +value is @code{#f}.") + (enable-6to4? + maybe-boolean + "Automatically enable anycast 6to4 if possible. This is not +recommended, as the use of 6to4 will generally lead to a severe +degradation of connection quality. See RFC6343. Default value +is @code{#f} (as recommended by RFC6343 section 4.1).") + (vendor-class-id + maybe-string + "Set DHCP option 60 (Vendor Class ID) to the given string. This +option can be used by DHCP servers to identify specific clients +without having to rely on MAC address ranges, etc.") + (enable-online-check? + maybe-boolean + "Enable or disable use of HTTP GET as an online status check. When +a service is in a READY state, and is selected as default, ConnMan will +issue an HTTP GET request to verify that end-to-end connectivity is +successful. Only then the service will be transitioned to ONLINE +state. If this setting is false, the default service will remain +in READY state. Default value is @code{#t}.") + (online-check-ipv4-url + maybe-string + "IPv4 URL used during the online status check. Please refer to +the README for more detailed information. Default value is +@url{http://ipv4.connman.net/online/status.html}.") + (online-check-ipv6-url + maybe-string + "IPv6 URL used during the online status check. Please refer to +the README for more detailed information. Default value is +@url{http://ipv6.connman.net/online/status.html}.") + (online-check-initial-interval + maybe-number + "Range of intervals between two online check requests. Please +refer to the README for more detailed information. Default value +is @samp{1}.") + (online-check-max-interval + maybe-number + "Range of intervals between two online check requests. Please +refer to the README for more detailed information. Default value +is @samp{1}.") + (enable-online-to-ready-transition? + maybe-boolean + "WARNING: This is an experimental feature. In addition to +@code{enable-online-check} setting, enable or disable use of HTTP GET +to detect the loss of end-to-end connectivity. If this setting is +@code{#f}, when the default service transitions to ONLINE state, the +HTTP GET request is no more called until next cycle, initiated by a +transition of the default service to DISCONNECT state. If this +setting is @code{#t}, the HTTP GET request keeps being called to +guarantee that end-to-end connectivity is still successful. If not, +the default service will transition to READY state, enabling another +service to become the default one, in replacement. Default value +is @code{#f}.") + (auto-connect-roaming-services? + maybe-boolean + "Automatically connect roaming services. This is not recommended +unless you know you won't have any billing problem. Default value +is @code{#f}.") + (address-conflict-detection? + maybe-boolean + "Enable or disable the implementation of IPv4 address conflict +detection according to RFC5227. ConnMan will send probe ARP packets +to see if an IPv4 address is already in use before assigning the +address to an interface. If an address conflict occurs for a +statically configured address, an IPv4LL address will be chosen +instead (according to RFC3927). If an address conflict occurs for +an address offered via DHCP, ConnMan sends a DHCP DECLINE once +and for the second conflict resorts to finding an IPv4LL +address. Default value is @code{#f}.") + (localtime + maybe-string + "Path to localtime file. Defaults to @file{/etc/localtime}.") + (regulatory-domain-follows-timezone? + maybe-boolean + "Enable regulatory domain to be changed along timezone changes. +With this option set to true each time the timezone changes the first +present ISO3166 country code is read from +@file{/usr/share/zoneinfo/zone1970.tab} and set as regulatory domain +value. Default value is @code{#f}.") + (resolv-conf + maybe-string + "Path to resolv.conf file. If the file does not exist, but +intermediate directories exist, it will be created. If this option +is not set, it tries to write into @file{/var/run/connman/resolv.conf} +if it fails (@file{/var/run/connman} does not exist or is not +writeable). If you do not want to update resolv.conf, you can +set @file{/dev/null}.") + (prefix connman-general-configuration-)) + (define-record-type* connman-configuration make-connman-configuration connman-configuration? @@ -1337,7 +1576,9 @@ (define-record-type* (default #f)) (iwd? connman-configuration-iwd? (default #f) - (sanitize warn-iwd?-field-deprecation))) + (sanitize warn-iwd?-field-deprecation)) + (general-configuration connman-configuration-general-configuration + (default (connman-general-configuration)))) (define (connman-activation config) (let ((disable-vpn? (connman-configuration-disable-vpn? config))) @@ -1350,10 +1591,17 @@ (define (connman-activation config) (define (connman-shepherd-service config) (match-record config (connman shepherd-requirement - disable-vpn? iwd?) + disable-vpn? iwd? + general-configuration) (let ((iwd? (or iwd? ; TODO: deprecated field, remove later. (and shepherd-requirement - (memq 'iwd shepherd-requirement))))) + (memq 'iwd shepherd-requirement)))) + (config (mixed-text-file + "main.conf" + "[General]\n" + (serialize-configuration + general-configuration + connman-general-configuration-fields)))) (list (shepherd-service (documentation "Run Connman") (provision '(connman networking)) @@ -1365,6 +1613,7 @@ (define (connman-shepherd-service config) (start #~(make-forkexec-constructor (list (string-append #$connman "/sbin/connmand") + (string-append "--config=" #$config) "--nodaemon" "--nodnsproxy" #$@(if disable-vpn? '("--noplugin=vpn") '()) -- cgit v1.2.3 From 916fb5347ab8d441e92ec6bfb13f9e9fef524ff7 Mon Sep 17 00:00:00 2001 From: Romain GARBAGE Date: Mon, 22 Jan 2024 11:32:55 +0100 Subject: guix: download: Add support for git repositories. * guix/scripts/download.scm (git-download-to-store*): Add new variable. (copy-recursively-without-dot-git): New variable. (git-download-to-file): Add new variable. (show-help): Add 'git', 'commit', 'branch' and 'recursive'options help message. (%default-options): Add default value for 'git-reference' and 'recursive' options. (%options): Add 'git', 'commit', 'branch' and 'recursive' command line options. (guix-download) [hash]: Compute hash with 'file-hash*' instead of 'port-hash' from (gcrypt hash) module. This allows us to compute hashes for directories. * doc/guix.texi (Invoking guix-download): Add @item entries for `git', `commit', `branch' and `recursive' options. Add a paragraph in the introduction. * tests/guix-download.sh: New tests. Move variables and trap definition to the top of the file. Change-Id: Ic2c428dca4cfcb0d4714ed361a4c46609339140a Signed-off-by: Maxim Cournoyer Reviewed-by: Maxim Cournoyer --- doc/guix.texi | 23 +++++++ guix/scripts/download.scm | 167 +++++++++++++++++++++++++++++++++++++++++++--- tests/guix-download.sh | 45 ++++++++++++- 3 files changed, 222 insertions(+), 13 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 110853b98c..a6187690bb 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -14021,6 +14021,9 @@ the certificates of X.509 authorities from the directory pointed to by the @env{SSL_CERT_DIR} environment variable (@pxref{X.509 Certificates}), unless @option{--no-check-certificate} is used. +Alternatively, @command{guix download} can also retrieve a Git +repository, possibly a specific commit, tag, or branch. + The following options are available: @table @code @@ -14045,6 +14048,26 @@ URL, which makes you vulnerable to ``man-in-the-middle'' attacks. @itemx -o @var{file} Save the downloaded file to @var{file} instead of adding it to the store. + +@item --git +@itemx -g +Checkout the Git repository at the latest commit on the default branch. + +@item --commit=@var{commit-or-tag} +Checkout the Git repository at @var{commit-or-tag}. + +@var{commit-or-tag} can be either a tag or a commit defined in the Git +repository. + +@item --branch=@var{branch} +Checkout the Git repository at @var{branch}. + +The repository will be checked out at the latest commit of @var{branch}, +which must be a valid branch of the Git repository. + +@item --recursive +@itemx -r +Recursively clone the Git repository. @end table @node Invoking guix hash diff --git a/guix/scripts/download.scm b/guix/scripts/download.scm index 19052d5652..de68e6f328 100644 --- a/guix/scripts/download.scm +++ b/guix/scripts/download.scm @@ -22,17 +22,24 @@ (define-module (guix scripts download) #:use-module (guix scripts) #:use-module (guix store) #:use-module (gcrypt hash) + #:use-module (guix hash) #:use-module (guix base16) #:use-module (guix base32) #:autoload (guix base64) (base64-encode) #:use-module ((guix download) #:hide (url-fetch)) + #:use-module ((guix git) + #:select (latest-repository-commit + update-cached-checkout + with-git-error-handling)) #:use-module ((guix build download) #:select (url-fetch)) + #:use-module (guix build utils) #:use-module ((guix progress) #:select (current-terminal-columns)) #:use-module ((guix build syscalls) #:select (terminal-columns)) #:use-module (web uri) + #:use-module (ice-9 ftw) #:use-module (ice-9 match) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) @@ -54,6 +61,57 @@ (define (download-to-file url file) (url-fetch url file #:mirrors %mirrors))) file)) +;; This is a simplified version of 'copy-recursively'. +;; It allows us to filter out the ".git" subfolder. +;; TODO: Remove when 'copy-recursively' supports '#:select?'. +(define (copy-recursively-without-dot-git source destination) + (define strip-source + (let ((len (string-length source))) + (lambda (file) + (substring file len)))) + + (file-system-fold (lambda (file stat result) ; enter? + (not (string-suffix? "/.git" file))) + (lambda (file stat result) ; leaf + (let ((dest (string-append destination + (strip-source file)))) + (case (stat:type stat) + ((symlink) + (let ((target (readlink file))) + (symlink target dest))) + (else + (copy-file file dest))))) + (lambda (dir stat result) ; down + (let ((target (string-append destination + (strip-source dir)))) + (mkdir-p target))) + (const #t) ; up + (const #t) ; skip + (lambda (file stat errno result) + (format (current-error-port) "i/o error: ~a: ~a~%" + file (strerror errno)) + #f) + #t + source)) + +(define (git-download-to-file url file reference recursive?) + "Download the git repo at URL to file, checked out at REFERENCE. +REFERENCE must be a pair argument as understood by 'latest-repository-commit'. +Return FILE." + ;; 'libgit2' doesn't support the URL format generated by 'uri->string' so + ;; we have to do a little fixup. Dropping completely the 'file:' protocol + ;; part gives better performance. + (let ((url (cond ((string-prefix? "file://" url) + (string-drop url (string-length "file://"))) + ((string-prefix? "file:" url) + (string-drop url (string-length "file:"))) + (else url)))) + (copy-recursively-without-dot-git + (with-git-error-handling + (update-cached-checkout url #:ref reference #:recursive? recursive?)) + file)) + file) + (define (ensure-valid-store-file-name name) "Replace any character not allowed in a store name by an underscore." @@ -67,17 +125,46 @@ (define valid name)) -(define* (download-to-store* url #:key (verify-certificate? #t)) +(define* (download-to-store* url + #:key (verify-certificate? #t) + #:allow-other-keys) (with-store store (download-to-store store url (ensure-valid-store-file-name (basename url)) #:verify-certificate? verify-certificate?))) +(define* (git-download-to-store* url + reference + recursive? + #:key (verify-certificate? #t)) + "Download the git repository at URL to the store, checked out at REFERENCE. +URL must specify a protocol (i.e https:// or file://), REFERENCE must be a +pair argument as understood by 'latest-repository-commit'." + ;; Ensure the URL string is properly formatted when using the 'file' + ;; protocol: URL is generated using 'uri->string', which returns + ;; "file:/path/to/file" instead of "file:///path/to/file", which in turn + ;; makes 'git-download-to-store' fail. + (let* ((file? (string-prefix? "file:" url)) + (url (if (and file? + (not (string-prefix? "file:///" url))) + (string-append "file://" + (string-drop url (string-length "file:"))) + url))) + (with-store store + ;; TODO: Verify certificate support and deactivation. + (with-git-error-handling + (latest-repository-commit store + url + #:recursive? recursive? + #:ref reference))))) + (define %default-options ;; Alist of default option values. `((format . ,bytevector->nix-base32-string) (hash-algorithm . ,(hash-algorithm sha256)) (verify-certificate? . #t) + (git-reference . #f) + (recursive? . #f) (download-proc . ,download-to-store*))) (define (show-help) @@ -97,6 +184,19 @@ (define (show-help) do not validate the certificate of HTTPS servers ")) (format #t (G_ " -o, --output=FILE download to FILE")) + (format #t (G_ " + -g, --git download the default branch's latest commit of the + Git repository at URL")) + (format #t (G_ " + --commit=COMMIT-OR-TAG + download the given commit or tag of the Git + repository at URL")) + (format #t (G_ " + --branch=BRANCH download the given branch of the Git repository + at URL")) + (format #t (G_ " + -r, --recursive download a Git repository recursively")) + (newline) (display (G_ " -h, --help display this help and exit")) @@ -105,6 +205,13 @@ (define (show-help) (newline) (show-bug-report-information)) +(define (add-git-download-option result) + (alist-cons 'download-proc + ;; XXX: #:verify-certificate? currently ignored. + (lambda* (url #:key verify-certificate? ref recursive?) + (git-download-to-store* url ref recursive?)) + (alist-delete 'download result))) + (define %options ;; Specifications of the command-line options. (list (option '(#\f "format") #t #f @@ -136,10 +243,46 @@ (define fmt-proc (alist-cons 'verify-certificate? #f result))) (option '(#\o "output") #t #f (lambda (opt name arg result) - (alist-cons 'download-proc - (lambda* (url #:key verify-certificate?) - (download-to-file url arg)) - (alist-delete 'download result)))) + (let* ((git + (assoc-ref result 'git-reference))) + (if git + (alist-cons 'download-proc + (lambda* (url + #:key + verify-certificate? + ref + recursive?) + (git-download-to-file + url + arg + (assoc-ref result 'git-reference) + recursive?)) + (alist-delete 'download result)) + (alist-cons 'download-proc + (lambda* (url + #:key verify-certificate? + #:allow-other-keys) + (download-to-file url arg)) + (alist-delete 'download result)))))) + (option '(#\g "git") #f #f + (lambda (opt name arg result) + ;; Ignore this option if 'commit' or 'branch' has + ;; already been provided + (if (assoc-ref result 'git-reference) + result + (alist-cons 'git-reference '() + (add-git-download-option result))))) + (option '("commit") #t #f + (lambda (opt name arg result) + (alist-cons 'git-reference `(tag-or-commit . ,arg) + (add-git-download-option result)))) + (option '("branch") #t #f + (lambda (opt name arg result) + (alist-cons 'git-reference `(branch . ,arg) + (add-git-download-option result)))) + (option '(#\r "recursive") #f #f + (lambda (opt name arg result) + (alist-cons 'recursive? #t result))) (option '(#\h "help") #f #f (lambda args @@ -183,12 +326,14 @@ (define (parse-options) (terminal-columns))) (fetch (uri->string uri) #:verify-certificate? - (assq-ref opts 'verify-certificate?)))) - (hash (call-with-input-file - (or path - (leave (G_ "~a: download failed~%") - arg)) - (cute port-hash (assoc-ref opts 'hash-algorithm) <>))) + (assq-ref opts 'verify-certificate?) + #:ref (assq-ref opts 'git-reference) + #:recursive? (assq-ref opts 'recursive?)))) + (hash (let* ((path* (or path + (leave (G_ "~a: download failed~%") + arg)))) + (file-hash* path* + #:algorithm (assoc-ref opts 'hash-algorithm)))) (fmt (assq-ref opts 'format))) (format #t "~a~%~a~%" path (fmt hash)) #t))) diff --git a/tests/guix-download.sh b/tests/guix-download.sh index f4cb335eef..d4cd2ea6b9 100644 --- a/tests/guix-download.sh +++ b/tests/guix-download.sh @@ -16,6 +16,12 @@ # You should have received a copy of the GNU General Public License # along with GNU Guix. If not, see . +# Define some files/folders needed for the tests. +output="t-download-$$" +test_git_repo="$(mktemp -d)" +output_dir="t-archive-dir-$$" +trap 'rm -rf "$test_git_repo" ; rm -f "$output" ; rm -rf "$output_dir"' EXIT + # # Test the `guix download' command-line utility. # @@ -36,8 +42,6 @@ guix download "file://$abs_top_srcdir/README" guix download "$abs_top_srcdir/README" # This one too, even if it cannot talk to the daemon. -output="t-download-$$" -trap 'rm -f "$output"' EXIT GUIX_DAEMON_SOCKET="/nowhere" guix download -o "$output" \ "file://$abs_top_srcdir/README" cmp "$output" "$abs_top_srcdir/README" @@ -45,4 +49,41 @@ cmp "$output" "$abs_top_srcdir/README" # This one should fail. guix download "file:///does-not-exist" "file://$abs_top_srcdir/README" && false +# Test git support with local repository. +# First, create a dummy git repo in the temporary directory. +( + cd $test_git_repo + git init + touch test + git config user.name "User" + git config user.email "user@domain" + git add test + git commit -m "Commit" + git tag -a -m "v1" v1 +) + +# Extract commit number. +commit=$((cd $test_git_repo && git log) | head -n 1 | cut -f2 -d' ') + +# We expect that guix hash is working properly or at least that the output of +# 'guix download' is consistent with 'guix hash'. +expected_hash=$(guix hash -rx $test_git_repo) + +# Test the different options +for option in "" "--commit=$commit" "--commit=v1" "--branch=master" +do + command_output="$(guix download --git $option "file://$test_git_repo")" + computed_hash="$(echo $command_output | cut -f2 -d' ')" + store_path="$(echo $command_output | cut -f1 -d' ')" + [ "$expected_hash" = "$computed_hash" ] + diff -r -x ".git" $test_git_repo $store_path +done + +# Should fail. +guix download --git --branch=non_existent "file://$test_git_repo" && false + +# Same but download to file instead of store. +guix download --git "file://$test_git_repo" -o $output_dir +diff -r -x ".git" $test_git_repo $output_dir + exit 0 -- cgit v1.2.3 From 6cca8f069431f4475d8eaf9336cb952ce5694e55 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Mon, 15 Jan 2024 18:18:36 +0100 Subject: weather: Add ‘-e’. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/scripts/weather.scm (show-help, %options): Add ‘-e’. (guix-weather): Handle it. * doc/guix.texi (Invoking guix weather): Document it. Change-Id: I6dc97ec2b8226b57be33247b05a34c23b573a64f --- doc/guix.texi | 16 +++++++++++++++- guix/scripts/weather.scm | 9 ++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index a6187690bb..db0c751ded 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -22,7 +22,7 @@ @set SUBSTITUTE-URLS https://@value{SUBSTITUTE-SERVER-1} https://@value{SUBSTITUTE-SERVER-2} @copying -Copyright @copyright{} 2012-2023 Ludovic Courtès@* +Copyright @copyright{} 2012-2024 Ludovic Courtès@* Copyright @copyright{} 2013, 2014, 2016 Andreas Enge@* Copyright @copyright{} 2013 Nikita Karetnikov@* Copyright @copyright{} 2014, 2015, 2016 Alex Kost@* @@ -16744,6 +16744,20 @@ guix package}). This option can be repeated several times, in which case the manifests are concatenated. +@item --expression=@var{expr} +@itemx -e @var{expr} +Consider the package @var{expr} evaluates to. + +A typical use case for this option is specifying a package that is +hidden and thus cannot be referred to in the usual way, as in this +example: + +@example +guix weather -e '(@@@@ (gnu packages rust) rust-bootstrap)' +@end example + +This option can be repeated. + @item --coverage[=@var{count}] @itemx -c [@var{count}] Report on substitute coverage for packages: list packages with at least diff --git a/guix/scripts/weather.scm b/guix/scripts/weather.scm index 2f8985593d..08a1b22a74 100644 --- a/guix/scripts/weather.scm +++ b/guix/scripts/weather.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2017-2023 Ludovic Courtès +;;; Copyright © 2017-2024 Ludovic Courtès ;;; Copyright © 2017 Ricardo Wurmus ;;; Copyright © 2018 Kyle Meyer ;;; Copyright © 2020 Simon Tournier @@ -388,6 +388,8 @@ (define (show-help) -m, --manifest=MANIFEST look up substitutes for packages specified in MANIFEST")) (display (G_ " + -e, --expression=EXPR build the object EXPR evaluates to")) + (display (G_ " -c, --coverage[=COUNT] show substitute coverage for packages with at least COUNT dependents")) @@ -426,6 +428,9 @@ (define %options (option '(#\m "manifest") #t #f (lambda (opt name arg result) (alist-cons 'manifest arg result))) + (option '(#\e "expression") #t #f + (lambda (opt name arg result) + (alist-cons 'expression arg result))) (option '(#\c "coverage") #f #t (lambda (opt name arg result) (alist-cons 'coverage @@ -611,6 +616,8 @@ (define (package-list opts) (base (filter-map (match-lambda (('argument . spec) (specification->package spec)) + (('expression . str) + (read/eval-package-expression str)) (_ #f)) opts))) -- cgit v1.2.3 From 2b0f47580948deb2884aade5131e129702eb8fc9 Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer Date: Fri, 26 Jan 2024 14:37:17 -0500 Subject: doc: Define postgresql-service-type as a variable. Using defvar for service types causes them to be part of the index, which is useful for discoverability. * doc/guix.texi (Database Services) : Define with defvar. Change-Id: If1c920ad275a9386ec7bb9e48e9a132df98dee97 --- doc/guix.texi | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index db0c751ded..3854c9f67d 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -25798,6 +25798,9 @@ The @code{(gnu services databases)} module provides the following services. @subsubheading PostgreSQL +@defvar postgresql-service-type +The service type for the PostgreSQL database server. Its value should +be a valid @code{postgresql-configuration} object, documented below. The following example describes a PostgreSQL service with the default configuration. @@ -25824,6 +25827,7 @@ sudo -u postgres -s /bin/sh createuser --interactive createdb $MY_USER_LOGIN # Replace appropriately. @end example +@end defvar @deftp {Data Type} postgresql-configuration Data type representing the configuration for the -- cgit v1.2.3 From 063445792b75e157d3a06eaab258739f6de5a961 Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer Date: Fri, 26 Jan 2024 15:20:49 -0500 Subject: doc: Define jami-service-type as a variable. Using defvar for service types causes them to be part of the index, which is useful for discoverability. * doc/guix.texi (Telephony Services) : Define with defvar. Change-Id: I7cbb3b7c84c34a91db689b8698a19ed49ef607b4 --- doc/guix.texi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 3854c9f67d..881d9cede3 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -28601,10 +28601,11 @@ services: @subsubheading Jami -@cindex jami, service - -This section describes how to configure a Jami server that can be used -to host video (or audio) conferences, among other uses. The following +@defvar jami-service-type +The service type for running Jami as a service. It takes a +@code{jami-configuration} object as a value, documented below. This +section describes how to configure a Jami server that can be used to +host video (or audio) conferences, among other uses. The following example demonstrates how to specify Jami account archives (backups) to be provisioned automatically: @@ -28732,6 +28733,7 @@ Account_username: f3345f2775ddfe07a4b0d95daea111d15fbc1199 The remaining actions should be self-explanatory. The complete set of available configuration options is detailed below. +@end defvar @c TODO: Ideally, the following fragments would be auto-generated at @c build time, so that they needn't be manually duplicated. -- cgit v1.2.3 From e06b283f60b2d3cdfe6b29511b34bfa8bd272e8d Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer Date: Fri, 26 Jan 2024 15:23:17 -0500 Subject: doc: Define mumble-server-service-type as a variable. Using defvar for service types causes them to be part of the index, which is useful for discoverability. * doc/guix.texi (Telephony Services) : Define with defvar. Change-Id: I01bed0c86ff12425a81294cb12f1b2a8bd14cd6f --- doc/guix.texi | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 881d9cede3..4af830aed7 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -28830,6 +28830,12 @@ account fingerprint for a registered username. This section describes how to set up and run a @uref{https://mumble.info, Mumble} server (formerly known as Murmur). +@defvar mumble-server-service-type + +This is the service to run a Mumble server. It takes a +@code{mumble-server-configuration} object as its value, defined below. +@end defvar + @deftp {Data Type} mumble-server-configuration The service type for the Mumble server. An example configuration can look like this: -- cgit v1.2.3 From 2823253484e49391c6ba3c653a2f9e9f5e5f38ae Mon Sep 17 00:00:00 2001 From: Florian Pelz Date: Sun, 21 Jan 2024 14:01:38 +0100 Subject: doc: Fix typo. Follow-up to 3872ecf274ca53a5c195f6b51081474876897565. * doc/guix.texi (Complex Configurations): Use correct variable name. --- doc/guix.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 4af830aed7..c458befb76 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -43375,7 +43375,7 @@ A clause has the following form: the generated record. @var{type-decl} is either @code{@var{type}} for fields that require a -value to be set or @code{(@var{type} @var{default})} otherwise. +value to be set or @code{(@var{type} @var{default-value})} otherwise. @var{type} is the type of the value corresponding to @var{field-name}; since Guile is untyped, a predicate -- cgit v1.2.3 From 2f67528edd2d7669b441f61cb36d1b0f4f60bdb9 Mon Sep 17 00:00:00 2001 From: Giacomo Leidi Date: Sun, 28 Jan 2024 16:37:16 +0100 Subject: home: Add home-dotfiles-service. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/home/service/dotfiles.scm: New file; * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * po/guix/POTFILES.in: Add it. * doc/guix.texi (Essential Home Services): Document it. Change-Id: I6769169cfacefc3842faa5b31bee081c56c28743 Co-authored-by: Ludovic Courtès --- doc/guix.texi | 108 +++++++++++++++++++++++++++++++++++++ gnu/home/services/dotfiles.scm | 117 +++++++++++++++++++++++++++++++++++++++++ gnu/local.mk | 1 + po/guix/POTFILES.in | 1 + 4 files changed, 227 insertions(+) create mode 100644 gnu/home/services/dotfiles.scm (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index c458befb76..dee14e3bb7 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -44216,6 +44216,114 @@ to use alternative services to implement more advanced use cases like read-only home. Feel free to experiment and share your results. @end defvar +It is often the case that Guix Home users already have a setup for versioning +their user configuration files (also known as @emph{dotfiles}) in a single +directory, and some way of automatically deploy changes to their user home. + +The @code{home-dotfiles-service-type} from @code{(gnu home services dotfiles)} +is designed to ease the way into using Guix Home for this kind of users, +allowing them to point the service to their dotfiles directory, which must +follow the layout suggested by +@uref{https://www.gnu.org/software/stow/, GNU Stow}, +and have their dotfiles automatically deployed to their user home, without +migrating them to Guix native configurations. + +The dotfiles directory layout is expected to be structured as follows. Please +keep in mind that it is advisable to keep your dotfiles directories under +version control, for example in the same repository where you'd track your +Guix Home configuration. + +@example +~$ tree -a ./dotfiles/ +dotfiles/ +├── git +│ └── .gitconfig +├── gpg +│ └── .gnupg +│ ├── gpg-agent.conf +│ └── gpg.conf +├── guile +│ └── .guile +├── guix +│ └── .config +│ └── guix +│ └── channels.scm +├── nix +│ ├── .config +│ │ └── nixpkgs +│ │ └── config.nix +│ └── .nix-channels +├── tmux +│ └── .tmux.conf +└── vim + └── .vimrc + +13 directories, 10 files +@end example + +For an informal specification please refer to the Stow manual +(@pxref{Top,,, stow, Introduction}). A suitable configuration would then +be: + +@lisp +(home-environment + ;; @dots{} + (services + (service home-dotfiles-service-type + (home-dotfiles-configuration + (directories (list "./dotfiles")))))) +@end lisp + +The expected home directory state would then be: + +@example +. +├── .config +│ ├── guix +│ │ └── channels.scm +│ └── nixpkgs +│ └── config.nix +├── .gitconfig +├── .gnupg +│ ├── gpg-agent.conf +│ └── gpg.conf +├── .guile +├── .nix-channels +├── .tmux.conf +└── .vimrc +@end example + +@defvar home-dotfiles-service-type +Return a service which is very similiar to @code{home-files-service-type} +(and actually extends it), but designed to ease the way into using Guix +Home for users that already track their dotfiles under some kind of version +control. This service allows users to point Guix Home to their dotfiles +directory and have their files automatically deployed to their home directory +just like Stow would, without migrating all of their dotfiles to Guix native +configurations. +@end defvar + +@deftp {Data Type} home-dotfiles-configuration +Available @code{home-dotfiles-configuration} fields are: + +@table @asis +@item @code{source-directory} (default: @code{(current-source-directory)}) +The path where dotfile directories are resolved. By default dotfile directories +are resolved relative the source location where +@code{home-dotfiles-configuration} appears. + +@item @code{directories} (type: list-of-strings) +The list of dotfiles directories where @code{home-dotfiles-service-type} will +look for application dotfiles. + +@item @code{exclude} (default: @code{'(".*~" ".*\\.swp" "\\.git" "\\.gitignore")}) +The list of file patterns @code{home-dotfiles-service-type} will exclude while +visiting each one of the @code{directories}. + +@end table + +@end deftp + @defvar home-xdg-configuration-files-service-type The service is very similar to @code{home-files-service-type} (and actually extends it), but used for defining files, which will go to diff --git a/gnu/home/services/dotfiles.scm b/gnu/home/services/dotfiles.scm new file mode 100644 index 0000000000..6a740c42ce --- /dev/null +++ b/gnu/home/services/dotfiles.scm @@ -0,0 +1,117 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2024 Ludovic Courtès +;;; Copyright © 2024 Giacomo Leidi +;;; +;;; 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 . + +(define-module (gnu home services dotfiles) + #:use-module (gnu home services) + #:use-module (gnu services) + #:autoload (guix build utils) (find-files) + #:use-module (guix gexp) + #:use-module (guix records) + #:use-module ((guix utils) #:select (current-source-directory)) + #:use-module (srfi srfi-1) + #:use-module (ice-9 ftw) + #:use-module (ice-9 regex) + #:export (home-dotfiles-service-type + home-dotfiles-configuration + home-dotfiles-configuration? + home-dotfiles-configuration-source-directory + home-dotfiles-configuration-directories + home-dotfiles-configuration-excluded)) + +(define %home-dotfiles-excluded + '(".*~" + ".*\\.swp" + "\\.git" + "\\.gitignore")) + +(define-record-type* + home-dotfiles-configuration make-home-dotfiles-configuration + home-dotfiles-configuration? + (source-directory home-dotfiles-configuration-source-directory + (default (current-source-directory)) + (innate)) + (directories home-dotfiles-configuration-directories ;list of strings + (default '())) + (excluded home-dotfiles-configuration-excluded ;list of strings + (default %home-dotfiles-excluded))) + +(define (import-dotfiles directory files) + "Return a list of objects compatible with @code{home-files-service-type}'s +value. Each object is a pair where the first element is the relative path +of a file and the second is a gexp representing the file content. Objects are +generated by recursively visiting DIRECTORY and mapping its contents to the +user's home directory, excluding files that match any of the patterns in EXCLUDED." + (define (strip file) + (string-drop file (+ 1 (string-length directory)))) + + (define (format file) + ;; Remove from FILE characters that cannot be used in the store. + (string-append + "home-dotfiles-" + (string-map (lambda (chr) + (if (and (char-set-contains? char-set:ascii chr) + (char-set-contains? char-set:graphic chr) + (not (memv chr '(#\. #\/ #\space)))) + chr + #\-)) + file))) + + (map (lambda (file) + (let ((stripped (strip file))) + (list stripped + (local-file file (format stripped) + #:recursive? #t)))) + files)) + +(define (home-dotfiles-configuration->files config) + "Return a list of objects compatible with @code{home-files-service-type}'s +value, generated following GNU Stow's algorithm for each of the +directories in CONFIG, excluding files that match any of the patterns configured." + (define excluded + (home-dotfiles-configuration-excluded config)) + (define exclusion-rx + (make-regexp (string-append "^.*(" (string-join excluded "|") ")$"))) + + (define (directory-contents directory) + (find-files directory + (lambda (file stat) + (not (regexp-exec exclusion-rx + (basename file)))))) + + (define (resolve directory) + ;; Resolve DIRECTORY relative to the 'source-directory' field of CONFIG. + (if (string-prefix? "/" directory) + directory + (in-vicinity (home-dotfiles-configuration-source-directory config) + directory))) + + (append-map (lambda (directory) + (let* ((directory (resolve directory)) + (contents (directory-contents directory))) + (import-dotfiles directory contents))) + (home-dotfiles-configuration-directories config))) + +(define-public home-dotfiles-service-type + (service-type (name 'home-dotfiles) + (extensions + (list (service-extension home-files-service-type + home-dotfiles-configuration->files))) + (default-value (home-dotfiles-configuration)) + (description "Files that will be put in the user's home directory +following GNU Stow's algorithm, and further processed during activation."))) diff --git a/gnu/local.mk b/gnu/local.mk index 041e2f1b7b..5e0a058848 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -96,6 +96,7 @@ GNU_SYSTEM_MODULES = \ %D%/home/services.scm \ %D%/home/services/desktop.scm \ %D%/home/services/dict.scm \ + %D%/home/services/dotfiles.scm \ %D%/home/services/symlink-manager.scm \ %D%/home/services/fontutils.scm \ %D%/home/services/gnupg.scm \ diff --git a/po/guix/POTFILES.in b/po/guix/POTFILES.in index 154ad4e530..d13e19619d 100644 --- a/po/guix/POTFILES.in +++ b/po/guix/POTFILES.in @@ -14,6 +14,7 @@ gnu/services/samba.scm gnu/services/version-control.scm gnu/home/services.scm gnu/home/services/desktop.scm +gnu/home/services/dotfiles.scm gnu/home/services/fontutils.scm gnu/home/services/gnupg.scm gnu/home/services/guix.scm -- cgit v1.2.3 From 5d2bc09f0a54ccc7bd8fbcee478cf6412de5dfc5 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 28 Jan 2024 22:05:33 +0100 Subject: doc: Add index entries for “dot files” and “Stow”. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc/guix.texi (Essential Home Services): Add index entries. Change-Id: I0c3a5f5d94fe273c137eb3ca5fa6c5c91a34599b --- doc/guix.texi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index dee14e3bb7..58c3024642 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -44216,10 +44216,12 @@ to use alternative services to implement more advanced use cases like read-only home. Feel free to experiment and share your results. @end defvar +@cindex dot files in Guix Home It is often the case that Guix Home users already have a setup for versioning -their user configuration files (also known as @emph{dotfiles}) in a single +their user configuration files (also known as @emph{dot files}) in a single directory, and some way of automatically deploy changes to their user home. +@cindex Stow-like dot file management The @code{home-dotfiles-service-type} from @code{(gnu home services dotfiles)} is designed to ease the way into using Guix Home for this kind of users, allowing them to point the service to their dotfiles directory, which must -- cgit v1.2.3 From dde76db33fbdede6bf26821f8c21cca7df45e79e Mon Sep 17 00:00:00 2001 From: Attila Lendvai Date: Thu, 25 Jan 2024 16:05:41 +0100 Subject: services: shepherd: Add respawn-limit and respawn-delay. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/shepherd.scm (): Add respawn-limit and respawn-delay. (shepherd-service-file): Emit the two values into the shepherd service constructor form. Change-Id: I54408e8fb4bcc0956d9610771bf5c566fdc2914c Signed-off-by: Ludovic Courtès --- doc/guix.texi | 9 +++++++++ gnu/services/shepherd.scm | 14 ++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 58c3024642..bb0af26d93 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -43143,6 +43143,15 @@ shepherd, The GNU Shepherd Manual}, for more info. Whether to restart the service when it stops, for instance when the underlying process dies. +@item @code{respawn-limit} (default: @code{#f}) +Set a limit on how many times and how frequently a service may be +restarted by Shepherd before it is disabled. @xref{Defining +Services,,, shepherd, The GNU Shepherd Manual}, for details. + +@item @code{respawn-delay} (default: @code{#f}) +When true, this is the delay in seconds before restarting a failed +service. + @item @code{start} @itemx @code{stop} (default: @code{#~(const #f)}) The @code{start} and @code{stop} fields refer to the Shepherd's diff --git a/gnu/services/shepherd.scm b/gnu/services/shepherd.scm index 5ebac129ce..f5bcde721f 100644 --- a/gnu/services/shepherd.scm +++ b/gnu/services/shepherd.scm @@ -55,6 +55,8 @@ (define-module (gnu services shepherd) shepherd-service-canonical-name shepherd-service-requirement shepherd-service-one-shot? + shepherd-service-respawn-limit + shepherd-service-respawn-delay shepherd-service-respawn? shepherd-service-start shepherd-service-stop @@ -211,6 +213,10 @@ (define-record-type* (default #f)) (respawn? shepherd-service-respawn? ;Boolean (default #t)) + (respawn-limit shepherd-service-respawn-limit + (default #f)) + (respawn-delay shepherd-service-respawn-delay + (default #f)) (start shepherd-service-start) ;g-expression (procedure) (stop shepherd-service-stop ;g-expression (procedure) (default #~(const #f))) @@ -309,6 +315,14 @@ (define (shepherd-service-file service) #:one-shot? '#$(shepherd-service-one-shot? service) #:respawn? '#$(shepherd-service-respawn? service) + #$@(if (shepherd-service-respawn-limit service) + `(#:respawn-limit + ,(shepherd-service-respawn-limit service)) + '()) + #$@(if (shepherd-service-respawn-delay service) + `(#:respawn-delay + ,(shepherd-service-respawn-delay service)) + '()) #:start #$(shepherd-service-start service) #:stop #$(shepherd-service-stop service) #:actions -- cgit v1.2.3 From a2b1ef903be001d5abfc47fc3e8add04fb748ff3 Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Wed, 31 Jan 2024 11:46:22 +0000 Subject: services: certbot: Symlink certificates to /etc/certs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/certbot.scm (certbot-deploy-hook): New procedure. (certbot-command): Pass new deploy hook to certbot. * doc/guix.texi: Replace "letsencrypt/live" with "certs" throughout, except in the certbot deploy-hook description. Change-Id: I2ba5e4903d1e293e566b732a84b07d5a134b697d Signed-off-by: Clément Lassieur --- doc/guix.texi | 24 ++++++++++++------------ gnu/services/certbot.scm | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 14 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index bb0af26d93..97be37f9b5 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -43,7 +43,7 @@ Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021 Christopher Baines@* Copyright @copyright{} 2017, 2018, 2019 Clément Lassieur@* Copyright @copyright{} 2017, 2018, 2020, 2021, 2022 Mathieu Othacehe@* Copyright @copyright{} 2017 Federico Beffa@* -Copyright @copyright{} 2017, 2018 Carlo Zancanaro@* +Copyright @copyright{} 2017, 2018, 2024 Carlo Zancanaro@* Copyright @copyright{} 2017 Thomas Danckaert@* Copyright @copyright{} 2017 humanitiesNerd@* Copyright @copyright{} 2017, 2021 Christine Lemmer-Webber@* @@ -28135,7 +28135,7 @@ Prosodyctl will also help you to import certificates from the them. See @url{https://prosody.im/doc/letsencrypt}. @example -prosodyctl --root cert import /etc/letsencrypt/live +prosodyctl --root cert import /etc/certs @end example The available configuration parameters follow. Each parameter @@ -28846,8 +28846,8 @@ look like this: (welcome-text "Welcome to this Mumble server running on Guix!") (cert-required? #t) ;disallow text password logins - (ssl-cert "/etc/letsencrypt/live/mumble.example.com/fullchain.pem") - (ssl-key "/etc/letsencrypt/live/mumble.example.com/privkey.pem"))) + (ssl-cert "/etc/certs/mumble.example.com/fullchain.pem") + (ssl-key "/etc/certs/mumble.example.com/privkey.pem"))) @end lisp After reconfiguring your system, you can manually set the mumble-server @@ -28965,12 +28965,12 @@ Should logged ips be obfuscated to protect the privacy of users. File name of the SSL/TLS certificate used for encrypted connections. @lisp -(ssl-cert "/etc/letsencrypt/live/example.com/fullchain.pem") +(ssl-cert "/etc/certs/example.com/fullchain.pem") @end lisp @item @code{ssl-key} (default: @code{#f}) Filepath to the ssl private key used for encrypted connections. @lisp -(ssl-key "/etc/letsencrypt/live/example.com/privkey.pem") +(ssl-key "/etc/certs/example.com/privkey.pem") @end lisp @item @code{ssl-dh-params} (default: @code{#f}) @@ -32694,8 +32694,8 @@ example, @samp{"example.com www.example.com"}. @end deftp For each @code{certificate-configuration}, the certificate is saved to -@code{/etc/letsencrypt/live/@var{name}/fullchain.pem} and the key is -saved to @code{/etc/letsencrypt/live/@var{name}/privkey.pem}. +@code{/etc/certs/@var{name}/fullchain.pem} and the key is +saved to @code{/etc/certs/@var{name}/privkey.pem}. @node DNS Services @subsection DNS Services @cindex DNS (domain name system) @@ -37381,9 +37381,9 @@ serve the default @file{/srv/git} over HTTPS might be: (listen '("443 ssl")) (server-name "git.my-host.org") (ssl-certificate - "/etc/letsencrypt/live/git.my-host.org/fullchain.pem") + "/etc/certs/git.my-host.org/fullchain.pem") (ssl-certificate-key - "/etc/letsencrypt/live/git.my-host.org/privkey.pem") + "/etc/certs/git.my-host.org/privkey.pem") (locations (list (git-http-nginx-location-configuration @@ -38508,9 +38508,9 @@ footers. (nginx-server-block (nginx-server-configuration (ssl-certificate - "/etc/letsencrypt/live/myweb.site/fullchain.pem") + "/etc/certs/myweb.site/fullchain.pem") (ssl-certificate-key - "/etc/letsencrypt/live/myweb.site/privkey.pem") + "/etc/certs/myweb.site/privkey.pem") (listen '("443 ssl http2" "[::]:443 ssl http2")) (locations (list diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm index 0c45471659..3926d0551a 100644 --- a/gnu/services/certbot.scm +++ b/gnu/services/certbot.scm @@ -6,6 +6,7 @@ ;;; Copyright © 2020 Jack Hill ;;; Copyright © 2020 Tobias Geerinckx-Rice ;;; Copyright © 2021 Raghav Gururajan +;;; Copyright © 2024 Carlo Zancanaro ;;; ;;; This file is part of GNU Guix. ;;; @@ -87,6 +88,35 @@ (define-record-type* (body (list "return 301 https://$host$request_uri;")))))) +(define (certbot-deploy-hook name deploy-hook-script) + "Returns a gexp which creates symlinks for privkey.pem and fullchain.pem +from /etc/certs/NAME to /etc/letsenctypt/live/NAME. If DEPLOY-HOOK-SCRIPT is +not #f then it is run after the symlinks have been created." + (program-file + (string-append name "-deploy-hook") + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (mkdir-p #$(string-append "/etc/certs/" name)) + (chmod #$(string-append "/etc/certs/" name) #o755) + + ;; Create new symlinks + (symlink #$(string-append + "/etc/letsencrypt/live/" name "/privkey.pem") + #$(string-append "/etc/certs/" name "/privkey.pem.new")) + (symlink #$(string-append + "/etc/letsencrypt/live/" name "/fullchain.pem") + #$(string-append "/etc/certs/" name "/fullchain.pem.new")) + + ;; Rename over the top of the old ones, if there are any. + (rename-file #$(string-append "/etc/certs/" name "/privkey.pem.new") + #$(string-append "/etc/certs/" name "/privkey.pem")) + (rename-file #$(string-append "/etc/certs/" name "/fullchain.pem.new") + #$(string-append "/etc/certs/" name "/fullchain.pem")) + #$@(if deploy-hook-script + (list #~(invoke #$deploy-hook-script)) + '()))))) + (define certbot-command (match-lambda (($ package webroot certificates email @@ -118,7 +148,8 @@ (define certbot-command `("--manual-auth-hook" ,authentication-hook) '()) (if cleanup-hook `("--manual-cleanup-hook" ,cleanup-hook) '()) - (if deploy-hook `("--deploy-hook" ,deploy-hook) '())) + (list "--deploy-hook" + (certbot-deploy-hook name deploy-hook))) (append (list name certbot "certonly" "-n" "--agree-tos" "--webroot" "-w" webroot @@ -130,7 +161,8 @@ (define certbot-command '("--register-unsafely-without-email")) (if server `("--server" ,server) '()) (if rsa-key-size `("--rsa-key-size" ,rsa-key-size) '()) - (if deploy-hook `("--deploy-hook" ,deploy-hook) '())))))) + (list "--deploy-hook" + (certbot-deploy-hook name deploy-hook))))))) certificates))) (program-file "certbot-command" -- cgit v1.2.3 From fc0ec9a3cc2707260b88c79286e91fa1a3a594cb Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Wed, 31 Jan 2024 11:46:23 +0000 Subject: services: certbot: Create self-signed certificates before certbot runs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/certbot.scm (): Add start-self-signed? field. (generate-certificate-gexp): New procedure. (certbot-activation): Generate self-signed certificates when start-self-signed? is #t. * doc/guix.texi (Certificate services): Document start-self-signed?. Change-Id: Icfd85ae0c3e29324acbcde6ba283546cf0e27a1d Signed-off-by: Clément Lassieur --- doc/guix.texi | 6 +++++ gnu/services/certbot.scm | 62 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 3 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 97be37f9b5..732abceb0f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -32690,6 +32690,12 @@ certificates and keys; the shell variable @code{$RENEWED_DOMAINS} will contain a space-delimited list of renewed certificate domains (for example, @samp{"example.com www.example.com"}. +@item @code{start-self-signed?} (default: @code{#t}) +Whether to generate an initial self-signed certificate during system +activation. This option is particularly useful to allow @code{nginx} to +start before @code{certbot} has run, because @code{certbot} relies on +@code{nginx} running to perform HTTP challenges. + @end table @end deftp diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm index 3926d0551a..10b99f5630 100644 --- a/gnu/services/certbot.scm +++ b/gnu/services/certbot.scm @@ -35,6 +35,7 @@ (define-module (gnu services certbot) #:use-module (guix records) #:use-module (guix gexp) #:use-module (srfi srfi-1) + #:use-module (ice-9 format) #:use-module (ice-9 match) #:export (certbot-service-type certbot-configuration @@ -64,7 +65,9 @@ (define-record-type* (cleanup-hook certificate-cleanup-hook (default #f)) (deploy-hook certificate-configuration-deploy-hook - (default #f))) + (default #f)) + (start-self-signed? certificate-configuration-start-self-signed? + (default #t))) (define-record-type* certbot-configuration make-certbot-configuration @@ -91,7 +94,10 @@ (define-record-type* (define (certbot-deploy-hook name deploy-hook-script) "Returns a gexp which creates symlinks for privkey.pem and fullchain.pem from /etc/certs/NAME to /etc/letsenctypt/live/NAME. If DEPLOY-HOOK-SCRIPT is -not #f then it is run after the symlinks have been created." +not #f then it is run after the symlinks have been created. This wrapping is +necessary for certificates with start-self-signed? set to #t, as it will +overwrite the initial self-signed certificates upon the first successful +deploy." (program-file (string-append name "-deploy-hook") (with-imported-modules '((guix build utils)) @@ -108,7 +114,8 @@ (define (certbot-deploy-hook name deploy-hook-script) "/etc/letsencrypt/live/" name "/fullchain.pem") #$(string-append "/etc/certs/" name "/fullchain.pem.new")) - ;; Rename over the top of the old ones, if there are any. + ;; Rename over the top of the old ones, just in case they were the + ;; original self-signed certificates. (rename-file #$(string-append "/etc/certs/" name "/privkey.pem.new") #$(string-append "/etc/certs/" name "/privkey.pem")) (rename-file #$(string-append "/etc/certs/" name "/fullchain.pem.new") @@ -184,6 +191,47 @@ (define (certbot-renewal-jobs config) #~(job '(next-minute-from (next-hour '(0 12)) (list (random 60))) #$(certbot-command config)))) +(define (generate-certificate-gexp certbot-cert-directory rsa-key-size) + (match-lambda + (($ name (primary-domain other-domains ...) + challenge + csr authentication-hook + cleanup-hook deploy-hook) + (let (;; Arbitrary default subject, with just the + ;; right domain filled in. These values don't + ;; have any real significance. + (subject (string-append + "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=" + primary-domain)) + (alt-names (if (null? other-domains) + #f + (format #f "subjectAltName=~{DNS:~a~^,~}" + other-domains))) + (directory (string-append "/etc/certs/" (or name primary-domain)))) + #~(when (not (file-exists? #$directory)) + ;; We generate self-signed certificates in /etc/certs/{domain}, + ;; because certbot is very sensitive to its directory + ;; structure. It refuses to write over the top of existing files, + ;; so we need to use a directory outside of its control. + ;; + ;; These certificates are overwritten by the certbot deploy hook + ;; the first time it successfully obtains a letsencrypt-signed + ;; certificate. + (mkdir-p #$directory) + (chmod #$directory #o755) + (invoke #$(file-append openssl "/bin/openssl") + "req" "-x509" + "-newkey" #$(string-append "rsa:" (or rsa-key-size "4096")) + "-keyout" #$(string-append directory "/privkey.pem") + "-out" #$(string-append directory "/fullchain.pem") + "-sha256" + "-days" "1" ; Only one day, because we expect certbot to run + "-nodes" + "-subj" #$subject + #$@(if alt-names + (list "-addext" alt-names) + (list)))))))) + (define (certbot-activation config) (let* ((certbot-directory "/var/lib/certbot") (certbot-cert-directory "/etc/letsencrypt/live") @@ -198,6 +246,14 @@ (define (certbot-activation config) (mkdir-p #$webroot) (mkdir-p #$certbot-directory) (mkdir-p #$certbot-cert-directory) + + #$@(let ((rsa-key-size (and rsa-key-size + (number->string rsa-key-size)))) + (map (generate-certificate-gexp certbot-cert-directory + rsa-key-size) + (filter certificate-configuration-start-self-signed? + certificates))) + (copy-file #$(certbot-command config) #$script) (display #$message))))))) -- cgit v1.2.3 From d4a4b12f0ac52563254d34dc1e26030b354d3f73 Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Wed, 31 Jan 2024 11:46:24 +0000 Subject: services: certbot: Reload nginx in deploy hook. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/services/certbot.scm (certbot-deploy-hook): Reload nginx. * doc/guix.texi (Certificate services): Remove deploy-hook from example. Change-Id: Ibb10481170a6fda7df72492072b939dd6a6ad176 Signed-off-by: Clément Lassieur --- doc/guix.texi | 10 +--------- gnu/services/certbot.scm | 10 ++++++++-- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'doc/guix.texi') diff --git a/doc/guix.texi b/doc/guix.texi index 732abceb0f..c71d7e94cf 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -32562,21 +32562,13 @@ A service type for the @code{certbot} Let's Encrypt client. Its value must be a @code{certbot-configuration} record as in this example: @lisp -(define %certbot-deploy-hook - (program-file "certbot-deploy-hook.scm" - (with-imported-modules '((gnu services herd)) - #~(begin - (use-modules (gnu services herd)) - (with-shepherd-action 'nginx ('reload) result result))))) - (service certbot-service-type (certbot-configuration (email "foo@@example.net") (certificates (list (certificate-configuration - (domains '("example.net" "www.example.net")) - (deploy-hook %certbot-deploy-hook)) + (domains '("example.net" "www.example.net"))) (certificate-configuration (domains '("bar.example.net"))))))) @end lisp diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm index 10b99f5630..cb1be0c0e9 100644 --- a/gnu/services/certbot.scm +++ b/gnu/services/certbot.scm @@ -100,9 +100,11 @@ (define (certbot-deploy-hook name deploy-hook-script) deploy." (program-file (string-append name "-deploy-hook") - (with-imported-modules '((guix build utils)) + (with-imported-modules '((gnu services herd) + (guix build utils)) #~(begin - (use-modules (guix build utils)) + (use-modules (gnu services herd) + (guix build utils)) (mkdir-p #$(string-append "/etc/certs/" name)) (chmod #$(string-append "/etc/certs/" name) #o755) @@ -120,6 +122,10 @@ (define (certbot-deploy-hook name deploy-hook-script) #$(string-append "/etc/certs/" name "/privkey.pem")) (rename-file #$(string-append "/etc/certs/" name "/fullchain.pem.new") #$(string-append "/etc/certs/" name "/fullchain.pem")) + + ;; With the new certificates in place, tell nginx to reload them. + (with-shepherd-action 'nginx ('reload) result result) + #$@(if deploy-hook-script (list #~(invoke #$deploy-hook-script)) '()))))) -- cgit v1.2.3