services: Add ddclient service.

* gnu/services/dns.scm (ddclient-configuration, ddclient-service-type): New
variables.
(uglify-field-name, serialize-field, serialize-boolean, serialize-integer,
serialize-string, serialize-list, serialize-extra-options,
ddclient-activation, ddclient-shepherd-service,
generate-ddclient-documentation): New procedures.
* doc/guix.texi (DNS Services): Document it.
This commit is contained in:
Oleg Pykhalov 2018-07-13 11:49:13 +03:00
parent 4db7a9dc66
commit 8490a8346b
No known key found for this signature in database
GPG Key ID: 7246E11C69B79569
2 changed files with 275 additions and 1 deletions

View File

@ -17263,6 +17263,114 @@ When false, disable negative caching.
@end table
@end deftp
@subsubheading ddclient Service
@cindex ddclient
The ddclient service described below runs the ddclient daemon, which takes
care of automatically updating DNS entries for service providers such as
@uref{https://dyn.com/dns/, Dyn}.
The following example show instantiates the service with its default
configuration:
@example
(service ddclient-service-type)
@end example
Note that ddclient needs to access credentials that are stored in a
@dfn{secret file}, by default @file{/etc/ddclient/secrets} (see
@code{secret-file} below.) You are expected to create this file manually, in
an ``out-of-band'' fashion (you @emph{could} make this file part of the
service configuration, for instance by using @code{plain-file}, but it will be
world-readable @i{via} @file{/gnu/store}.) See the examples in the
@file{share/ddclient} directory of the @code{ddclient} package.
@c %start of fragment
Available @code{ddclient-configuration} fields are:
@deftypevr {@code{ddclient-configuration} parameter} package ddclient
The ddclient package.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} integer daemon
The period after which ddclient will retry to check IP and domain name.
Defaults to @samp{300}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} boolean syslog
Use syslog for the output.
Defaults to @samp{#t}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} string mail
Mail to user.
Defaults to @samp{"root"}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} string mail-failure
Mail failed update to user.
Defaults to @samp{"root"}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} string pid
The ddclient PID file.
Defaults to @samp{"/var/run/ddclient/ddclient.pid"}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} boolean ssl
Enable SSL support.
Defaults to @samp{#t}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} string user
Specifies the user name or ID that is used when running ddclient
program.
Defaults to @samp{"ddclient"}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} string group
Group of the user who will run the ddclient program.
Defaults to @samp{"ddclient"}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} string secret-file
Secret file which will be appended to @file{ddclient.conf} file. This
file contains credentials for use by ddclient. You are expected to
create it manually.
Defaults to @samp{"/etc/ddclient/secrets.conf"}.
@end deftypevr
@deftypevr {@code{ddclient-configuration} parameter} list extra-options
Extra options will be appended to @file{ddclient.conf} file.
Defaults to @samp{()}.
@end deftypevr
@c %end of fragment
@node VPN Services
@subsubsection VPN Services
@cindex VPN (virtual private network)

View File

