* [bug#32141] [PATCH] services: Add ddclient service.
@ 2018-07-13 14:58 Oleg Pykhalov
2018-07-19 9:40 ` Ludovic Courtès
0 siblings, 1 reply; 7+ messages in thread
From: Oleg Pykhalov @ 2018-07-13 14:58 UTC (permalink / raw)
To: 32141
* gnu/services/dns.scm (ddclient-configuration, opaque-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, generate-opaque-ddclient-documentation): New
procedures.
* doc/guix.texi (DNS Services): Document it.
---
doc/guix.texi | 107 +++++++++++++++++++++++++++++++++
gnu/services/dns.scm | 137 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 243 insertions(+), 1 deletion(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index eaec4c422..fcc7c0037 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -17123,6 +17123,113 @@ When false, disable negative caching.
@end table
@end deftp
+@subsubheading ddclient Service
+
+@cindex ddclient
+@uref{https://sourceforge.net/projects/ddclient/, ddclient} is an address
+updating utility for dynamic DNS services.
+
+The following example will configure the service with values from
+@file{ddclient.conf} file. You could get a @file{ddclient.conf} sample from
+@code{ddclient} package.
+
+@example
+(use-modules (ice-9 textual-ports))
+
+(service ddclient-service-type
+ (opaque-ddclient-configuration
+ (ddclient-conf
+ (call-with-input-file "ddclient.conf"
+ get-string-all))))
+@end example
+
+@c %start of fragment
+
+Available @code{opaque-ddclient-configuration} fields are:
+
+@deftypevr {@code{opaque-ddclient-configuration} parameter} package ddclient
+The ddclient package.
+
+@end deftypevr
+
+@deftypevr {@code{opaque-ddclient-configuration} parameter} string ddclient-conf
+The contents of the @file{ddclient.conf} to use.
+
+@end deftypevr
+
+@deftypevr {@code{opaque-ddclient-configuration} parameter} string pid
+The ddclient PID file.
+
+Defaults to @samp{"/var/run/ddclient.pid"}.
+
+@end deftypevr
+
+
+@c %end of fragment
+
+
+@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.pid"}.
+
+@end deftypevr
+
+@deftypevr {@code{ddclient-configuration} parameter} boolean ssl
+Enable SSL support.
+
+Defaults to @samp{#t}.
+
+@end deftypevr
+
+@deftypevr {@code{ddclient-configuration} parameter} list extra-options
+Extra options will be appended to ddclient configuration file.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+
+@c %end of fragment
+
+
@node VPN Services
@subsubsection VPN Services
@cindex VPN (virtual private network)
diff --git a/gnu/services/dns.scm b/gnu/services/dns.scm
index 2c57a36b8..7a3184b42 100644
--- a/gnu/services/dns.scm
+++ b/gnu/services/dns.scm
@@ -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,11 @@
zone-entry
dnsmasq-service-type
- dnsmasq-configuration))
+ dnsmasq-configuration
+
+ ddclient-service-type
+ ddclient-configuration
+ opaque-ddclient-configuration))
;;;
;;; Knot DNS.
@@ -670,3 +675,133 @@
(compose list dnsmasq-shepherd-service))))
(default-value (dnsmasq-configuration))
(description "Run the dnsmasq DNS server.")))
+
+\f
+;;;
+;;; 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.pid")
+ "The ddclient PID file.")
+ (ssl
+ (boolean #t)
+ "Enable SSL support.")
+ (extra-options
+ (list '())
+ "Extra options will be appended to ddclient configuration file."))
+
+(define-configuration opaque-ddclient-configuration
+ (ddclient
+ (package ddclient)
+ "The ddclient package.")
+ (ddclient-conf
+ (string (configuration-missing-field 'opaque-ddclient-configuration
+ 'ddclient-conf))
+ "The contents of the @file{ddclient.conf} to use.")
+ (pid
+ (string "/var/run/ddclient.pid")
+ "The ddclient PID file."))
+
+(define (ddclient-activation config)
+ "Return the activation GEXP for CONFIG."
+ (let ((config-str
+ (if (opaque-ddclient-configuration? config)
+ (opaque-ddclient-configuration-ddclient-conf config)
+ (with-output-to-string
+ (lambda ()
+ (serialize-configuration config
+ ddclient-configuration-fields))))))
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+ (mkdir-p "/var/cache/ddclient")
+ ;; 'ddclient' complains about ddclient.conf file permissions, which
+ ;; rules out /gnu/store. Thus we copy the ddclient.conf to /etc.
+ (mkdir-p "/etc/ddclient")
+ (let ((file "/etc/ddclient/ddclient.conf"))
+ (copy-file #$(plain-file "ddclient.conf" config-str) file)
+ (chmod file #o600))))))
+
+(define (ddclient-shepherd-service config)
+ "Return a <shepherd-service> for ddclient with CONFIG."
+ (let* ((opaque-config? (opaque-ddclient-configuration? config))
+ (pid (if opaque-config?
+ (opaque-ddclient-configuration-pid config)
+ (ddclient-configuration-pid config)))
+ (ddclient (if opaque-config?
+ (opaque-ddclient-configuration-ddclient config)
+ (ddclient-configuration-ddclient 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"
+ "-debug" "-verbose")
+ #:pid-file #$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")))
+ (stop #~(make-kill-destructor))))))
+
+(define ddclient-service-type
+ (service-type
+ (name 'ddclient)
+ (extensions
+ (list (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))
+
+(define (generate-opaque-ddclient-documentation)
+ (generate-documentation
+ `((opaque-ddclient-configuration ,opaque-ddclient-configuration-fields))
+ 'opaque-ddclient-configuration))
--
2.18.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [bug#32141] [PATCH] services: Add ddclient service.
2018-07-13 14:58 [bug#32141] [PATCH] services: Add ddclient service Oleg Pykhalov
@ 2018-07-19 9:40 ` Ludovic Courtès
2018-07-25 7:22 ` Oleg Pykhalov
0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2018-07-19 9:40 UTC (permalink / raw)
To: Oleg Pykhalov; +Cc: 32141
Hi Oleg,
Oleg Pykhalov <go.wigust@gmail.com> skribis:
> * gnu/services/dns.scm (ddclient-configuration, opaque-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, generate-opaque-ddclient-documentation): New
> procedures.
> * doc/guix.texi (DNS Services): Document it.
[...]
> +@subsubheading ddclient Service
> +
> +@cindex ddclient
> +@uref{https://sourceforge.net/projects/ddclient/, ddclient} is an address
> +updating utility for dynamic DNS services.
It would be nice to expound a bit, like:
The ddclient service described below runs the ddclient daemon, which
takes care of automatically updating DNS entries for service providers
such as DynDNS.com.
Also, is there a better home page?
Otherwise LGTM!
> + (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"
> + "-debug" "-verbose")
> + #:pid-file #$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")))
> + (stop #~(make-kill-destructor))))))
Does it run as root? If there’s no option to run it (mostly) as
non-root, perhaps it would make sense to try using
‘make-forkexec-constructor/container’ here (as a separate patch.)
WDYT?
Thank you,
Ludo’.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [bug#32141] [PATCH] services: Add ddclient service.
2018-07-19 9:40 ` Ludovic Courtès
@ 2018-07-25 7:22 ` Oleg Pykhalov
2018-07-26 8:51 ` Ludovic Courtès
0 siblings, 1 reply; 7+ messages in thread
From: Oleg Pykhalov @ 2018-07-25 7:22 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 32141
[-- Attachment #1: Type: text/plain, Size: 2949 bytes --]
Hello Ludovic,
Thank you for review.
ludo@gnu.org (Ludovic Courtès) writes:
> Oleg Pykhalov <go.wigust@gmail.com> skribis:
>
>> * gnu/services/dns.scm (ddclient-configuration, opaque-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, generate-opaque-ddclient-documentation): New
>> procedures.
>> * doc/guix.texi (DNS Services): Document it.
>
> [...]
>
>> +@subsubheading ddclient Service
>> +
>> +@cindex ddclient
>> +@uref{https://sourceforge.net/projects/ddclient/, ddclient} is an address
>> +updating utility for dynamic DNS services.
>
> It would be nice to expound a bit, like:
>
> The ddclient service described below runs the ddclient daemon, which
> takes care of automatically updating DNS entries for service providers
> such as DynDNS.com.
OK. I improved little bit with “such as @uref{https://dyn.com/dns/,
Dyn}.” if you don't mind.
> Also, is there a better home page?
I think no. I found http://ddclient.sf.net/ in Debian package recipe
[1], but ‘curl -Ik --location http://ddclient.sf.net/’ returns a
https://sourceforge.net/p/ddclient/wiki/Home/ URI.
> Otherwise LGTM!
>
>> + (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"
>> + "-debug" "-verbose")
>> + #:pid-file #$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")))
>> + (stop #~(make-kill-destructor))))))
>
> Does it run as root? If there’s no option to run it (mostly) as
> non-root, perhaps it would make sense to try using
> ‘make-forkexec-constructor/container’ here (as a separate patch.)
>
> WDYT?
It did run as root. I've succeeded to run it with ‘ddclient’ user.
Also, the generated ‘ddclient.conf’ which contains secrets is stored in
the store. I probably should change the ‘ddclient-activation’ procedure
--8<---------------cut here---------------start------------->8---
(copy-file #$(plain-file "ddclient.conf" config-str) file)
--8<---------------cut here---------------end--------------->8---
to a procedure which writes ‘config-str’ to the file without storing it
somewhere else. WDYT?
[1] https://packages.debian.org/stretch/ddclient
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* [bug#32141] [PATCH] services: Add ddclient service.
2018-07-25 7:22 ` Oleg Pykhalov
@ 2018-07-26 8:51 ` Ludovic Courtès
2018-08-01 17:27 ` Oleg Pykhalov
0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2018-07-26 8:51 UTC (permalink / raw)
To: Oleg Pykhalov; +Cc: 32141
Hi Oleg,
Oleg Pykhalov <go.wigust@gmail.com> skribis:
> ludo@gnu.org (Ludovic Courtès) writes:
[...]
>>> +@subsubheading ddclient Service
>>> +
>>> +@cindex ddclient
>>> +@uref{https://sourceforge.net/projects/ddclient/, ddclient} is an address
>>> +updating utility for dynamic DNS services.
>>
>> It would be nice to expound a bit, like:
>>
>> The ddclient service described below runs the ddclient daemon, which
>> takes care of automatically updating DNS entries for service providers
>> such as DynDNS.com.
>
> OK. I improved little bit with “such as @uref{https://dyn.com/dns/,
> Dyn}.” if you don't mind.
Sure.
>> Does it run as root? If there’s no option to run it (mostly) as
>> non-root, perhaps it would make sense to try using
>> ‘make-forkexec-constructor/container’ here (as a separate patch.)
>>
>> WDYT?
>
> It did run as root. I've succeeded to run it with ‘ddclient’ user.
Awesome.
> Also, the generated ‘ddclient.conf’ which contains secrets is stored in
> the store. I probably should change the ‘ddclient-activation’ procedure
>
> (copy-file #$(plain-file "ddclient.conf" config-str) file)
>
> to a procedure which writes ‘config-str’ to the file without storing it
> somewhere else. WDYT?
The problem would be the same: the activation script would contain
‘config-str’, and it would live in the store.
In short we must not manipulate secrets in anything that goes through
the store. The only thing I can suggest is to leave it up to the
user to create a file containing the secret in an out-of-band fashion;
/etc is a good place for such things.
For example, they could create /etc/ddclient-secrets and then we would
somehow arrange to get that file read.
To do that there are two possibilities that come to mind:
1. If the config file syntax has an “include” directive, just include
/etc/ddclient-secrets unconditionally in the generated config file.
2. Write an activation snippet that concatenates the generated config
file with /etc/ddclient-secrets and stores that as
/etc/ddclient.conf (or something like that.)
Thoughts?
Ludo’.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [bug#32141] [PATCH] services: Add ddclient service.
2018-07-26 8:51 ` Ludovic Courtès
@ 2018-08-01 17:27 ` Oleg Pykhalov
2018-08-27 11:22 ` Ludovic Courtès
0 siblings, 1 reply; 7+ messages in thread
From: Oleg Pykhalov @ 2018-08-01 17:27 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 32141
[-- Attachment #1.1: Type: text/plain, Size: 2165 bytes --]
Hello Ludovic,
I applied all your suggestions and updated the documentation. The patch
is attached below. I run a ddclient service from this patch currently.
ludo@gnu.org (Ludovic Courtès) writes:
[…]
>> Also, the generated ‘ddclient.conf’ which contains secrets is stored in
>> the store. I probably should change the ‘ddclient-activation’ procedure
>>
>> (copy-file #$(plain-file "ddclient.conf" config-str) file)
>>
>> to a procedure which writes ‘config-str’ to the file without storing it
>> somewhere else. WDYT?
>
> The problem would be the same: the activation script would contain
> ‘config-str’, and it would live in the store.
>
> In short we must not manipulate secrets in anything that goes through
> the store. The only thing I can suggest is to leave it up to the
> user to create a file containing the secret in an out-of-band fashion;
> /etc is a good place for such things.
>
> For example, they could create /etc/ddclient-secrets and then we would
> somehow arrange to get that file read.
>
> To do that there are two possibilities that come to mind:
>
> 1. If the config file syntax has an “include” directive, just include
> /etc/ddclient-secrets unconditionally in the generated config file.
>
> 2. Write an activation snippet that concatenates the generated config
> file with /etc/ddclient-secrets and stores that as
> /etc/ddclient.conf (or something like that.)
>
> Thoughts?
Could we use ‘/etc/ddclient’ directory for secrets file, because
ddclient program use this directory by default?
--8<---------------cut here---------------start------------->8---
The following example will configure the service.
By default, the @code{secret-file} in @code{ddclient-configuration} is
pointing to @file{/etc/ddclient/secrets.conf} file, which will be appended to
@file{/etc/ddclient/ddclient.conf} and should be created in advance. See
samples inside @file{/share/ddclient} directory of @code{ddclient} package.
@example
(service ddclient-service-type)
@end example
--8<---------------cut here---------------end--------------->8---
[-- Attachment #1.2: [PATCH] services: Add ddclient service. --]
[-- Type: text/x-patch, Size: 10810 bytes --]
From 3f47ae60ecb2e8780c451e93976b5c83135d8420 Mon Sep 17 00:00:00 2001
From: Oleg Pykhalov <go.wigust@gmail.com>
Date: Fri, 13 Jul 2018 11:49:13 +0300
Subject: [PATCH] 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.
---
doc/guix.texi | 103 +++++++++++++++++++++++++++
gnu/services/dns.scm | 166 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 268 insertions(+), 1 deletion(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index 080b091b3..e08bfe059 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -17211,6 +17211,109 @@ 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 will configure the service.
+
+By default, the @code{secret-file} in @code{ddclient-configuration} is
+pointing to @file{/etc/ddclient/secrets.conf} file, which will be appended to
+@file{/etc/ddclient/ddclient.conf} and should be created in advance. See
+samples inside @file{/share/ddclient} directory of @code{ddclient} package.
+
+@example
+(service ddclient-service-type)
+@end example
+
+
+@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 ddclient.conf file.
+
+Defaults to @samp{"/etc/ddclient/secrets.conf"}.
+
+@end deftypevr
+
+@deftypevr {@code{ddclient-configuration} parameter} list extra-options
+Extra options will be appended to ddclient configuration file.
+
+Defaults to @samp{()}.
+
+@end deftypevr
+
+
+@c %end of fragment
+
+
@node VPN Services
@subsubsection VPN Services
@cindex VPN (virtual private network)
diff --git a/gnu/services/dns.scm b/gnu/services/dns.scm
index 2c57a36b8..7ac61dfca 100644
--- a/gnu/services/dns.scm
+++ b/gnu/services/dns.scm
@@ -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,163 @@
(compose list dnsmasq-shepherd-service))))
(default-value (dnsmasq-configuration))
(description "Run the dnsmasq DNS server.")))
+
+\f
+;;;
+;;; 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 ddclient.conf file.")
+ (extra-options
+ (list '())
+ "Extra options will be appended to ddclient configuration 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))
--
2.18.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [bug#32141] [PATCH] services: Add ddclient service.
2018-08-01 17:27 ` Oleg Pykhalov
@ 2018-08-27 11:22 ` Ludovic Courtès
2018-08-29 22:45 ` bug#32141: " Oleg Pykhalov
0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2018-08-27 11:22 UTC (permalink / raw)
To: Oleg Pykhalov; +Cc: 32141
Hi Oleg,
Sorry for the delay, I had forgotten about this patch. (Feel free to
ping when that happens!)
Oleg Pykhalov <go.wigust@gmail.com> skribis:
> I applied all your suggestions and updated the documentation. The patch
> is attached below. I run a ddclient service from this patch currently.
Neat.
> ludo@gnu.org (Ludovic Courtès) writes:
[...]
>> In short we must not manipulate secrets in anything that goes through
>> the store. The only thing I can suggest is to leave it up to the
>> user to create a file containing the secret in an out-of-band fashion;
>> /etc is a good place for such things.
>>
>> For example, they could create /etc/ddclient-secrets and then we would
>> somehow arrange to get that file read.
>>
>> To do that there are two possibilities that come to mind:
>>
>> 1. If the config file syntax has an “include” directive, just include
>> /etc/ddclient-secrets unconditionally in the generated config file.
>>
>> 2. Write an activation snippet that concatenates the generated config
>> file with /etc/ddclient-secrets and stores that as
>> /etc/ddclient.conf (or something like that.)
>>
>> Thoughts?
>
> Could we use ‘/etc/ddclient’ directory for secrets file, because
> ddclient program use this directory by default?
Sure.
> From 3f47ae60ecb2e8780c451e93976b5c83135d8420 Mon Sep 17 00:00:00 2001
> From: Oleg Pykhalov <go.wigust@gmail.com>
> Date: Fri, 13 Jul 2018 11:49:13 +0300
> Subject: [PATCH] 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.
[...]
> +By default, the @code{secret-file} in @code{ddclient-configuration} is
> +pointing to @file{/etc/ddclient/secrets.conf} file, which will be appended to
> +@file{/etc/ddclient/ddclient.conf} and should be created in advance. See
> +samples inside @file{/share/ddclient} directory of @code{ddclient} package.
I propose slightly different wording, to make it clear that users are
expected to provide the secret file:
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.
WDYT?
> +@deftypevr {@code{ddclient-configuration} parameter} string secret-file
> +Secret file which will be appended to ddclient.conf file.
^
@file{ddclient.conf}
Maybe add:
This file contains credentials for use by ddclient. You are expected
to create it manually.
> +Defaults to @samp{"/etc/ddclient/secrets.conf"}.
OK with changes along these lines.
Thank you!
Ludo’.
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#32141: [PATCH] services: Add ddclient service.
2018-08-27 11:22 ` Ludovic Courtès
@ 2018-08-29 22:45 ` Oleg Pykhalov
0 siblings, 0 replies; 7+ messages in thread
From: Oleg Pykhalov @ 2018-08-29 22:45 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 32141-done
[-- Attachment #1: Type: text/plain, Size: 2010 bytes --]
Hi Ludovic,
ludo@gnu.org (Ludovic Courtès) writes:
> Sorry for the delay, I had forgotten about this patch. (Feel free to
> ping when that happens!)
No problem. OK. Feel free the same and thank you for pinging me.
> Oleg Pykhalov <go.wigust@gmail.com> skribis:
[…]
>> +By default, the @code{secret-file} in @code{ddclient-configuration} is
>> +pointing to @file{/etc/ddclient/secrets.conf} file, which will be appended to
>> +@file{/etc/ddclient/ddclient.conf} and should be created in advance. See
>> +samples inside @file{/share/ddclient} directory of @code{ddclient} package.
>
> I propose slightly different wording, to make it clear that users are
> expected to provide the secret file:
>
> 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.
>
> WDYT?
It looks more clear. I will apply this, thanks.
>> +@deftypevr {@code{ddclient-configuration} parameter} string secret-file
>> +Secret file which will be appended to ddclient.conf file.
> ^
> @file{ddclient.conf}
>
> Maybe add:
>
> This file contains credentials for use by ddclient. You are expected
> to create it manually.
>
>> +Defaults to @samp{"/etc/ddclient/secrets.conf"}.
Applied.
> OK with changes along these lines.
Pushed as 8490a8346b5c8207f5798be55bea1de865b0bd42
Thanks,
Oleg.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2018-08-29 22:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-13 14:58 [bug#32141] [PATCH] services: Add ddclient service Oleg Pykhalov
2018-07-19 9:40 ` Ludovic Courtès
2018-07-25 7:22 ` Oleg Pykhalov
2018-07-26 8:51 ` Ludovic Courtès
2018-08-01 17:27 ` Oleg Pykhalov
2018-08-27 11:22 ` Ludovic Courtès
2018-08-29 22:45 ` bug#32141: " Oleg Pykhalov
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).