summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorraingloom <raingloom@protonmail.com>2020-06-11 14:09:57 +0200
committerJulien Lepiller <julien@lepiller.eu>2020-11-05 18:45:40 +0100
commitfe1cd098d2b83737e96f19438612291f5a9316e4 (patch)
tree7e9085dabc9abc611d92a083659ec0906a91a667
parentd814246e2ebc4bb65d3714fcd9a6285553a8c092 (diff)
services: Add yggdrasil-service-type.
* gnu/services/networking.scm (yggdrasil-configuration) (yggdrasil-configuration?, yggdrasil-configuration-package) (yggdrasil-configuration-auto-conf, yggdrasil-configuration-log-level) (yggdrasil-configuration-log-to): New procedures. (yggdrasil-service-type): New variable. * doc/guix.texi: Document it. * gnu/system/examples/yggdrasil.tmpl: Provide example. Signed-off-by: Julien Lepiller <julien@lepiller.eu>
-rw-r--r--doc/guix.texi96
-rw-r--r--gnu/services/networking.scm117
-rw-r--r--gnu/system/examples/yggdrasil.tmpl60
3 files changed, 272 insertions, 1 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index b7f1bc1f00..217ed7a8a8 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -82,6 +82,7 @@ Copyright @copyright{} 2020 Pierre Langlois@*
Copyright @copyright{} 2020 pinoaffe@*
Copyright @copyright{} 2020 André Batista@*
Copyright @copyright{} 2020 Alexandru-Sergiu Marton@*
+Copyright @copyright{} 2020 raingloom@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -16848,6 +16849,101 @@ Use this to add additional options and manage shared secrets out-of-band.
@end table
@end deftp
+@defvr {Scheme Variable} yggdrasil-service-type
+The service type for connecting to the @uref{https://yggdrasil-network.github.io/,
+Yggdrasil network}, an early-stage implementation of a fully end-to-end
+encrypted IPv6 network.
+
+@quotation
+Yggdrasil provides name-independent routing with cryptographically generated
+addresses. Static addressing means you can keep the same address as long as
+you want, even if you move to a new location, or generate a new address (by
+generating new keys) whenever you want.
+@uref{https://yggdrasil-network.github.io/2018/07/28/addressing.html}
+@end quotation
+
+Pass it a value of @code{yggdrasil-configuration} to connect it to public
+peers and/or local peers.
+
+Here is an example using public peers and a static address. The static
+signing and encryption keys are defined in @file{/etc/yggdrasil-private.conf}
+(the default value for @code{config-file}).
+
+@lisp
+;; part of the operating-system declaration
+(service yggdrasil-service-type
+ (yggdrasil-configuration
+ (autoconf? #f) ;; use only the public peers
+ (json-config
+ ;; choose one from
+ ;; https://github.com/yggdrasil-network/public-peers
+ '((peers . #("tcp://1.2.3.4:1337"))))
+ ;; /etc/yggdrasil-private.conf is the default value for config-file
+ ))
+@end lisp
+@example
+# sample content for /etc/yggdrasil-private.conf
+@{
+ # Your public encryption key. Your peers may ask you for this to put
+ # into their AllowedEncryptionPublicKeys configuration.
+ EncryptionPublicKey: 378dc5...
+
+ # Your private encryption key. DO NOT share this with anyone!
+ EncryptionPrivateKey: 0777...
+
+ # Your public signing key. You should not ordinarily need to share
+ # this with anyone.
+ SigningPublicKey: e1664...
+
+ # Your private signing key. DO NOT share this with anyone!
+ SigningPrivateKey: 0589d...
+@}
+@end example
+@end defvr
+
+@deftp {Data Type} yggdrasil-configuration
+Data type representing the configuration of Yggdrasil.
+
+@table @asis
+@item @code{package} (default: @code{yggdrasil})
+Package object of Yggdrasil.
+
+@item @code{json-config} (default: @code{'()})
+Contents of @file{/etc/yggdrasil.conf}. Will be merged with
+@file{/etc/yggdrasil-private.conf}. Note that these settings are stored in
+the Guix store, which is readable to all users. @strong{Do not store your
+private keys in it}. See the output of @code{yggdrasil -genconf} for a
+quick overview of valid keys and their default values.
+
+@item @code{autoconf?} (default: @code{#f})
+Whether to use automatic mode. Enabling it makes Yggdrasil use adynamic IP
+and peer with IPv6 neighbors.
+
+@item @code{log-level} (default: @code{'info})
+How much detail to include in logs. Use @code{'debug} for more detail.
+
+@item @code{log-to} (default: @code{'stdout})
+Where to send logs. By default, the service logs standard output to
+@file{/var/log/yggdrasil.log}. The alternative is @code{'syslog}, which
+sends output to the running syslog service.
+
+@item @code{config-file} (default: @code{"/etc/yggdrasil-private.conf"})
+What HJSON file to load sensitive data from. This is where private keys
+should be stored, which are necessary to specify if you don't want a
+randomized address after each restart. Use @code{#f} to disable. Options
+defined in this file take precedence over @code{json-config}. Use the output
+of @code{yggdrasil -genconf} as a starting point. To configure a static
+address, delete everything except these options:
+
+@itemize
+@item @code{EncryptionPublicKey}
+@item @code{EncryptionPrivateKey}
+@item @code{SigningPublicKey}
+@item @code{SigningPrivateKey}
+@end itemize
+@end table
+@end deftp
+
@node Unattended Upgrades
@subsection Unattended Upgrades
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index 64f54e787f..9ec0f6a9ca 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -61,7 +61,9 @@
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-26)
+ #:use-module (srfi srfi-43)
#:use-module (ice-9 match)
+ #:use-module (json)
#:re-export (static-networking-service
static-networking-service-type)
#:export (%facebook-host-aliases
@@ -180,7 +182,17 @@
pagekite-configuration-kitesecret
pagekite-configuration-frontend
pagekite-configuration-kites
- pagekite-configuration-extra-file))
+ pagekite-configuration-extra-file
+
+ yggdrasil-service-type
+ yggdrasil-configuration
+ yggdrasil-configuration?
+ yggdrasil-configuration-autoconf?
+ yggdrasil-configuration-config-file
+ yggdrasil-configuration-log-level
+ yggdrasil-configuration-log-to
+ yggdrasil-configuration-json-config
+ yggdrasil-configuration-package))
;;; Commentary:
;;;
@@ -1750,4 +1762,107 @@ table inet filter {
"Run @url{https://pagekite.net/,PageKite}, a tunneling solution to make
local servers publicly accessible on the web, even behind NATs and firewalls.")))
+
+;;;
+;;; Yggdrasil
+;;;
+
+(define-record-type* <yggdrasil-configuration>
+ yggdrasil-configuration
+ make-yggdrasil-configuration
+ yggdrasil-configuration?
+ (package yggdrasil-configuration-package
+ (default yggdrasil))
+ (json-config yggdrasil-configuration-json-config
+ (default '()))
+ (config-file yggdrasil-config-file
+ (default "/etc/yggdrasil-private.conf"))
+ (autoconf? yggdrasil-configuration-autoconf?
+ (default #f))
+ (log-level yggdrasil-configuration-log-level
+ (default 'info))
+ (log-to yggdrasil-configuration-log-to
+ (default 'stdout)))
+
+(define (yggdrasil-configuration-file config)
+ (define (scm->yggdrasil-json x)
+ (define key-value?
+ dotted-list?)
+ (define (param->camel str)
+ (string-concatenate
+ (map
+ string-capitalize
+ (string-split str (cut eqv? <> #\-)))))
+ (cond
+ ((key-value? x)
+ (let ((k (car x))
+ (v (cdr x)))
+ (cons
+ (if (symbol? k)
+ (param->camel (symbol->string k))
+ k)
+ v)))
+ ((list? x) (map scm->yggdrasil-json x))
+ ((vector? x) (vector-map scm->yggdrasil-json x))
+ (else x)))
+ (computed-file
+ "yggdrasil.conf"
+ #~(call-with-output-file #$output
+ (lambda (port)
+ ;; it's HJSON, so comments are a-okay
+ (display "# Generated by yggdrasil-service\n" port)
+ (display #$(scm->json-string
+ (scm->yggdrasil-json
+ (yggdrasil-configuration-json-config config)))
+ port)))))
+
+(define (yggdrasil-shepherd-service config)
+ "Return a <shepherd-service> for yggdrasil with CONFIG."
+ (define yggdrasil-command
+ #~(append
+ (list (string-append
+ #$(yggdrasil-configuration-package config)
+ "/bin/yggdrasil")
+ "-useconffile"
+ #$(yggdrasil-configuration-file config))
+ (if #$(yggdrasil-configuration-autoconf? config)
+ '("-autoconf")
+ '())
+ (let ((extraconf #$(yggdrasil-config-file config)))
+ (if extraconf
+ (list "-extraconffile" extraconf)
+ '()))
+ (list "-loglevel"
+ #$(symbol->string
+ (yggdrasil-configuration-log-level config))
+ "-logto"
+ #$(symbol->string
+ (yggdrasil-configuration-log-to config)))))
+ (list (shepherd-service
+ (documentation "Connect to the Yggdrasil mesh network")
+ (provision '(yggdrasil))
+ (requirement '(networking))
+ (start #~(make-forkexec-constructor
+ #$yggdrasil-command
+ #:log-file "/var/log/yggdrasil.log"
+ #:group "yggdrasil"))
+ (stop #~(make-kill-destructor)))))
+
+(define %yggdrasil-accounts
+ (list (user-group (name "yggdrasil") (system? #t))))
+
+(define yggdrasil-service-type
+ (service-type
+ (name 'yggdrasil)
+ (description
+ "Connect to the Yggdrasil mesh network.
+See yggdrasil -genconf for config options.")
+ (extensions
+ (list (service-extension shepherd-root-service-type
+ yggdrasil-shepherd-service)
+ (service-extension account-service-type
+ (const %yggdrasil-accounts))
+ (service-extension profile-service-type
+ (compose list yggdrasil-configuration-package))))))
+
;;; networking.scm ends here
diff --git a/gnu/system/examples/yggdrasil.tmpl b/gnu/system/examples/yggdrasil.tmpl
new file mode 100644
index 0000000000..be80bf4de9
--- /dev/null
+++ b/gnu/system/examples/yggdrasil.tmpl
@@ -0,0 +1,60 @@
+;; This is an operating system configuration template
+;; for a "bare bones" setup, with no X11 display server.
+
+(use-modules (gnu))
+(use-service-modules networking ssh)
+(use-package-modules admin curl networking screen)
+
+(operating-system
+ (host-name "ruby-guard-5545")
+ (timezone "Europe/Budapest")
+ (locale "en_US.utf8")
+
+ ;; Boot in "legacy" BIOS mode, assuming /dev/sdX is the
+ ;; target hard disk, and "my-root" is the label of the target
+ ;; root file system.
+ (bootloader (bootloader-configuration
+ (bootloader grub-bootloader)
+ (target "/dev/sdX")))
+ (file-systems (cons (file-system
+ (device (file-system-label "my-root"))
+ (mount-point "/")
+ (type "ext4"))
+ %base-file-systems))
+ (users (cons (user-account
+ (name "alice")
+ (comment "Bob's sister")
+ (group "users")
+ ;; adding her to the yggdrasil group means she can use
+ ;; yggdrasilctl to modify the configuration
+ (supplementary-groups '("wheel" "yggdrasil")))
+ %base-user-accounts))
+
+ ;; Globally-installed packages.
+ (packages (cons* screen curl %base-packages))
+
+ ;; Add services to the baseline: a DHCP client and
+ ;; an SSH server.
+ ;; If you add an /etc/yggdrasil-private.conf, you can log in to ssh
+ ;; using your Yggdrasil IPv6 address from another machine running Yggdrasil.
+ ;; Alternatively, the client can sit behind a router that has Yggdrasil.
+ ;; That file is specifically _not_ handled by Guix, because we don't want its
+ ;; contents to sit in the world-readable /gnu/store.
+ (services
+ (append
+ (list
+ (service dhcp-client-service-type)
+ (service yggdrasil-service-type
+ (yggdrasil-configuration
+ (log-to 'stdout)
+ (log-level 'debug)
+ (autoconf? #f)
+ (json-config
+ ;; choose a few from
+ ;; https://github.com/yggdrasil-network/public-peers
+ '((peers . #("tcp://1.2.3.4:1337"))))
+ (config-file #f)))
+ (service openssh-service-type
+ (openssh-configuration
+ (port-number 2222))))
+ %base-services)))