@ -1,5 +1,6 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 Julien Lepiller <julien@lepiller.eu>
;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@ -45,7 +46,10 @@
zone-entry
dnsmasq-service-type
dnsmasq-configuration))
dnsmasq-configuration
ddclient-service-type
ddclient-configuration))
;;;
;;; Knot DNS.
@ -670,3 +674,165 @@
(compose list dnsmasq-shepherd-service))))
(default-value (dnsmasq-configuration))
(description "Run the dnsmasq DNS server.")))
;;;
;;; ddclient
;;;
(define (uglify-field-name field-name)
(string-delete #\? (symbol->string field-name)))
(define (serialize-field field-name val)
(format #t "~a=~a\n" (uglify-field-name field-name) val))
(define (serialize-boolean field-name val)
(serialize-field field-name (if val "yes" "no")))
(define (serialize-integer field-name val)
(serialize-field field-name (number->string val)))
(define (serialize-string field-name val)
(if (and (string? val) (string=? val ""))
""
(serialize-field field-name val)))
(define (serialize-list field-name val)
(if (null? val) "" (serialize-field field-name (string-join val))))
(define (serialize-extra-options extra-options)
(string-join extra-options "\n" 'suffix))
(define-configuration ddclient-configuration
(ddclient
(package ddclient)
"The ddclient package.")
(daemon
(integer 300)
"The period after which ddclient will retry to check IP and domain name.")
(syslog
(boolean #t)
"Use syslog for the output.")
(mail
(string "root")
"Mail to user.")
(mail-failure
(string "root")
"Mail failed update to user.")
(pid
(string "/var/run/ddclient/ddclient.pid")
"The ddclient PID file.")
(ssl
(boolean #t)
"Enable SSL support.")
(user
(string "ddclient")
"Specifies the user name or ID that is used when running ddclient
program.")
(group
(string "ddclient")
"Group of the user who will run the ddclient program.")
(secret-file
(string "/etc/ddclient/secrets.conf")
"Secret file which will be appended to @file{ddclient.conf} file. This
file contains credentials for use by ddclient. You are expected to create it
manually.")
(extra-options
(list '())
"Extra options will be appended to @file{ddclient.conf} file."))
(define (ddclient-account config)
"Return the user accounts and user groups for CONFIG."
(let ((ddclient-user (ddclient-configuration-user config))
(ddclient-group (ddclient-configuration-group config)))
(list (user-group
(name ddclient-group)
(system? #t))
(user-account
(name ddclient-user)
(system? #t)
(group ddclient-group)
(comment "ddclientd privilege separation user")
(home-directory (string-append "/var/run/" ddclient-user))))))
(define (ddclient-activation config)
"Return the activation GEXP for CONFIG."
(with-imported-modules '((guix build utils)
(ice-9 rdelim))
#~(begin
(use-modules (guix build utils)
(ice-9 rdelim))
(let ((ddclient-user
#$(passwd:uid (getpw (ddclient-configuration-user config))))
(ddclient-group
#$(passwd:gid (getpw (ddclient-configuration-group config))))
(ddclient-secret-file
#$(ddclient-configuration-secret-file config)))
;; 'ddclient' complains about ddclient.conf file permissions, which
;; rules out /gnu/store. Thus we copy the ddclient.conf to /etc.
(for-each (lambda (dir)
(mkdir-p dir)
(chmod dir #o700)
(chown dir ddclient-user ddclient-group))
'("/var/cache/ddclient" "/var/run/ddclient"
"/etc/ddclient"))
(with-output-to-file "/etc/ddclient/ddclient.conf"
(lambda ()
(display
(string-append
"# Generated by 'ddclient-service'.\n\n"
#$(with-output-to-string
(lambda ()
(serialize-configuration config
ddclient-configuration-fields)))
(if (string-null? ddclient-secret-file)
""
(format #f "\n\n# Appended from '~a'.\n\n~a"
ddclient-secret-file
(with-input-from-file ddclient-secret-file
read-string)))))))
(chmod "/etc/ddclient/ddclient.conf" #o600)
(chown "/etc/ddclient/ddclient.conf"
ddclient-user ddclient-group)))))
(define (ddclient-shepherd-service config)
"Return a <shepherd-service> for ddclient with CONFIG."
(let ((ddclient (ddclient-configuration-ddclient config))
(ddclient-pid (ddclient-configuration-pid config))
(ddclient-user (ddclient-configuration-user config))
(ddclient-group (ddclient-configuration-group config)))
(list (shepherd-service
(provision '(ddclient))
(documentation "Run ddclient daemon.")
(start #~(make-forkexec-constructor
(list #$(file-append ddclient "/bin/ddclient")
"-foreground"
"-file" "/etc/ddclient/ddclient.conf")
#:pid-file #$ddclient-pid
#:environment-variables
(list "SSL_CERT_DIR=/run/current-system/profile\
/etc/ssl/certs"
"SSL_CERT_FILE=/run/current-system/profile\
/etc/ssl/certs/ca-certificates.crt")
#:user #$ddclient-user
#:group #$ddclient-group))
(stop #~(make-kill-destructor))))))
(define ddclient-service-type
(service-type
(name 'ddclient)
(extensions
(list (service-extension account-service-type
ddclient-account)
(service-extension shepherd-root-service-type
ddclient-shepherd-service)
(service-extension activation-service-type
ddclient-activation)))
(default-value (ddclient-configuration))
(description "Configure address updating utility for dynamic DNS services,
ddclient.")))
(define (generate-ddclient-documentation)
(generate-documentation
`((ddclient-configuration ,ddclient-configuration-fields))
'ddclient-configuration))