diff mbox

[2/2] services: Add tlsdate-service.

Message ID 20161205183101.5937-3-ng0@libertad.pw
State New
Headers show

Commit Message

ng0 Dec. 5, 2016, 6:31 p.m. UTC
* gnu/services/networking.scm (<tlsdate-configuration>): New record type.
(%tlsdate-accounts): New variables.
(tlsdate-shepherd-service): New procedure.
(tlsdate-service-type): New variable.
* doc/guix.texi (Networking Services): Document it.
---
 doc/guix.texi               | 32 +++++++++++++++++
 gnu/services/networking.scm | 84 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

Comments

Chris Marusich Dec. 7, 2016, 7:18 a.m. UTC | #1
Hi ng0!

Neat, I never knew about tlsdate until now!

ng0 <ng0@libertad.pw> writes:

> * gnu/services/networking.scm (<tlsdate-configuration>): New record type.
> (%tlsdate-accounts): New variables.
> (tlsdate-shepherd-service): New procedure.
> (tlsdate-service-type): New variable.
> * doc/guix.texi (Networking Services): Document it.
> ---
>  doc/guix.texi               | 32 +++++++++++++++++
>  gnu/services/networking.scm | 84 ++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 115 insertions(+), 1 deletion(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 4d7f96d90..f6efd040d 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -8594,6 +8594,38 @@ make an initial adjustment of more than 1,000 seconds.
>  List of host names used as the default NTP servers.
>  @end defvr
>  
> +@cindex tlsdate
> +@deffn {Scheme Procedure} tlsdate-service [#:config (tlsdate-configuration)]
> +
> +Return a service that runs @command{tlsdate}, a simple TCP based time service.
> +The daemon will synchronize the system clock with a server of your
> +choice via TCP at boot.

When you said TCP, did you mean TLS?

Are we running the daemon, or are we just running the tlsdate command
once at boot?

> +The optional @var{config} argument should be a
> +@code{<tlsdate-configuration>} object, by default it syncs the time with gnu.org.
> +
> +@end deffn
> +
> +@deftp {Data Type} tlsdate-configuration
> +Data type representing the configuration of tlsdate.
> +
> +@table @asis
> +@item @code{package} (default: @var{tlsdate})
> +Package object of the tlsdate time service.
> +
> +@item @code{port} (default: @var{'()})
> +Set the port of the remote hostname which should be used.
> +
> +@item @code{host} (default: @var{"gnu.org"})
> +Set the remote hostname which will be queried. Defaults to @code{gnu.org}.

I've briefly read about tlsdate.  Looks like it's a hack to sync time
from a "trusted" source using TLS.  Since this trust will vary by user,
wouldn't it be better to leave this field to the discretion of the user?

I think one could also argue that to be good Internet neighbors, we
should avoid putting a default hostname in here, to avoid spamming one
specific host by default with all the tlsdate traffic from this service.

> +@item @code{extra-options} (default: @var{'()})
> +Extra options will be passed to @code{tlsdate}, please run
> +@command{man tlsdate} for more information.
> +
> +@end table
> +@end deftp
> +
>  @cindex Tor
>  @deffn {Scheme Procedure} tor-service [@var{config-file}] [#:tor @var{tor}]
>  Return a service to run the @uref{https://torproject.org, Tor} anonymous
> diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
> index d672ecf68..52a899b8f 100644
> --- a/gnu/services/networking.scm
> +++ b/gnu/services/networking.scm
> @@ -3,6 +3,7 @@
>  ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
>  ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
>  ;;; Copyright © 2016 John Darrington <jmd@gnu.org>
> +;;; Copyright © 2016 ng0 <ng0@libertad.pw>
>  ;;;
>  ;;; This file is part of GNU Guix.
>  ;;;
> @@ -66,7 +67,13 @@
>              wicd-service
>              network-manager-service
>              connman-service
> -            wpa-supplicant-service-type))
> +            wpa-supplicant-service-type
> +
> +            tlsdate-service
> +            tlsdate-configuration
> +            tlsdate-service-type
> +            tlsdate-configuration?
> +            tlsdate-configuration))
>  
>  ;;; Commentary:
>  ;;;
> @@ -360,6 +367,81 @@ make an initial adjustment of more than 1,000 seconds."
>  
>  
>  ;;;
> +;;; tlsdate
> +;;;
> +
> +(define-record-type* <tlsdate-configuration>
> +  tlsdate-configuration make-tlsdate-configuration
> +  tlsdate-configuration?
> +  (package        tlsdate-configuration-package
> +                  (default tlsdate))
> +  (host           tlsdate-configuration-host
> +                  (default "gnu.org"))
> +  (port           tlsdate-configuration-port
> +                  (default #f))
> +  (extra-options  tlsdate-configuration-extra-options
> +                  (default '())))
> +
> +(define %tlsdate-accounts
> +  (list (user-group (name "tlsdate") (system? #t))
> +        (user-account
> +         (name "tlsdate")
> +         (group "tlsdate")
> +         (system? #t)
> +         (comment "tlsdate daemon user")

Is this really a daemon?  It looks like we're just invoking a command
which runs once at boot, but perhaps I'm mistaken.

> +         (home-directory "/var/empty")
> +         (shell (file-append shadow "/sbin/nologin")))))
> +
> +(define tlsdate-shepherd-service
> +  (match-lambda
> +    (($ <tlsdate-configuration>
> +        package host port extra-options)
> +     (let* ((tlsdate (file-append package "/bin/tlsdate"))
> +            (command `(,tlsdate
> +                       "-l" ; leap
> +                       "-t" ; timewarp
> +                       ,@(if host
> +                             `(,(string-append
> +                                 "-H" " " host))
> +                             '())
> +                       ,@(if port
> +                             `(,(string-append
> +                                 "-p" " " (number->string port)))
> +                             '())
> +                       ,@extra-options)))
> +       (list (shepherd-service
> +              ;;(provision '(tlsdate))
> +              (provision '(ntp))
> +              ;; tlsdate needs at least one network interface to be up, hence the
> +              ;; dependency on 'loopback'.
> +              (requirement '(user-processes loopback syslogd))
> +
> +              (start #~(make-forkexec-constructor '#$command

Just so I'm clear here, you've written '#$command in the gexp here
because when command is expanded via ungexp (#$), it will be expanded
into a list, and you intend to pass that list literally to the
make-forkexec-constructor procedure (at the time the gexp is run), which
is why you used quote (').  Right?

> +                                                  #:user "tlsdate"
> +                                                  #:group "tlsdate"))
> +              (stop #~(make-kill-destructor))

Does this "service" actually spawn a long-running process?  If not, will
this destructor actually be used?  If it IS used, will it send a signal
to a non-existent process (or worse, a process that happens to share the
same PID as the one we previously spawned)?  Will Shepherd repeatedly
re-spawn the "service"?  I'm still learning how Shepherd services work,
so if I'm missing something obvious, please let me know.

> +              (documentation "Run the tlsdate service.")))))))
> +
> +(define tlsdate-service-type
> +  (service-type
> +   (name 'tlsdate)
> +   (extensions
> +    (list (service-extension shepherd-root-service-type
> +                             tlsdate-shepherd-service)
> +          (service-extension account-service-type
> +                             (const %tlsdate-accounts))))))
> +
> +(define* (tlsdate-service #:key (config (tlsdate-configuration)))
> +  "Return a service that runs @command{tlsdate}, a simple TCP based
> +time service.

When you said TCP, did you mean TLS?

> +The optional @var{config} argument should be a
> +@code{<tlsdate-configuration>} object, by default it querries gnu.org
> +for time once at boot."
> +  (service tlsdate-service-type config))

When I talked with davexunit on IRC about doing something with a
side-effect once at boot, he was not in support of the idea [1], and I
agree he was right about that.  Maybe this tlsdate service is a little
different since it's happening once at EVERY boot instead of just the
very first one.  However, if we're going to add a tlsdate service,
wouldn't it make sense to use tlsdated instead of invoking tlsdate once?

Alternatively, if using tlsdated is difficult for some reason, is it
feasible to hold off on adding this service?  It seems to me like you
could accomplish what you need by running tlsdate ad-hoc when you need
it, or perhaps by configuring your own mcron job to run it periodically
(see: (guix) Scheduled Job Execution).  Again, I might be missing
something, so please let me know if that isn't a feasible alternative to
this service you're proposing.

[1] See https://gnunet.org/bot/log/guix/2016-11-30#T1216852 (excerpt follows):

[14:29:15]	<marusich>	davexunit, I see. Cool. Also, is there a way to do something "one time at first boot" in a GuixSD system, I wonder?
[14:29:44]	<davexunit>	marusich: no
[14:29:52]	<davexunit>	that goes against everything GuixSD is about
[14:30:08]	<davexunit>	if the only the first generation of a system did some side-effect
[14:30:14]	<davexunit>	it would be hard to reproduce elsewhere
ng0 Dec. 7, 2016, 12:04 p.m. UTC | #2
Chris Marusich <cmmarusich@gmail.com> writes:

> Hi ng0!
>
> Neat, I never knew about tlsdate until now!
>
> ng0 <ng0@libertad.pw> writes:
>
>> * gnu/services/networking.scm (<tlsdate-configuration>): New record type.
>> (%tlsdate-accounts): New variables.
>> (tlsdate-shepherd-service): New procedure.
>> (tlsdate-service-type): New variable.
>> * doc/guix.texi (Networking Services): Document it.
>> ---
>>  doc/guix.texi               | 32 +++++++++++++++++
>>  gnu/services/networking.scm | 84 ++++++++++++++++++++++++++++++++++++++++++++-
>>  2 files changed, 115 insertions(+), 1 deletion(-)
>>
>> diff --git a/doc/guix.texi b/doc/guix.texi
>> index 4d7f96d90..f6efd040d 100644
>> --- a/doc/guix.texi
>> +++ b/doc/guix.texi
>> @@ -8594,6 +8594,38 @@ make an initial adjustment of more than 1,000 seconds.
>>  List of host names used as the default NTP servers.
>>  @end defvr
>>  
>> +@cindex tlsdate
>> +@deffn {Scheme Procedure} tlsdate-service [#:config (tlsdate-configuration)]
>> +
>> +Return a service that runs @command{tlsdate}, a simple TCP based time service.
>> +The daemon will synchronize the system clock with a server of your
>> +choice via TCP at boot.
>
> When you said TCP, did you mean TLS?

It depends. I understand it as being different from ntp, but I
think TLS would also be correct.

> Are we running the daemon, or are we just running the tlsdate command
> once at boot?

The tlsdate command, but see further below.

>> +The optional @var{config} argument should be a
>> +@code{<tlsdate-configuration>} object, by default it syncs the time with gnu.org.
>> +
>> +@end deffn
>> +
>> +@deftp {Data Type} tlsdate-configuration
>> +Data type representing the configuration of tlsdate.
>> +
>> +@table @asis
>> +@item @code{package} (default: @var{tlsdate})
>> +Package object of the tlsdate time service.
>> +
>> +@item @code{port} (default: @var{'()})
>> +Set the port of the remote hostname which should be used.
>> +
>> +@item @code{host} (default: @var{"gnu.org"})
>> +Set the remote hostname which will be queried. Defaults to @code{gnu.org}.
>
> I've briefly read about tlsdate.  Looks like it's a hack to sync time
> from a "trusted" source using TLS.  Since this trust will vary by user,
> wouldn't it be better to leave this field to the discretion of the user?

The problem is, it defaults to google.com if we leave it
blank. I think this can be patched in the config it comes
with. But then again you could argue that so many people use
google that not using google and differing from the default would
make it obvious? I don't know much about tlsdate at the moment,
but I'm sure Jacob had an opinion and reasons why google.com was
picked.
sidenote: For my live-system I'm in the process of porting
another date/time application to Guix which eventually could
serve as a base for a gnunet based time service at some
point. The application I port uses hidden-services for getting
the time, so it's not ideal in my use case which is why tlsdate
comes before that (tor, potentially dangerous to people).

> I think one could also argue that to be good Internet neighbors, we
> should avoid putting a default hostname in here, to avoid spamming one
> specific host by default with all the tlsdate traffic from this service.
>
>> +@item @code{extra-options} (default: @var{'()})
>> +Extra options will be passed to @code{tlsdate}, please run
>> +@command{man tlsdate} for more information.
>> +
>> +@end table
>> +@end deftp
>> +
>>  @cindex Tor
>>  @deffn {Scheme Procedure} tor-service [@var{config-file}] [#:tor @var{tor}]
>>  Return a service to run the @uref{https://torproject.org, Tor} anonymous
>> diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
>> index d672ecf68..52a899b8f 100644
>> --- a/gnu/services/networking.scm
>> +++ b/gnu/services/networking.scm
>> @@ -3,6 +3,7 @@
>>  ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
>>  ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
>>  ;;; Copyright © 2016 John Darrington <jmd@gnu.org>
>> +;;; Copyright © 2016 ng0 <ng0@libertad.pw>
>>  ;;;
>>  ;;; This file is part of GNU Guix.
>>  ;;;
>> @@ -66,7 +67,13 @@
>>              wicd-service
>>              network-manager-service
>>              connman-service
>> -            wpa-supplicant-service-type))
>> +            wpa-supplicant-service-type
>> +
>> +            tlsdate-service
>> +            tlsdate-configuration
>> +            tlsdate-service-type
>> +            tlsdate-configuration?
>> +            tlsdate-configuration))
>>  
>>  ;;; Commentary:
>>  ;;;
>> @@ -360,6 +367,81 @@ make an initial adjustment of more than 1,000 seconds."
>>  
>>  
>>  ;;;
>> +;;; tlsdate
>> +;;;
>> +
>> +(define-record-type* <tlsdate-configuration>
>> +  tlsdate-configuration make-tlsdate-configuration
>> +  tlsdate-configuration?
>> +  (package        tlsdate-configuration-package
>> +                  (default tlsdate))
>> +  (host           tlsdate-configuration-host
>> +                  (default "gnu.org"))
>> +  (port           tlsdate-configuration-port
>> +                  (default #f))
>> +  (extra-options  tlsdate-configuration-extra-options
>> +                  (default '())))
>> +
>> +(define %tlsdate-accounts
>> +  (list (user-group (name "tlsdate") (system? #t))
>> +        (user-account
>> +         (name "tlsdate")
>> +         (group "tlsdate")
>> +         (system? #t)
>> +         (comment "tlsdate daemon user")
>
> Is this really a daemon?  It looks like we're just invoking a command
> which runs once at boot, but perhaps I'm mistaken.

No, you are correct. I wanted to check out how the reaction and
feedback towards a one-time service at boot were, but I'll take
the feedback at the bottom of this message and switch back to the
tlsdated, which has some problems and isn't as easy as tlsdate.

>> +         (home-directory "/var/empty")
>> +         (shell (file-append shadow "/sbin/nologin")))))
>> +
>> +(define tlsdate-shepherd-service
>> +  (match-lambda
>> +    (($ <tlsdate-configuration>
>> +        package host port extra-options)
>> +     (let* ((tlsdate (file-append package "/bin/tlsdate"))
>> +            (command `(,tlsdate
>> +                       "-l" ; leap
>> +                       "-t" ; timewarp
>> +                       ,@(if host
>> +                             `(,(string-append
>> +                                 "-H" " " host))
>> +                             '())
>> +                       ,@(if port
>> +                             `(,(string-append
>> +                                 "-p" " " (number->string port)))
>> +                             '())
>> +                       ,@extra-options)))
>> +       (list (shepherd-service
>> +              ;;(provision '(tlsdate))
>> +              (provision '(ntp))
>> +              ;; tlsdate needs at least one network interface to be up, hence the
>> +              ;; dependency on 'loopback'.
>> +              (requirement '(user-processes loopback syslogd))
>> +
>> +              (start #~(make-forkexec-constructor '#$command
>
> Just so I'm clear here, you've written '#$command in the gexp here
> because when command is expanded via ungexp (#$), it will be expanded
> into a list, and you intend to pass that list literally to the
> make-forkexec-constructor procedure (at the time the gexp is run), which
> is why you used quote (').  Right?

I can respond to that once I've read more into shepherd and
gexp. Currently I just break until it's no longer broken, which
obviously is not ideal but it's one way to learn.

>> +                                                  #:user "tlsdate"
>> +                                                  #:group "tlsdate"))
>> +              (stop #~(make-kill-destructor))
>
> Does this "service" actually spawn a long-running process?  If not, will
> this destructor actually be used?  If it IS used, will it send a signal
> to a non-existent process (or worse, a process that happens to share the
> same PID as the one we previously spawned)?  Will Shepherd repeatedly
> re-spawn the "service"?  I'm still learning how Shepherd services work,
> so if I'm missing something obvious, please let me know.

Okay, this was written based on tlsdated and then rewritten but I
left some parts unchanged. This explains the "respawn until
shepherd switches tlsdate off" behavior.

>> +              (documentation "Run the tlsdate service.")))))))
>> +
>> +(define tlsdate-service-type
>> +  (service-type
>> +   (name 'tlsdate)
>> +   (extensions
>> +    (list (service-extension shepherd-root-service-type
>> +                             tlsdate-shepherd-service)
>> +          (service-extension account-service-type
>> +                             (const %tlsdate-accounts))))))
>> +
>> +(define* (tlsdate-service #:key (config (tlsdate-configuration)))
>> +  "Return a service that runs @command{tlsdate}, a simple TCP based
>> +time service.
>
> When you said TCP, did you mean TLS?

Adding to what I replied the first time you asked this, let's be
consistent and say just TLS.

>> +The optional @var{config} argument should be a
>> +@code{<tlsdate-configuration>} object, by default it querries gnu.org
>> +for time once at boot."
>> +  (service tlsdate-service-type config))
>
> When I talked with davexunit on IRC about doing something with a
> side-effect once at boot, he was not in support of the idea [1], and I
> agree he was right about that.  Maybe this tlsdate service is a little
> different since it's happening once at EVERY boot instead of just the
> very first one.  However, if we're going to add a tlsdate service,
> wouldn't it make sense to use tlsdated instead of invoking tlsdate once?
>
> Alternatively, if using tlsdated is difficult for some reason, is it
> feasible to hold off on adding this service?  It seems to me like you
> could accomplish what you need by running tlsdate ad-hoc when you need
> it, or perhaps by configuring your own mcron job to run it periodically
> (see: (guix) Scheduled Job Execution).  Again, I might be missing
> something, so please let me know if that isn't a feasible alternative to
> this service you're proposing.

My intention is to provide a service which does get the time,
regulary, but does not talk to the outside too much.
If the delay for tlsdated is set (can be part of the daemon
options) to something reasonable as default (for example 1 hour,
for my purposes I can shift it then or just use an mcron job as
you mentioned), I think this won't be an issue.
I don't think that a time service which just runs once will be an
issue, but I'd like to be proven wrong. Nothing bad happens when
ntp is run and that's also started at first boot of first
generation and continous to be started in every generation
afterwards. I think what you were talking about (in the excerpt)
is different to tlsdate.
But as a conclusion to the reasons you listed and what I've
written, I'll change this service back to tlsdated (and rename it
to tlsdated).

If our issue tracker would already be public I could link you to
more specific reasons and discussion, but so far: just assume I'm
building a system around/integrated into GuixSD which after core
(phase one) targets piece by piece to eliminate the need to fetch
information through the old internet and rather use gnunet for
those tasks. That's not easy to achieve (not in a very short
time), but this tlsdate is an intermediate solution.

**
There's an related issue:
Every service I currently work on absolutely requires network to
be tested (well except `psyced` which can cope fine just
locally), would the qemu be able to talk to outside if I created
an network bridge? Or is there more to be added? I know I had
this dicussion in the past but obviously it did not work for me
as I'm still sitting on an 90% finished 'in theory it works'
gnunet service for guix.
**

> [1] See https://gnunet.org/bot/log/guix/2016-11-30#T1216852 (excerpt follows):
>
> [14:29:15]	<marusich>	davexunit, I see. Cool. Also, is there a way to do something "one time at first boot" in a GuixSD system, I wonder?
> [14:29:44]	<davexunit>	marusich: no
> [14:29:52]	<davexunit>	that goes against everything GuixSD is about
> [14:30:08]	<davexunit>	if the only the first generation of a system did some side-effect
> [14:30:14]	<davexunit>	it would be hard to reproduce elsewhere
>
> -- 
> Chris
Chris Marusich Dec. 9, 2016, 6:29 a.m. UTC | #3
ng0 <ng0@libertad.pw> writes:

> The problem is, it defaults to google.com if we leave it
> blank. I think this can be patched in the config it comes
> with. But then again you could argue that so many people use
> google that not using google and differing from the default would
> make it obvious? I don't know much about tlsdate at the moment,
> but I'm sure Jacob had an opinion and reasons why google.com was
> picked.

I see.  I'd say just use the default that comes with the package.  If a
user needs to update it to something else, they probably know what
they're doing and whom they trust.

>> Is this really a daemon?  It looks like we're just invoking a command
>> which runs once at boot, but perhaps I'm mistaken.
>
> No, you are correct. I wanted to check out how the reaction and
> feedback towards a one-time service at boot were, but I'll take
> the feedback at the bottom of this message and switch back to the
> tlsdated, which has some problems and isn't as easy as tlsdate.

I'm not 100% certain that "run a command once at boot (every time we
boot)" is bad, but I do think that if we can use the daemon instead, it
is obviously a better fit for the "service" model.

> Adding to what I replied the first time you asked this, let's be
> consistent and say just TLS.

Cool.  I don't know much about tlsdate, though.  If in fact it is
getting the timestamp from TCP, then the word "TCP" seems correct.
However, based on what I've read [1], tcpdate gets the time from the TLS
handshake [1], so "TLS" seems correct to me.

> I don't think that a time service which just runs once will be an
> issue, but I'd like to be proven wrong.

You're probably right about this.  I think I may have overreacted.  I
think that practically speaking, a "service" which just runs tlsdate
once at boot (every time we boot) is a little ugly (because it's a
stretch to say that it's a "service"), but it's not bad.  However, I do
still think that tlsdated is the natural fit for the "service" model,
since it is a daemon, and tlsdate is not.  So why not use it?

I agree: I think the problem David and I were discussing earlier in IRC
is different, and uglier.  For details, please refer to the IRC log.

> If our issue tracker would already be public I could link you to
> more specific reasons and discussion, but so far: just assume I'm
> building a system around/integrated into GuixSD which after core
> (phase one) targets piece by piece to eliminate the need to fetch
> information through the old internet and rather use gnunet for
> those tasks. That's not easy to achieve (not in a very short
> time), but this tlsdate is an intermediate solution.

Sounds cool!

> **
> There's an related issue:
> Every service I currently work on absolutely requires network to
> be tested (well except `psyced` which can cope fine just
> locally), would the qemu be able to talk to outside if I created
> an network bridge? Or is there more to be added? I know I had
> this dicussion in the past but obviously it did not work for me
> as I'm still sitting on an 90% finished 'in theory it works'
> gnunet service for guix.
> **

There are many ways to launch a qemu virtual machine.  If you use "the
right" combination of options, your guest will be able send IP packets
to other hosts on the Internet.  I'd be happy to help troubleshoot
whatever problems you're having - if you're interested, please contact
me privately (or start a new email thread) so we don't derail this email
thread.
diff mbox

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 4d7f96d90..f6efd040d 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -8594,6 +8594,38 @@  make an initial adjustment of more than 1,000 seconds.
 List of host names used as the default NTP servers.
 @end defvr
 
+@cindex tlsdate
+@deffn {Scheme Procedure} tlsdate-service [#:config (tlsdate-configuration)]
+
+Return a service that runs @command{tlsdate}, a simple TCP based time service.
+The daemon will synchronize the system clock with a server of your
+choice via TCP at boot.
+
+The optional @var{config} argument should be a
+@code{<tlsdate-configuration>} object, by default it syncs the time with gnu.org.
+
+@end deffn
+
+@deftp {Data Type} tlsdate-configuration
+Data type representing the configuration of tlsdate.
+
+@table @asis
+@item @code{package} (default: @var{tlsdate})
+Package object of the tlsdate time service.
+
+@item @code{port} (default: @var{'()})
+Set the port of the remote hostname which should be used.
+
+@item @code{host} (default: @var{"gnu.org"})
+Set the remote hostname which will be queried. Defaults to @code{gnu.org}.
+
+@item @code{extra-options} (default: @var{'()})
+Extra options will be passed to @code{tlsdate}, please run
+@command{man tlsdate} for more information.
+
+@end table
+@end deftp
+
 @cindex Tor
 @deffn {Scheme Procedure} tor-service [@var{config-file}] [#:tor @var{tor}]
 Return a service to run the @uref{https://torproject.org, Tor} anonymous
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index d672ecf68..52a899b8f 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -3,6 +3,7 @@ 
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 John Darrington <jmd@gnu.org>
+;;; Copyright © 2016 ng0 <ng0@libertad.pw>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -66,7 +67,13 @@ 
             wicd-service
             network-manager-service
             connman-service
-            wpa-supplicant-service-type))
+            wpa-supplicant-service-type
+
+            tlsdate-service
+            tlsdate-configuration
+            tlsdate-service-type
+            tlsdate-configuration?
+            tlsdate-configuration))
 
 ;;; Commentary:
 ;;;
@@ -360,6 +367,81 @@  make an initial adjustment of more than 1,000 seconds."
 
 
 ;;;
+;;; tlsdate
+;;;
+
+(define-record-type* <tlsdate-configuration>
+  tlsdate-configuration make-tlsdate-configuration
+  tlsdate-configuration?
+  (package        tlsdate-configuration-package
+                  (default tlsdate))
+  (host           tlsdate-configuration-host
+                  (default "gnu.org"))
+  (port           tlsdate-configuration-port
+                  (default #f))
+  (extra-options  tlsdate-configuration-extra-options
+                  (default '())))
+
+(define %tlsdate-accounts
+  (list (user-group (name "tlsdate") (system? #t))
+        (user-account
+         (name "tlsdate")
+         (group "tlsdate")
+         (system? #t)
+         (comment "tlsdate daemon user")
+         (home-directory "/var/empty")
+         (shell (file-append shadow "/sbin/nologin")))))
+
+(define tlsdate-shepherd-service
+  (match-lambda
+    (($ <tlsdate-configuration>
+        package host port extra-options)
+     (let* ((tlsdate (file-append package "/bin/tlsdate"))
+            (command `(,tlsdate
+                       "-l" ; leap
+                       "-t" ; timewarp
+                       ,@(if host
+                             `(,(string-append
+                                 "-H" " " host))
+                             '())
+                       ,@(if port
+                             `(,(string-append
+                                 "-p" " " (number->string port)))
+                             '())
+                       ,@extra-options)))
+       (list (shepherd-service
+              ;;(provision '(tlsdate))
+              (provision '(ntp))
+              ;; tlsdate needs at least one network interface to be up, hence the
+              ;; dependency on 'loopback'.
+              (requirement '(user-processes loopback syslogd))
+
+              (start #~(make-forkexec-constructor '#$command
+                                                  #:user "tlsdate"
+                                                  #:group "tlsdate"))
+              (stop #~(make-kill-destructor))
+              (documentation "Run the tlsdate service.")))))))
+
+(define tlsdate-service-type
+  (service-type
+   (name 'tlsdate)
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             tlsdate-shepherd-service)
+          (service-extension account-service-type
+                             (const %tlsdate-accounts))))))
+
+(define* (tlsdate-service #:key (config (tlsdate-configuration)))
+  "Return a service that runs @command{tlsdate}, a simple TCP based
+time service.
+
+The optional @var{config} argument should be a
+@code{<tlsdate-configuration>} object, by default it querries gnu.org
+for time once at boot."
+  (service tlsdate-service-type config))
+
+
+;;;
 ;;; Tor.
 ;;;