From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56812) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fkuut-0003L6-0u for guix-patches@gnu.org; Wed, 01 Aug 2018 13:28:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fkuuo-0003bm-Ur for guix-patches@gnu.org; Wed, 01 Aug 2018 13:28:07 -0400 Received: from debbugs.gnu.org ([208.118.235.43]:32892) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fkuuo-0003ay-L3 for guix-patches@gnu.org; Wed, 01 Aug 2018 13:28:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1fkuun-0002Yx-VS for guix-patches@gnu.org; Wed, 01 Aug 2018 13:28:01 -0400 Subject: [bug#32141] [PATCH] services: Add ddclient service. Resent-Message-ID: From: Oleg Pykhalov References: <20180713145854.12250-1-go.wigust@gmail.com> <87lga7wokr.fsf@gnu.org> <87effrpynp.fsf@gmail.com> <87o9eu2xl1.fsf@gnu.org> Date: Wed, 01 Aug 2018 20:27:38 +0300 In-Reply-To: <87o9eu2xl1.fsf@gnu.org> ("Ludovic \=\?utf-8\?Q\?Court\=C3\=A8s\=22'\?\= \=\?utf-8\?Q\?s\?\= message of "Thu, 26 Jul 2018 10:51:30 +0200") Message-ID: <874lgengj9.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+kyle=kyleam.com@gnu.org Sender: "Guix-patches" To: Ludovic =?UTF-8?Q?Court=C3=A8s?= Cc: 32141@debbugs.gnu.org --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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=C3=A8s) writes: [=E2=80=A6] >> Also, the generated =E2=80=98ddclient.conf=E2=80=99 which contains secre= ts is stored in >> the store. I probably should change the =E2=80=98ddclient-activation=E2= =80=99 procedure >> >> (copy-file #$(plain-file "ddclient.conf" config-str) file) >> >> to a procedure which writes =E2=80=98config-str=E2=80=99 to the file wit= hout storing it >> somewhere else. WDYT? > > The problem would be the same: the activation script would contain > =E2=80=98config-str=E2=80=99, 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 =E2=80=9Cinclude=E2=80=9D 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 =E2=80=98/etc/ddclient=E2=80=99 directory for secrets file, be= cause ddclient program use this directory by default? =2D-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 =2D-8<---------------cut here---------------end--------------->8--- --=-=-= Content-Type: text/x-patch; charset=utf-8 Content-Disposition: attachment; filename=0001-services-Add-ddclient-service.patch Content-Transfer-Encoding: quoted-printable Content-Description: [PATCH] services: Add ddclient service. From=203f47ae60ecb2e8780c451e93976b5c83135d8420 Mon Sep 17 00:00:00 2001 From: Oleg Pykhalov 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. =2D-- 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 =2D-- a/doc/guix.texi +++ b/doc/guix.texi @@ -17211,6 +17211,109 @@ When false, disable negative caching. @end table @end deftp =20 +@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 =2D-- a/gnu/services/dns.scm +++ b/gnu/services/dns.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2017 Julien Lepiller +;;; Copyright =C2=A9 2018 Oleg Pykhalov ;;; ;;; This file is part of GNU Guix. ;;; @@ -45,7 +46,10 @@ zone-entry =20 dnsmasq-service-type =2D dnsmasq-configuration)) + dnsmasq-configuration + + ddclient-service-type + ddclient-configuration)) =20 ;;; ;;; Knot DNS. @@ -670,3 +674,163 @@ (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=3D~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=3D? 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, wh= ich + ;; 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-fiel= ds))) + (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 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=3D/run/current-system/profile\ +/etc/ssl/certs" + "SSL_CERT_FILE=3D/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 servic= es, +ddclient."))) + +(define (generate-ddclient-documentation) + (generate-documentation + `((ddclient-configuration ,ddclient-configuration-fields)) + 'ddclient-configuration)) =2D-=20 2.18.0 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEc+OyAXw1EaDPCmAPckbhHGm3lWkFAlth7YoACgkQckbhHGm3 lWkHmw//ccEedT1wvTUJfBnn0pMDvynGpsE4R6EWK605yYmbA3wSY0ffYxGH5FWJ KF6KwLCej+jpelOsTD1ZdVkRALasVMihJybcxcjoT1XJjBEjJZ+o2bTFIxwuMORg ouo7I0Ua9qNQ2+xQrvCzpkMswkHEX1O+UntXzosLHEyYPzw3NdyDOvwMWetPcZ7F RCC5RIf3oav0d7FRKPGiGGmKfPrvVwsA7pb7PJx39DFAou2CLBVRBbtPK1mp/DAV wykjqojIPUaIWJxpVjWQ799mTnjFzPAtnOOkmore9HdJ/w9E7abP55ryqYMNugJ6 CskFE/a7v4RhFxaqy8tQ4/s/pMpuGyfvEe/9/43/Maa9X2c/IoNg6poIPJm7LhxB bsCO8VlgxwjHIzA1Rsvu4D5e+osO2STGvw7vcv3obIiosD0t3Fihve7oF5rfFp54 hUSwBAZ+lh5n7m0r4sVEW/CUu/hNEai6+vjCpSiVLKAB1FlYi4GGkQE2/8iy9RU9 Fpy+O+uPNpDUAFMdfci2bHgYPMPMGZXdnMIsOiynaIwKcgC6DQ2feETKNwyXYQdC DKaP+eC5aK1V5Gg5E/8bw/CQXvc2zH0ol+695XjmfN41p7mHO//qgAZoo4Y+OoyY DPyb8VedoyRdcnjioRCjmw4fdlAUhnDPezZEeKan5eVZtMUdJ1s= =zbMP -----END PGP SIGNATURE----- --==-=-=--