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
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ 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] 13+ 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
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ 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] 13+ 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
  2024-10-23 18:20 ` [bug#73955] [PATCH v3 0/3] Improve customizability of WireGuard service Richard Sent
  3 siblings, 1 reply; 13+ 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] 13+ 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; 13+ 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] 13+ 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
  3 siblings, 2 replies; 13+ 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] 13+ 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; 13+ 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] 13+ 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; 13+ 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] 13+ 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)
  3 siblings, 3 replies; 13+ 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] 13+ 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; 13+ 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] 13+ 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; 13+ 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] 13+ 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; 13+ 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] 13+ 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; 13+ 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] 13+ 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; 13+ 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] 13+ messages in thread

end of thread, other threads:[~2024-11-04 14:54 UTC | newest]

Thread overview: 13+ 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

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.