Subject: [bug#73955] [PATCH v4 2/3] services: wireguard: Add the bootstrap-private-key? field.

From: Richard Sent <[email-masked]>
Date: Wed, 4 Dec 2024 15:59:34 -0500

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