all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service
@ 2024-10-22 21:21 Richard Sent
  2024-10-22 21:25 ` [bug#73955] [PATCH 1/2] services: wireguard: Make the private-key field optional Richard Sent
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-22 21:21 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, guix, maxim.cournoyer, eu

Hi all,

The goal for this patch series is to improve wireguard-service's
customizability, primarily by supporting gexps evaluating to strings in most
fields. Prior to this patch, lists of gexp's were not serialized to strings,
preventing certain constructs from being used.

This was prompted from an issue I ran into a while back. [1]

I tested the serialization of several config records and did not notice any
issues. I would greatly appreciate if any users of wireguard-service could
confirm their existing configurations still serialize correctly. You can do so
via these guix REPL commands:

$ guix repl -L /path/to/guix/clone/with/patches
,use (guix)
,use (gnu services vpn)
,build ((@@ (gnu services vpn) wireguard-configuration-file)
        <paste-your-wireguard-configuration>)

I took the liberty of CCing a few people who previously committed to
WireGuard. Apologies if I committed a faux pas. :)

[1]: https://lists.gnu.org/archive/html/help-guix/2024-01/msg00204.html

Richard Sent (2):
  services: wireguard: Make the private-key field optional.
  services: wireguard: Support lists of gexps for most fields.

 doc/guix.texi        |  5 ++-
 gnu/services/vpn.scm | 74 +++++++++++++++++++++++---------------------
 2 files changed, 43 insertions(+), 36 deletions(-)


base-commit: bd26815cf8ce38a3b03676a6e3fc482bb74247cb
-- 
2.46.0





^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH 1/2] services: wireguard: Make the private-key field optional.
  2024-10-22 21:21 [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service Richard Sent
@ 2024-10-22 21:25 ` Richard Sent
  2024-10-22 21:25 ` [bug#73955] [PATCH 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-22 21:25 UTC (permalink / raw)
  To: 73955
  Cc: othacehe, Richard Sent, guix, maxim.cournoyer, eu,
	Ludovic Courtès, Maxim Cournoyer

Users who retrieve the private-key via a PreUp field need to be able to
disable the default retrieval mechanism.

* gnu/services/vpn.scm (<wireguard-configuration>)[private-key]: Change
comment.
(wireguard-configuration-file): Conditionally serialize private-key.
* gnu/services/vpn.scm (wireguard-activation): Do not create private-key if
the field is #f.
* doc/guix.texi (VPN Services)[wireguard-configuration]: Document it.

Change-Id: Iac419809ae94eb76e97ff1f1749e2f4b3e65bb04
---
 doc/guix.texi        |  5 ++++-
 gnu/services/vpn.scm | 36 ++++++++++++++++++++----------------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index ac3a7adef0..5558bd7d44 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34453,7 +34453,10 @@ VPN Services
 
 @item @code{private-key} (default: @code{"/etc/wireguard/private.key"})
 The private key file for the interface.  It is automatically generated
-if the file does not exist.
+if the file does not exist.  If this field is @code{#f}, a private key
+is not created and the path is not serialized to the configuration file.
+This allows for retrieving the private key programmatically with a PreUp
+command.
 
 @item @code{peers} (default: @code{'()})
 The authorized peers on this interface.  This is a list of
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index 7fb4775757..b62e0ac838 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -741,7 +741,7 @@ (define-record-type* <wireguard-configuration>
                       (default '("10.0.0.1/32")))
   (port               wireguard-configuration-port ;integer
                       (default 51820))
-  (private-key        wireguard-configuration-private-key ;string
+  (private-key        wireguard-configuration-private-key ;maybe-string
                       (default "/etc/wireguard/private.key"))
   (peers              wireguard-configuration-peers ;list of <wiregard-peer>
                       (default '()))
@@ -805,9 +805,12 @@ (define (wireguard-configuration-file config)
                     #$@(if (null? pre-up)
                            '()
                            (list (format #f "~{PreUp = ~a~%~}" pre-up)))
-                    (format #f "PostUp = ~a set %i private-key ~a\
-~{ peer ~a preshared-key ~a~}" #$(file-append wireguard "/bin/wg")
-#$private-key '#$peer-keys)
+                    (if #$private-key
+                        (format #f "PostUp = ~a set %i private-key ~a\
+~{ peer ~a preshared-key ~a~}"
+                                #$(file-append wireguard "/bin/wg")
+                                #$private-key '#$peer-keys)
+                        "")
                     #$@(if (null? post-up)
                            '()
                            (list (format #f "~{PostUp = ~a~%~}" post-up)))
@@ -838,18 +841,19 @@ (define (wireguard-activation config)
         (use-modules (guix build utils)
                      (ice-9 popen)
                      (ice-9 rdelim))
-        (mkdir-p (dirname #$private-key))
-        (unless (file-exists? #$private-key)
-          (let* ((pipe
-                  (open-input-pipe (string-append
-                                    #$(file-append wireguard "/bin/wg")
-                                    " genkey")))
-                 (key (read-line pipe)))
-            (call-with-output-file #$private-key
-              (lambda (port)
-                (display key port)))
-            (chmod #$private-key #o400)
-            (close-pipe pipe))))))
+        (when #$private-key
+          (mkdir-p (dirname #$private-key))
+          (unless (file-exists? #$private-key)
+            (let* ((pipe
+                    (open-input-pipe (string-append
+                                      #$(file-append wireguard "/bin/wg")
+                                      " genkey")))
+                   (key (read-line pipe)))
+              (call-with-output-file #$private-key
+                (lambda (port)
+                  (display key port)))
+              (chmod #$private-key #o400)
+              (close-pipe pipe)))))))
 
 ;;; XXX: Copied from (guix scripts pack), changing define to define*.
 (define-syntax-rule (define-with-source (variable args ...) body body* ...)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH 2/2] services: wireguard: Support lists of gexps for most fields.
  2024-10-22 21:21 [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service Richard Sent
  2024-10-22 21:25 ` [bug#73955] [PATCH 1/2] services: wireguard: Make the private-key field optional Richard Sent
@ 2024-10-22 21:25 ` Richard Sent
  2024-10-23  9:26   ` Mathieu Othacehe
  2024-10-23 15:30 ` [bug#73955] [PATCH v2 0/2] Improve customizability in WireGuard service Richard Sent
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Richard Sent @ 2024-10-22 21:25 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, guix, maxim.cournoyer, eu

In order to support more flexibility in Wireguard configuration, ungexp the
configuration fields directly instead of ungexp-splicing a sexp
calculator. This allows for the fields to take arbitrary gexps instead of only
strings which is particularly helpful for the Pre/Post Up/Down commands.

For example, the wg-quick(8) manual has an example on how to use
password-store to retrieve a private key with a PreUp entry. This is now
possible.

* gnu/services/vpn.scm (wireguard-configuration-file): Ungexp configuration
lists instead of ungexp-splicing the code surrounding them.

Change-Id: If074cbb78473b6fd34e0e4e990d2ed268001d6c7
---
 gnu/services/vpn.scm | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index b62e0ac838..21a7fb827a 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -797,33 +797,33 @@ (define (wireguard-configuration-file config)
                  (define lines
                    (list
                     "[Interface]"
-                    #$@(if (null? addresses)
-                           '()
-                           (list (format #f "Address = ~{~a~^, ~}"
-                                         addresses)))
+                    (if (null? '#$addresses)
+                        ""
+                        (format #f "Address = ~{~a~^, ~}"
+                                (list #$@addresses)))
                     (format #f "~@[Table = ~a~]" #$table)
-                    #$@(if (null? pre-up)
-                           '()
-                           (list (format #f "~{PreUp = ~a~%~}" pre-up)))
+                    (if (null? '#$pre-up)
+                        ""
+                        (format #f "~{PreUp = ~a~%~}" (list #$@pre-up)))
                     (if #$private-key
                         (format #f "PostUp = ~a set %i private-key ~a\
 ~{ peer ~a preshared-key ~a~}"
                                 #$(file-append wireguard "/bin/wg")
                                 #$private-key '#$peer-keys)
                         "")
-                    #$@(if (null? post-up)
-                           '()
-                           (list (format #f "~{PostUp = ~a~%~}" post-up)))
-                    #$@(if (null? pre-down)
-                           '()
-                           (list (format #f "~{PreDown = ~a~%~}" pre-down)))
-                    #$@(if (null? post-down)
-                           '()
-                           (list (format #f "~{PostDown = ~a~%~}" post-down)))
+                    (if (null? '#$post-up)
+                        ""
+                        (format #f "~{PostUp = ~a~%~}" (list #$@post-up)))
+                    (if (null? '#$pre-down)
+                        ""
+                        (format #f "~{PreDown = ~a~%~}" (list #$@pre-down)))
+                    (if (null? '#$post-down)
+                        ""
+                        (format #f "~{PostDown = ~a~%~}" (list #$@post-down)))
                     (format #f "~@[ListenPort = ~a~]" #$port)
-                    #$@(if (null? dns)
-                           '()
-                           (list (format #f "DNS = ~{~a~^, ~}" dns)))))
+                    (if (null? '#$dns)
+                        ""
+                        (format #f "DNS = ~{~a~^, ~}" (list #$@dns)))))
 
                  (mkdir #$output)
                  (chdir #$output)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH 2/2] services: wireguard: Support lists of gexps for most fields.
  2024-10-22 21:25 ` [bug#73955] [PATCH 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
@ 2024-10-23  9:26   ` Mathieu Othacehe
  0 siblings, 0 replies; 16+ messages in thread
From: Mathieu Othacehe @ 2024-10-23  9:26 UTC (permalink / raw)
  To: Richard Sent; +Cc: eu, maxim.cournoyer, 73955, guix


Hello Richard,

Thanks for this series.

The first commit looks OK to me.

> For example, the wg-quick(8) manual has an example on how to use
> password-store to retrieve a private key with a PreUp entry. This is now
> possible.

It would be interesting to provide some testing for that.  Sadly, we do
not have a system test for Wireguard yet. We only have a unit test file
in (tests services vpn).

Adding a new (gnu tests vpn) module would be great in the future to test
different Wireguard configurations.

That can of course be done later on :)

Regarding this patch, the documentation is somehow vague on how to pass
post and pre commands:

--8<---------------cut here---------------start------------->8---
@item @code{post-up} (default: @code{'()})
The script commands to be run after setting up the interface.

...
--8<---------------cut here---------------end--------------->8---

Maybe you could elaborate on that a little bit and give some examples
that would be the translation of some of the post and pre commands that
are given in the wg-quick man page?

Thanks,

Mathieu




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v2 0/2] Improve customizability in WireGuard service
  2024-10-22 21:21 [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service Richard Sent
  2024-10-22 21:25 ` [bug#73955] [PATCH 1/2] services: wireguard: Make the private-key field optional Richard Sent
  2024-10-22 21:25 ` [bug#73955] [PATCH 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
@ 2024-10-23 15:30 ` Richard Sent
  2024-10-23 15:30   ` [bug#73955] [PATCH v2 1/2] services: wireguard: Make the private-key field optional Richard Sent
  2024-10-23 15:30   ` [bug#73955] [PATCH v2 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
  2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
  2024-12-04 20:59 ` [bug#73955] [PATCH v4 1/3] services: wireguard: Make the private-key field optional Richard Sent
  4 siblings, 2 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-23 15:30 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, Ludovic Courtès, Maxim Cournoyer

Hi all,

Thanks for the quick review Mathieu!

This patch is largely the same as before, but I spent some time
adjusting the documentation and adding an example of retrieving the
private key programmatically.

One interesting tidbit is pre-up and pals can alternatively be wrapped
in the gexp directly instead of each entry being gexp'd individually.

> ;; normal
> (pre-up (list #~(string-append "wg set %i private-key <("
>                                #$(file-append password-store "/bin/pass")
>                                " WireGuard/private-keys/%i)")))
> 
> ;; alternative
> (pre-up #~((string-append "wg set %i private-key <("
>                            #$(file-append password-store "/bin/pass")
>                            " WireGuard/private-keys/%i)")))

I see why this works (and it should work with any other service that
handles config lists with splicing+list wrapping), but it does feel a
little bit odd.

Seeing as how no other service seems to use the alternative form, I
opted to document the former.

Richard Sent (2):
  services: wireguard: Make the private-key field optional.
  services: wireguard: Support lists of gexps for most fields.

 doc/guix.texi        | 36 ++++++++++++++++-----
 gnu/services/vpn.scm | 75 +++++++++++++++++++++++---------------------
 2 files changed, 69 insertions(+), 42 deletions(-)


base-commit: bd26815cf8ce38a3b03676a6e3fc482bb74247cb
-- 
2.46.0





^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v2 1/2] services: wireguard: Make the private-key field optional.
  2024-10-23 15:30 ` [bug#73955] [PATCH v2 0/2] Improve customizability in WireGuard service Richard Sent
@ 2024-10-23 15:30   ` Richard Sent
  2024-10-23 15:30   ` [bug#73955] [PATCH v2 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-23 15:30 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, Ludovic Courtès, Maxim Cournoyer

Users who retrieve the private-key via a PreUp field need to be able to
disable the default retrieval mechanism.

* gnu/services/vpn.scm (<wireguard-configuration>)[private-key]: Change
comment.
(wireguard-configuration-file): Conditionally serialize private-key.
* gnu/services/vpn.scm (wireguard-activation): Do not create private-key if
the field is #f.
* doc/guix.texi (VPN Services)[wireguard-configuration]: Document it.

Change-Id: Iac419809ae94eb76e97ff1f1749e2f4b3e65bb04
---
 doc/guix.texi        |  5 ++++-
 gnu/services/vpn.scm | 36 ++++++++++++++++++++----------------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index ac3a7adef0..5558bd7d44 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34453,7 +34453,10 @@ VPN Services
 
 @item @code{private-key} (default: @code{"/etc/wireguard/private.key"})
 The private key file for the interface.  It is automatically generated
-if the file does not exist.
+if the file does not exist.  If this field is @code{#f}, a private key
+is not created and the path is not serialized to the configuration file.
+This allows for retrieving the private key programmatically with a PreUp
+command.
 
 @item @code{peers} (default: @code{'()})
 The authorized peers on this interface.  This is a list of
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index 7fb4775757..b62e0ac838 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -741,7 +741,7 @@ (define-record-type* <wireguard-configuration>
                       (default '("10.0.0.1/32")))
   (port               wireguard-configuration-port ;integer
                       (default 51820))
-  (private-key        wireguard-configuration-private-key ;string
+  (private-key        wireguard-configuration-private-key ;maybe-string
                       (default "/etc/wireguard/private.key"))
   (peers              wireguard-configuration-peers ;list of <wiregard-peer>
                       (default '()))
@@ -805,9 +805,12 @@ (define (wireguard-configuration-file config)
                     #$@(if (null? pre-up)
                            '()
                            (list (format #f "~{PreUp = ~a~%~}" pre-up)))
-                    (format #f "PostUp = ~a set %i private-key ~a\
-~{ peer ~a preshared-key ~a~}" #$(file-append wireguard "/bin/wg")
-#$private-key '#$peer-keys)
+                    (if #$private-key
+                        (format #f "PostUp = ~a set %i private-key ~a\
+~{ peer ~a preshared-key ~a~}"
+                                #$(file-append wireguard "/bin/wg")
+                                #$private-key '#$peer-keys)
+                        "")
                     #$@(if (null? post-up)
                            '()
                            (list (format #f "~{PostUp = ~a~%~}" post-up)))
@@ -838,18 +841,19 @@ (define (wireguard-activation config)
         (use-modules (guix build utils)
                      (ice-9 popen)
                      (ice-9 rdelim))
-        (mkdir-p (dirname #$private-key))
-        (unless (file-exists? #$private-key)
-          (let* ((pipe
-                  (open-input-pipe (string-append
-                                    #$(file-append wireguard "/bin/wg")
-                                    " genkey")))
-                 (key (read-line pipe)))
-            (call-with-output-file #$private-key
-              (lambda (port)
-                (display key port)))
-            (chmod #$private-key #o400)
-            (close-pipe pipe))))))
+        (when #$private-key
+          (mkdir-p (dirname #$private-key))
+          (unless (file-exists? #$private-key)
+            (let* ((pipe
+                    (open-input-pipe (string-append
+                                      #$(file-append wireguard "/bin/wg")
+                                      " genkey")))
+                   (key (read-line pipe)))
+              (call-with-output-file #$private-key
+                (lambda (port)
+                  (display key port)))
+              (chmod #$private-key #o400)
+              (close-pipe pipe)))))))
 
 ;;; XXX: Copied from (guix scripts pack), changing define to define*.
 (define-syntax-rule (define-with-source (variable args ...) body body* ...)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v2 2/2] services: wireguard: Support lists of gexps for most fields.
  2024-10-23 15:30 ` [bug#73955] [PATCH v2 0/2] Improve customizability in WireGuard service Richard Sent
  2024-10-23 15:30   ` [bug#73955] [PATCH v2 1/2] services: wireguard: Make the private-key field optional Richard Sent
@ 2024-10-23 15:30   ` Richard Sent
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-23 15:30 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, Ludovic Courtès, Maxim Cournoyer

In order to support more flexibility in Wireguard configuration, ungexp the
configuration fields directly instead of ungexp-splicing a sexp
calculator. This allows for the fields to take arbitrary gexps instead of only
strings which is particularly helpful for the Pre/Post Up/Down commands.

For example, the wg-quick(8) manual has an example on how to use
password-store to retrieve a private key with a PreUp entry. This is now
possible.

* gnu/services/vpn.scm (wireguard-configuration-file): Ungexp configuration
lists instead of ungexp-splicing the code surrounding them.
* doc/guix.texi (VPN Services)[wireguard]: Document it.

Change-Id: If074cbb78473b6fd34e0e4e990d2ed268001d6c7
---
 doc/guix.texi        | 31 +++++++++++++++++++++++++------
 gnu/services/vpn.scm | 39 ++++++++++++++++++++-------------------
 2 files changed, 45 insertions(+), 25 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 5558bd7d44..0520b24c23 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34430,13 +34430,15 @@ VPN Services
 The interface name for the VPN.
 
 @item @code{addresses} (default: @code{'("10.0.0.1/32")})
-The IP addresses to be assigned to the above interface.
+List of strings or G-expressions which represent the IP addresses to be
+assigned to the above interface.
 
 @item @code{port} (default: @code{51820})
 The port on which to listen for incoming connections.
 
 @item @code{dns} (default: @code{'())})
-The DNS server(s) to announce to VPN clients via DHCP.
+List of strings or G-expressions which represent the DNS server(s) to
+announce to VPN clients via DHCP.
 
 @item @code{monitor-ips?} (default: @code{#f})
 @cindex Dynamic IP, with Wireguard
@@ -34463,16 +34465,33 @@ VPN Services
 @var{wireguard-peer} records.
 
 @item @code{pre-up} (default: @code{'()})
-The script commands to be run before setting up the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed before setting up the interface.
+
+One example shown in the @code{wg-quick(8)} manual is retrieving a
+private key using @code{password-store}.  This can be achieved with the
+following code:
+
+@lisp
+(wireguard-configuration
+ ;; Retrieve the private key manually.
+ (private-key #f)
+ (pre-up (list #~(string-append "wg set %i private-key <("
+                                #$(file-append password-store "/bin/pass")
+                                " WireGuard/private-keys/%i)"))))
+@end lisp
 
 @item @code{post-up} (default: @code{'()})
-The script commands to be run after setting up the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed after setting up the interface.
 
 @item @code{pre-down} (default: @code{'()})
-The script commands to be run before tearing down the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed before tearing down the interface.
 
 @item @code{post-down} (default: @code{'()})
-The script commands to be run after tearing down the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed after tearing down the interface.
 
 @item @code{table} (default: @code{"auto"})
 The routing table to which routes are added, as a string.  There are two
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index b62e0ac838..c1daba5dc1 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -12,6 +12,7 @@
 ;;; Copyright © 2022 Cameron V Chaparro <cameron@cameronchaparro.com>
 ;;; Copyright © 2022 Timo Wilken <guix@twilken.net>
 ;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
+;;; Copyright © 2024 Richard Sent <richard@freakingpenguin.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -797,33 +798,33 @@ (define (wireguard-configuration-file config)
                  (define lines
                    (list
                     "[Interface]"
-                    #$@(if (null? addresses)
-                           '()
-                           (list (format #f "Address = ~{~a~^, ~}"
-                                         addresses)))
+                    (if (null? '#$addresses)
+                        ""
+                        (format #f "Address = ~{~a~^, ~}"
+                                (list #$@addresses)))
                     (format #f "~@[Table = ~a~]" #$table)
-                    #$@(if (null? pre-up)
-                           '()
-                           (list (format #f "~{PreUp = ~a~%~}" pre-up)))
+                    (if (null? '#$pre-up)
+                        ""
+                        (format #f "~{PreUp = ~a~%~}" (list #$@pre-up)))
                     (if #$private-key
                         (format #f "PostUp = ~a set %i private-key ~a\
 ~{ peer ~a preshared-key ~a~}"
                                 #$(file-append wireguard "/bin/wg")
                                 #$private-key '#$peer-keys)
                         "")
-                    #$@(if (null? post-up)
-                           '()
-                           (list (format #f "~{PostUp = ~a~%~}" post-up)))
-                    #$@(if (null? pre-down)
-                           '()
-                           (list (format #f "~{PreDown = ~a~%~}" pre-down)))
-                    #$@(if (null? post-down)
-                           '()
-                           (list (format #f "~{PostDown = ~a~%~}" post-down)))
+                    (if (null? '#$post-up)
+                        ""
+                        (format #f "~{PostUp = ~a~%~}" (list #$@post-up)))
+                    (if (null? '#$pre-down)
+                        ""
+                        (format #f "~{PreDown = ~a~%~}" (list #$@pre-down)))
+                    (if (null? '#$post-down)
+                        ""
+                        (format #f "~{PostDown = ~a~%~}" (list #$@post-down)))
                     (format #f "~@[ListenPort = ~a~]" #$port)
-                    #$@(if (null? dns)
-                           '()
-                           (list (format #f "DNS = ~{~a~^, ~}" dns)))))
+                    (if (null? '#$dns)
+                        ""
+                        (format #f "DNS = ~{~a~^, ~}" (list #$@dns)))))
 
                  (mkdir #$output)
                  (chdir #$output)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service.
  2024-10-22 21:21 [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service Richard Sent
                   ` (2 preceding siblings ...)
  2024-10-23 15:30 ` [bug#73955] [PATCH v2 0/2] Improve customizability in WireGuard service Richard Sent
@ 2024-10-23 18:20 ` Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 1/3] services: wireguard: Make the private-key field optional Richard Sent
                     ` (2 more replies)
  2024-12-04 20:59 ` [bug#73955] [PATCH v4 1/3] services: wireguard: Make the private-key field optional Richard Sent
  4 siblings, 3 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-23 18:20 UTC (permalink / raw)
  To: 73955; +Cc: Richard Sent

Hi all,

Apologies for the noise. While playing around some more I realized it
would be useful if preshared-keys also handled gexps. This allows for
constructs like

> (define (file-redirect script)
>   #~(string-append "<(" #$script ")"))
> 
> (wireguard-configuration
>  (private-key (file-redirect
>                (get-secret-program-file "foo")))
>  (peers (list (wireguard-peer
>                (public-key "X")
>                (preshared-key
>                 (file-redirect
>                  (get-secret-program-file "bar" )))))))

This results in a PostUp command like:

> PostUp = /gnu/store/.../wg set %i private-key <(/gnu/store/...wg-get-private)\
>          peer X preshared-key <(/gnu/store/...wg-get-preshared)

You could bang this together via the post-up escape hatch before v3 of
this patch, but it would be rather awkward and cause some unpleasant
linkage between peers and the interface configuration (since peers
can't specify their own postup commands).

Richard Sent (3):
  services: wireguard: Make the private-key field optional.
  services: wireguard: Support lists of gexps for most fields.
  services: wireguard: Support gexps for peer preshared keys.

 doc/guix.texi        | 36 ++++++++++++++++-----
 gnu/services/vpn.scm | 75 +++++++++++++++++++++++---------------------
 2 files changed, 69 insertions(+), 42 deletions(-)


base-commit: bd26815cf8ce38a3b03676a6e3fc482bb74247cb
-- 
2.46.0





^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v3 1/3] services: wireguard: Make the private-key field optional.
  2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
@ 2024-10-23 18:20   ` Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 2/3] services: wireguard: Support lists of gexps for most fields Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys Richard Sent
  2 siblings, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-23 18:20 UTC (permalink / raw)
  To: 73955; +Cc: Richard Sent, Ludovic Courtès, Maxim Cournoyer

Users who retrieve the private-key via a PreUp field need to be able to
disable the default retrieval mechanism.

* gnu/services/vpn.scm (<wireguard-configuration>)[private-key]: Change
comment.
(wireguard-configuration-file): Conditionally serialize private-key.
* gnu/services/vpn.scm (wireguard-activation): Do not create private-key if
the field is #f.
* doc/guix.texi (VPN Services)[wireguard-configuration]: Document it.

Change-Id: Iac419809ae94eb76e97ff1f1749e2f4b3e65bb04
---
 doc/guix.texi        |  5 ++++-
 gnu/services/vpn.scm | 36 ++++++++++++++++++++----------------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index ac3a7adef0..5558bd7d44 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34453,7 +34453,10 @@ VPN Services
 
 @item @code{private-key} (default: @code{"/etc/wireguard/private.key"})
 The private key file for the interface.  It is automatically generated
-if the file does not exist.
+if the file does not exist.  If this field is @code{#f}, a private key
+is not created and the path is not serialized to the configuration file.
+This allows for retrieving the private key programmatically with a PreUp
+command.
 
 @item @code{peers} (default: @code{'()})
 The authorized peers on this interface.  This is a list of
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index 7fb4775757..b62e0ac838 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -741,7 +741,7 @@ (define-record-type* <wireguard-configuration>
                       (default '("10.0.0.1/32")))
   (port               wireguard-configuration-port ;integer
                       (default 51820))
-  (private-key        wireguard-configuration-private-key ;string
+  (private-key        wireguard-configuration-private-key ;maybe-string
                       (default "/etc/wireguard/private.key"))
   (peers              wireguard-configuration-peers ;list of <wiregard-peer>
                       (default '()))
@@ -805,9 +805,12 @@ (define (wireguard-configuration-file config)
                     #$@(if (null? pre-up)
                            '()
                            (list (format #f "~{PreUp = ~a~%~}" pre-up)))
-                    (format #f "PostUp = ~a set %i private-key ~a\
-~{ peer ~a preshared-key ~a~}" #$(file-append wireguard "/bin/wg")
-#$private-key '#$peer-keys)
+                    (if #$private-key
+                        (format #f "PostUp = ~a set %i private-key ~a\
+~{ peer ~a preshared-key ~a~}"
+                                #$(file-append wireguard "/bin/wg")
+                                #$private-key '#$peer-keys)
+                        "")
                     #$@(if (null? post-up)
                            '()
                            (list (format #f "~{PostUp = ~a~%~}" post-up)))
@@ -838,18 +841,19 @@ (define (wireguard-activation config)
         (use-modules (guix build utils)
                      (ice-9 popen)
                      (ice-9 rdelim))
-        (mkdir-p (dirname #$private-key))
-        (unless (file-exists? #$private-key)
-          (let* ((pipe
-                  (open-input-pipe (string-append
-                                    #$(file-append wireguard "/bin/wg")
-                                    " genkey")))
-                 (key (read-line pipe)))
-            (call-with-output-file #$private-key
-              (lambda (port)
-                (display key port)))
-            (chmod #$private-key #o400)
-            (close-pipe pipe))))))
+        (when #$private-key
+          (mkdir-p (dirname #$private-key))
+          (unless (file-exists? #$private-key)
+            (let* ((pipe
+                    (open-input-pipe (string-append
+                                      #$(file-append wireguard "/bin/wg")
+                                      " genkey")))
+                   (key (read-line pipe)))
+              (call-with-output-file #$private-key
+                (lambda (port)
+                  (display key port)))
+              (chmod #$private-key #o400)
+              (close-pipe pipe)))))))
 
 ;;; XXX: Copied from (guix scripts pack), changing define to define*.
 (define-syntax-rule (define-with-source (variable args ...) body body* ...)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v3 2/3] services: wireguard: Support lists of gexps for most fields.
  2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 1/3] services: wireguard: Make the private-key field optional Richard Sent
@ 2024-10-23 18:20   ` Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys Richard Sent
  2 siblings, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-10-23 18:20 UTC (permalink / raw)
  To: 73955; +Cc: Richard Sent, Ludovic Courtès, Maxim Cournoyer

In order to support more flexibility in Wireguard configuration, ungexp the
configuration fields directly instead of ungexp-splicing a sexp
calculator. This allows for the fields to take arbitrary gexps instead of only
strings which is particularly helpful for the Pre/Post Up/Down commands.

For example, the wg-quick(8) manual has an example on how to use
password-store to retrieve a private key with a PreUp entry. This is now
possible.

* gnu/services/vpn.scm (wireguard-configuration-file): Ungexp configuration
lists instead of ungexp-splicing the code surrounding them.
* doc/guix.texi (VPN Services)[wireguard]: Document it.

Change-Id: If074cbb78473b6fd34e0e4e990d2ed268001d6c7
---
 doc/guix.texi        | 31 +++++++++++++++++++++++++------
 gnu/services/vpn.scm | 39 ++++++++++++++++++++-------------------
 2 files changed, 45 insertions(+), 25 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 5558bd7d44..0520b24c23 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34430,13 +34430,15 @@ VPN Services
 The interface name for the VPN.
 
 @item @code{addresses} (default: @code{'("10.0.0.1/32")})
-The IP addresses to be assigned to the above interface.
+List of strings or G-expressions which represent the IP addresses to be
+assigned to the above interface.
 
 @item @code{port} (default: @code{51820})
 The port on which to listen for incoming connections.
 
 @item @code{dns} (default: @code{'())})
-The DNS server(s) to announce to VPN clients via DHCP.
+List of strings or G-expressions which represent the DNS server(s) to
+announce to VPN clients via DHCP.
 
 @item @code{monitor-ips?} (default: @code{#f})
 @cindex Dynamic IP, with Wireguard
@@ -34463,16 +34465,33 @@ VPN Services
 @var{wireguard-peer} records.
 
 @item @code{pre-up} (default: @code{'()})
-The script commands to be run before setting up the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed before setting up the interface.
+
+One example shown in the @code{wg-quick(8)} manual is retrieving a
+private key using @code{password-store}.  This can be achieved with the
+following code:
+
+@lisp
+(wireguard-configuration
+ ;; Retrieve the private key manually.
+ (private-key #f)
+ (pre-up (list #~(string-append "wg set %i private-key <("
+                                #$(file-append password-store "/bin/pass")
+                                " WireGuard/private-keys/%i)"))))
+@end lisp
 
 @item @code{post-up} (default: @code{'()})
-The script commands to be run after setting up the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed after setting up the interface.
 
 @item @code{pre-down} (default: @code{'()})
-The script commands to be run before tearing down the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed before tearing down the interface.
 
 @item @code{post-down} (default: @code{'()})
-The script commands to be run after tearing down the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed after tearing down the interface.
 
 @item @code{table} (default: @code{"auto"})
 The routing table to which routes are added, as a string.  There are two
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index b62e0ac838..c1daba5dc1 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -12,6 +12,7 @@
 ;;; Copyright © 2022 Cameron V Chaparro <cameron@cameronchaparro.com>
 ;;; Copyright © 2022 Timo Wilken <guix@twilken.net>
 ;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
+;;; Copyright © 2024 Richard Sent <richard@freakingpenguin.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -797,33 +798,33 @@ (define (wireguard-configuration-file config)
                  (define lines
                    (list
                     "[Interface]"
-                    #$@(if (null? addresses)
-                           '()
-                           (list (format #f "Address = ~{~a~^, ~}"
-                                         addresses)))
+                    (if (null? '#$addresses)
+                        ""
+                        (format #f "Address = ~{~a~^, ~}"
+                                (list #$@addresses)))
                     (format #f "~@[Table = ~a~]" #$table)
-                    #$@(if (null? pre-up)
-                           '()
-                           (list (format #f "~{PreUp = ~a~%~}" pre-up)))
+                    (if (null? '#$pre-up)
+                        ""
+                        (format #f "~{PreUp = ~a~%~}" (list #$@pre-up)))
                     (if #$private-key
                         (format #f "PostUp = ~a set %i private-key ~a\
 ~{ peer ~a preshared-key ~a~}"
                                 #$(file-append wireguard "/bin/wg")
                                 #$private-key '#$peer-keys)
                         "")
-                    #$@(if (null? post-up)
-                           '()
-                           (list (format #f "~{PostUp = ~a~%~}" post-up)))
-                    #$@(if (null? pre-down)
-                           '()
-                           (list (format #f "~{PreDown = ~a~%~}" pre-down)))
-                    #$@(if (null? post-down)
-                           '()
-                           (list (format #f "~{PostDown = ~a~%~}" post-down)))
+                    (if (null? '#$post-up)
+                        ""
+                        (format #f "~{PostUp = ~a~%~}" (list #$@post-up)))
+                    (if (null? '#$pre-down)
+                        ""
+                        (format #f "~{PreDown = ~a~%~}" (list #$@pre-down)))
+                    (if (null? '#$post-down)
+                        ""
+                        (format #f "~{PostDown = ~a~%~}" (list #$@post-down)))
                     (format #f "~@[ListenPort = ~a~]" #$port)
-                    #$@(if (null? dns)
-                           '()
-                           (list (format #f "DNS = ~{~a~^, ~}" dns)))))
+                    (if (null? '#$dns)
+                        ""
+                        (format #f "DNS = ~{~a~^, ~}" (list #$@dns)))))
 
                  (mkdir #$output)
                  (chdir #$output)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys.
  2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 1/3] services: wireguard: Make the private-key field optional Richard Sent
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 2/3] services: wireguard: Support lists of gexps for most fields Richard Sent
@ 2024-10-23 18:20   ` Richard Sent
  2024-11-04  6:59     ` Mathieu Othacehe
  2 siblings, 1 reply; 16+ messages in thread
From: Richard Sent @ 2024-10-23 18:20 UTC (permalink / raw)
  To: 73955; +Cc: Richard Sent

* gnu/services/vpn.scm (wireguard-configuration-file)[lines]: Ungexp splice
with list instead of quote ungexp.

Change-Id: I50364359baafb749dc975db70478bef49e93d90c
---
 gnu/services/vpn.scm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index c1daba5dc1..6a73db78be 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -810,7 +810,7 @@ (define (wireguard-configuration-file config)
                         (format #f "PostUp = ~a set %i private-key ~a\
 ~{ peer ~a preshared-key ~a~}"
                                 #$(file-append wireguard "/bin/wg")
-                                #$private-key '#$peer-keys)
+                                #$private-key (list #$@peer-keys))
                         "")
                     (if (null? '#$post-up)
                         ""
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys.
  2024-10-23 18:20   ` [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys Richard Sent
@ 2024-11-04  6:59     ` Mathieu Othacehe
  2024-11-04 14:53       ` Richard Sent
  0 siblings, 1 reply; 16+ messages in thread
From: Mathieu Othacehe @ 2024-11-04  6:59 UTC (permalink / raw)
  To: Richard Sent; +Cc: 73955


Hello Richard,

Thanks for the updated series :)

> * gnu/services/vpn.scm (wireguard-configuration-file)[lines]: Ungexp splice
> with list instead of quote ungexp.

Do you think that it would make sense to also update the documentation
for the "preshared-key" field, to mention that it can be a gexp?

Mathieu




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys.
  2024-11-04  6:59     ` Mathieu Othacehe
@ 2024-11-04 14:53       ` Richard Sent
  0 siblings, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-11-04 14:53 UTC (permalink / raw)
  To: Mathieu Othacehe; +Cc: 73955

> Do you think that it would make sense to also update the documentation
> for the "preshared-key" field, to mention that it can be a gexp?

Makes sense to me!

> (wireguard-configuration
>  (private-key (file-redirect
>                (get-secret-program-file "foo"))))

I'm also realizing that while the wireguard.conf generated in my example is correct, we still bootstrap a private key at file path <(/gnu/store...), which isn't ideal.

We could only attempt to bootstrap "reasonable" file names (i.e. those that start with a /), but this feels icky and <(foo) is technically a valid file name.

I quite like how utilizing the private-key field for commands instead of a file path works (as opposed to a rather ugly manual postup), so perhaps a bootstrap-private-key? field should be added. As long as it defaults to #t I don't see it impacting existing setups.




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v4 1/3] services: wireguard: Make the private-key field optional.
  2024-10-22 21:21 [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service Richard Sent
                   ` (3 preceding siblings ...)
  2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
@ 2024-12-04 20:59 ` Richard Sent
  2024-12-04 20:59   ` [bug#73955] [PATCH v4 2/3] services: wireguard: Add the bootstrap-private-key? field Richard Sent
  2024-12-04 20:59   ` [bug#73955] [PATCH v4 3/3] services: wireguard: Support lists of gexps for most fields Richard Sent
  4 siblings, 2 replies; 16+ messages in thread
From: Richard Sent @ 2024-12-04 20:59 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, Ludovic Courtès, Maxim Cournoyer

Users who retrieve the private-key via a PreUp field need to be able to
disable the default retrieval mechanism.

* gnu/services/vpn.scm (<wireguard-configuration>)[private-key]: Change
comment.
(wireguard-configuration-file): Conditionally serialize private-key.
* gnu/services/vpn.scm (wireguard-activation): Do not create private-key if
the field is #f.
* doc/guix.texi (VPN Services)[wireguard-configuration]: Document it.

Change-Id: Iac419809ae94eb76e97ff1f1749e2f4b3e65bb04
---
 doc/guix.texi        |  4 +++-
 gnu/services/vpn.scm | 36 ++++++++++++++++++++----------------
 2 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index f43cb53990..fa9a147bd0 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34626,7 +34626,9 @@ VPN Services
 
 @item @code{private-key} (default: @code{"/etc/wireguard/private.key"})
 The private key file for the interface.  It is automatically generated
-if the file does not exist.
+if the file does not exist.  If this field is @code{#f}, a private key
+is not automatically created and the path is not serialized to the
+configuration file.
 
 @item @code{peers} (default: @code{'()})
 The authorized peers on this interface.  This is a list of
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index 7fb4775757..b62e0ac838 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -741,7 +741,7 @@ (define-record-type* <wireguard-configuration>
                       (default '("10.0.0.1/32")))
   (port               wireguard-configuration-port ;integer
                       (default 51820))
-  (private-key        wireguard-configuration-private-key ;string
+  (private-key        wireguard-configuration-private-key ;maybe-string
                       (default "/etc/wireguard/private.key"))
   (peers              wireguard-configuration-peers ;list of <wiregard-peer>
                       (default '()))
@@ -805,9 +805,12 @@ (define (wireguard-configuration-file config)
                     #$@(if (null? pre-up)
                            '()
                            (list (format #f "~{PreUp = ~a~%~}" pre-up)))
-                    (format #f "PostUp = ~a set %i private-key ~a\
-~{ peer ~a preshared-key ~a~}" #$(file-append wireguard "/bin/wg")
-#$private-key '#$peer-keys)
+                    (if #$private-key
+                        (format #f "PostUp = ~a set %i private-key ~a\
+~{ peer ~a preshared-key ~a~}"
+                                #$(file-append wireguard "/bin/wg")
+                                #$private-key '#$peer-keys)
+                        "")
                     #$@(if (null? post-up)
                            '()
                            (list (format #f "~{PostUp = ~a~%~}" post-up)))
@@ -838,18 +841,19 @@ (define (wireguard-activation config)
         (use-modules (guix build utils)
                      (ice-9 popen)
                      (ice-9 rdelim))
-        (mkdir-p (dirname #$private-key))
-        (unless (file-exists? #$private-key)
-          (let* ((pipe
-                  (open-input-pipe (string-append
-                                    #$(file-append wireguard "/bin/wg")
-                                    " genkey")))
-                 (key (read-line pipe)))
-            (call-with-output-file #$private-key
-              (lambda (port)
-                (display key port)))
-            (chmod #$private-key #o400)
-            (close-pipe pipe))))))
+        (when #$private-key
+          (mkdir-p (dirname #$private-key))
+          (unless (file-exists? #$private-key)
+            (let* ((pipe
+                    (open-input-pipe (string-append
+                                      #$(file-append wireguard "/bin/wg")
+                                      " genkey")))
+                   (key (read-line pipe)))
+              (call-with-output-file #$private-key
+                (lambda (port)
+                  (display key port)))
+              (chmod #$private-key #o400)
+              (close-pipe pipe)))))))
 
 ;;; XXX: Copied from (guix scripts pack), changing define to define*.
 (define-syntax-rule (define-with-source (variable args ...) body body* ...)

base-commit: e00ca95e08bc1cc2cb39f3178485ef16defce0be
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v4 2/3] services: wireguard: Add the bootstrap-private-key? field.
  2024-12-04 20:59 ` [bug#73955] [PATCH v4 1/3] services: wireguard: Make the private-key field optional Richard Sent
@ 2024-12-04 20:59   ` Richard Sent
  2024-12-04 20:59   ` [bug#73955] [PATCH v4 3/3] services: wireguard: Support lists of gexps for most fields Richard Sent
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-12-04 20:59 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, Ludovic Courtès, Maxim Cournoyer

The syntax from using the private-key field is more convenient than writing a
custom PreUp command (more formatting and preshared keys). Instead of trying
to guess if private-key is/is not a file path, add an option to disable
bootstrapping while still using private-key.

* gnu/services/vpn.scm (<wireguard-configuration>): Add
bootstrap-private-key?.
(wireguard-activation): Check bootstrap-private-key? before bootstrapping.
* doc/guix.texi (VPN Services)[wireguard]: Document it.

Change-Id: I6ba71ad58b26743057a221a54a246369022f83a5
---
 doc/guix.texi        | 19 +++++++++++++
 gnu/services/vpn.scm | 64 +++++++++++++++++++++++---------------------
 2 files changed, 53 insertions(+), 30 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index fa9a147bd0..ece73a27ae 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34630,6 +34630,25 @@ VPN Services
 is not automatically created and the path is not serialized to the
 configuration file.
 
+@item @code{bootstrap-private-key?} (default: @code{#t})
+Whether or not the private key should be generated automatically if it
+does not exist.
+
+Setting this to @code{#f} allows one to set the private key using
+command substitution.  One example shown in the @code{wg-quick(8)}
+manual is retrieving a private key using @code{password-store}.  This
+can be achieved with the following code:
+
+@lisp
+(wireguard-configuration
+ (private-key
+  #~(string-append "<("
+                   #$(file-append password-store "/bin/pass")
+                   ;; Wireguard replaces %i with the interface name.
+                   " WireGuard/private-keys/%i)")))
+@end lisp
+
+
 @item @code{peers} (default: @code{'()})
 The authorized peers on this interface.  This is a list of
 @var{wireguard-peer} records.
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index b62e0ac838..f9693fb099 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -80,6 +80,7 @@ (define-module (gnu services vpn)
             wireguard-configuration-monitor-ips?
             wireguard-configuration-monitor-ips-interval
             wireguard-configuration-private-key
+            wireguard-configuration-bootstrap-private-key?
             wireguard-configuration-peers
             wireguard-configuration-pre-up
             wireguard-configuration-post-up
@@ -733,34 +734,36 @@ (define-record-type* <wireguard-peer>
 (define-record-type* <wireguard-configuration>
   wireguard-configuration make-wireguard-configuration
   wireguard-configuration?
-  (wireguard          wireguard-configuration-wireguard ;file-like
-                      (default wireguard-tools))
-  (interface          wireguard-configuration-interface ;string
-                      (default "wg0"))
-  (addresses          wireguard-configuration-addresses ;string
-                      (default '("10.0.0.1/32")))
-  (port               wireguard-configuration-port ;integer
-                      (default 51820))
-  (private-key        wireguard-configuration-private-key ;maybe-string
-                      (default "/etc/wireguard/private.key"))
-  (peers              wireguard-configuration-peers ;list of <wiregard-peer>
-                      (default '()))
-  (dns                wireguard-configuration-dns ;list of strings
-                      (default '()))
-  (monitor-ips?       wireguard-configuration-monitor-ips? ;boolean
-                      (default #f))
-  (monitor-ips-interval wireguard-configuration-monitor-ips-interval
-                        (default '(next-minute (range 0 60 5)))) ;string | list
-  (pre-up             wireguard-configuration-pre-up ;list of strings
-                      (default '()))
-  (post-up            wireguard-configuration-post-up ;list of strings
-                      (default '()))
-  (pre-down           wireguard-configuration-pre-down ;list of strings
-                      (default '()))
-  (post-down          wireguard-configuration-post-down ;list of strings
-                      (default '()))
-  (table              wireguard-configuration-table ;string
-                      (default "auto")))
+  (wireguard              wireguard-configuration-wireguard ;file-like
+                          (default wireguard-tools))
+  (interface              wireguard-configuration-interface ;string
+                          (default "wg0"))
+  (addresses              wireguard-configuration-addresses ;string
+                          (default '("10.0.0.1/32")))
+  (port                   wireguard-configuration-port ;integer
+                          (default 51820))
+  (private-key            wireguard-configuration-private-key ;maybe-string
+                          (default "/etc/wireguard/private.key"))
+  (bootstrap-private-key? wireguard-configuration-bootstrap-private-key? ;boolean
+                          (default #t))
+  (peers                  wireguard-configuration-peers ;list of <wiregard-peer>
+                          (default '()))
+  (dns                    wireguard-configuration-dns ;list of strings
+                          (default '()))
+  (monitor-ips?           wireguard-configuration-monitor-ips? ;boolean
+                          (default #f))
+  (monitor-ips-interval   wireguard-configuration-monitor-ips-interval
+                          (default '(next-minute (range 0 60 5)))) ;string | list
+  (pre-up                 wireguard-configuration-pre-up ;list of strings
+                          (default '()))
+  (post-up                wireguard-configuration-post-up ;list of strings
+                          (default '()))
+  (pre-down               wireguard-configuration-pre-down ;list of strings
+                          (default '()))
+  (post-down              wireguard-configuration-post-down ;list of strings
+                          (default '()))
+  (table                  wireguard-configuration-table ;string
+                          (default "auto")))
 
 (define (wireguard-configuration-file config)
   (define (peer->config peer)
@@ -836,12 +839,13 @@ (define (wireguard-configuration-file config)
 
 (define (wireguard-activation config)
   (match-record config <wireguard-configuration>
-    (private-key wireguard)
+    (private-key bootstrap-private-key? wireguard)
     #~(begin
         (use-modules (guix build utils)
                      (ice-9 popen)
                      (ice-9 rdelim))
-        (when #$private-key
+        (when (and #$private-key
+                   #$bootstrap-private-key?)
           (mkdir-p (dirname #$private-key))
           (unless (file-exists? #$private-key)
             (let* ((pipe
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#73955] [PATCH v4 3/3] services: wireguard: Support lists of gexps for most fields.
  2024-12-04 20:59 ` [bug#73955] [PATCH v4 1/3] services: wireguard: Make the private-key field optional Richard Sent
  2024-12-04 20:59   ` [bug#73955] [PATCH v4 2/3] services: wireguard: Add the bootstrap-private-key? field Richard Sent
@ 2024-12-04 20:59   ` Richard Sent
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Sent @ 2024-12-04 20:59 UTC (permalink / raw)
  To: 73955; +Cc: othacehe, Richard Sent, Ludovic Courtès, Maxim Cournoyer

In order to support more flexibility in Wireguard configuration, ungexp the
configuration fields directly instead of ungexp-splicing a sexp
calculator. This allows for the fields to take arbitrary gexps instead of only
strings which is particularly helpful for the Pre/Post Up/Down commands.

* gnu/services/vpn.scm (wireguard-configuration-file): Ungexp configuration
lists instead of ungexp-splicing the code surrounding them.
* doc/guix.texi (VPN Services)[wireguard]: Document it.

Change-Id: If074cbb78473b6fd34e0e4e990d2ed268001d6c7
---
 doc/guix.texi        | 22 ++++++++++++++--------
 gnu/services/vpn.scm | 41 +++++++++++++++++++++--------------------
 2 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index ece73a27ae..43aa1ad71a 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -34603,13 +34603,15 @@ VPN Services
 The interface name for the VPN.
 
 @item @code{addresses} (default: @code{'("10.0.0.1/32")})
-The IP addresses to be assigned to the above interface.
+List of strings or G-expressions which represent the IP addresses to be
+assigned to the above interface.
 
 @item @code{port} (default: @code{51820})
 The port on which to listen for incoming connections.
 
 @item @code{dns} (default: @code{'())})
-The DNS server(s) to announce to VPN clients via DHCP.
+List of strings or G-expressions which represent the DNS server(s) to
+announce to VPN clients via DHCP.
 
 @item @code{monitor-ips?} (default: @code{#f})
 @cindex Dynamic IP, with Wireguard
@@ -34654,16 +34656,20 @@ VPN Services
 @var{wireguard-peer} records.
 
 @item @code{pre-up} (default: @code{'()})
-The script commands to be run before setting up the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed before setting up the interface.
 
 @item @code{post-up} (default: @code{'()})
-The script commands to be run after setting up the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed after setting up the interface.
 
 @item @code{pre-down} (default: @code{'()})
-The script commands to be run before tearing down the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed before tearing down the interface.
 
 @item @code{post-down} (default: @code{'()})
-The script commands to be run after tearing down the interface.
+List of strings or G-expressions.  These are script snippets which will
+be executed after tearing down the interface.
 
 @item @code{table} (default: @code{"auto"})
 The routing table to which routes are added, as a string.  There are two
@@ -34689,8 +34695,8 @@ VPN Services
 The peer public-key represented as a base64 string.
 
 @item @code{preshared-key} (default: @code{#f})
-An optional pre-shared key file for this peer.  The given file will not
-be autogenerated.
+An optional pre-shared key file for this peer that can be either a
+string or a G-expression.  The given file will not be autogenerated.
 
 @item @code{allowed-ips}
 A list of IP addresses from which incoming traffic for this peer is
diff --git a/gnu/services/vpn.scm b/gnu/services/vpn.scm
index f9693fb099..8e90032c93 100644
--- a/gnu/services/vpn.scm
+++ b/gnu/services/vpn.scm
@@ -12,6 +12,7 @@
 ;;; Copyright © 2022 Cameron V Chaparro <cameron@cameronchaparro.com>
 ;;; Copyright © 2022 Timo Wilken <guix@twilken.net>
 ;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
+;;; Copyright © 2024 Richard Sent <richard@freakingpenguin.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -800,33 +801,33 @@ (define (wireguard-configuration-file config)
                  (define lines
                    (list
                     "[Interface]"
-                    #$@(if (null? addresses)
-                           '()
-                           (list (format #f "Address = ~{~a~^, ~}"
-                                         addresses)))
+                    (if (null? '#$addresses)
+                        ""
+                        (format #f "Address = ~{~a~^, ~}"
+                                (list #$@addresses)))
                     (format #f "~@[Table = ~a~]" #$table)
-                    #$@(if (null? pre-up)
-                           '()
-                           (list (format #f "~{PreUp = ~a~%~}" pre-up)))
+                    (if (null? '#$pre-up)
+                        ""
+                        (format #f "~{PreUp = ~a~%~}" (list #$@pre-up)))
                     (if #$private-key
                         (format #f "PostUp = ~a set %i private-key ~a\
 ~{ peer ~a preshared-key ~a~}"
                                 #$(file-append wireguard "/bin/wg")
-                                #$private-key '#$peer-keys)
+                                #$private-key (list #$@peer-keys))
                         "")
-                    #$@(if (null? post-up)
-                           '()
-                           (list (format #f "~{PostUp = ~a~%~}" post-up)))
-                    #$@(if (null? pre-down)
-                           '()
-                           (list (format #f "~{PreDown = ~a~%~}" pre-down)))
-                    #$@(if (null? post-down)
-                           '()
-                           (list (format #f "~{PostDown = ~a~%~}" post-down)))
+                    (if (null? '#$post-up)
+                        ""
+                        (format #f "~{PostUp = ~a~%~}" (list #$@post-up)))
+                    (if (null? '#$pre-down)
+                        ""
+                        (format #f "~{PreDown = ~a~%~}" (list #$@pre-down)))
+                    (if (null? '#$post-down)
+                        ""
+                        (format #f "~{PostDown = ~a~%~}" (list #$@post-down)))
                     (format #f "~@[ListenPort = ~a~]" #$port)
-                    #$@(if (null? dns)
-                           '()
-                           (list (format #f "DNS = ~{~a~^, ~}" dns)))))
+                    (if (null? '#$dns)
+                        ""
+                        (format #f "DNS = ~{~a~^, ~}" (list #$@dns)))))
 
                  (mkdir #$output)
                  (chdir #$output)
-- 
2.46.0





^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2024-12-04 21:01 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-22 21:21 [bug#73955] [PATCH 0/2] Improve customizability of WireGuard service Richard Sent
2024-10-22 21:25 ` [bug#73955] [PATCH 1/2] services: wireguard: Make the private-key field optional Richard Sent
2024-10-22 21:25 ` [bug#73955] [PATCH 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
2024-10-23  9:26   ` Mathieu Othacehe
2024-10-23 15:30 ` [bug#73955] [PATCH v2 0/2] Improve customizability in WireGuard service Richard Sent
2024-10-23 15:30   ` [bug#73955] [PATCH v2 1/2] services: wireguard: Make the private-key field optional Richard Sent
2024-10-23 15:30   ` [bug#73955] [PATCH v2 2/2] services: wireguard: Support lists of gexps for most fields Richard Sent
2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
2024-10-23 18:20   ` [bug#73955] [PATCH v3 1/3] services: wireguard: Make the private-key field optional Richard Sent
2024-10-23 18:20   ` [bug#73955] [PATCH v3 2/3] services: wireguard: Support lists of gexps for most fields Richard Sent
2024-10-23 18:20   ` [bug#73955] [PATCH v3 3/3] services: wireguard: Support gexps for peer preshared keys Richard Sent
2024-11-04  6:59     ` Mathieu Othacehe
2024-11-04 14:53       ` Richard Sent
2024-12-04 20:59 ` [bug#73955] [PATCH v4 1/3] services: wireguard: Make the private-key field optional Richard Sent
2024-12-04 20:59   ` [bug#73955] [PATCH v4 2/3] services: wireguard: Add the bootstrap-private-key? field Richard Sent
2024-12-04 20:59   ` [bug#73955] [PATCH v4 3/3] services: wireguard: Support lists of gexps for most fields Richard Sent

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.