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>
This commit is contained in:
raingloom 2020-06-11 14:09:57 +02:00 committed by Julien Lepiller
parent d814246e2e
commit fe1cd098d2
No known key found for this signature in database
GPG key ID: 53D457B2D636EE82
3 changed files with 272 additions and 1 deletions

View file

@ -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

View file

@ -61,7 +61,9 @@ (define-module (gnu services networking)
#: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 @@ (define-module (gnu services networking)
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 @@ (define pagekite-service-type
"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

View file

@ -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)))