The Unix Way ■ Episode 15
Ask a Linux admin which time daemon their server runs. Pause for the silence. Then watch them check three different places to find out. On FreeBSD the question does not arise.
This is not a story about clocks. It is a story about how a basic system service ended up with three implementations, three default behaviours, three configuration files, and zero agreement, and what it costs the people who have to administer the result.
A Short History of NTP
The
Network
Time Protocol was designed by
David
L. Mills at the University of Delaware in 1985. RFC 958
standardised the original protocol; RFC 1305 codified
version 3 in 1992;
RFC 5905
finalised version 4 in 2010. The reference implementation,
called ntpd, was written by Mills and his
students alongside the protocol itself. For most of the
next thirty years, ntpd was the only serious
option for synchronising the clock on a Unix machine. The
University of Delaware NTP code became the reference, the
documentation, and the default.
The protocol matters because it is harder than it looks. A client cannot simply ask a server "what time is it" and accept the answer; the round-trip introduces latency, the network jitters, the local clock drifts at a rate that depends on temperature and load, and the only way to compute a useful offset is to query several servers, weigh their replies against each other, and apply a clock-discipline algorithm that gradually steers the local oscillator without abrupt jumps. The full NTP protocol embeds this into the daemon. The Simple Network Time Protocol, SNTP, is the same wire format used naively: query one server, accept one answer, set the clock.
FreeBSD: One Tool, In Base
ntpd(8)
has been part of the FreeBSD base system since 4.x in
2000. To enable it, an administrator adds a single line to
/etc/rc.conf:
ntpd_enable="YES"
The configuration file /etc/ntp.conf is shipped
with sensible defaults pointing at the FreeBSD pool
servers; non-default servers can be added by editing it.
The service is started with service ntpd start.
The diagnostic command is ntpq -p, which
prints the list of configured peers, their measured
offsets, and the daemon's current opinion about which it is
using.
For the rare case where the in-base ntpd does
not fit, OpenNTPD is available in ports under
net/openntpd.
The most common reason to reach for it is jails: the
OpenBSD-derived OpenNTPD is more comfortable binding to
specific addresses, which matters when a jail wants its own
NTP daemon listening on its own IP. For ninety-nine servers
out of a hundred, the in-base ntpd is the
answer, and the answer has not changed in over twenty
years.
The reason this is unremarkable on FreeBSD is the reason
most things on FreeBSD are unremarkable: a single team
makes the decisions and maintains the result. The base
system includes ntpd. The base system
documents ntpd. The base system upgrades
ntpd. There is no second opinion, because
there is no second team.
Linux: ntpd, the Original
The same ntpd from David L. Mills was, for
most of Linux's existence, the standard time daemon on
Linux too. Distributions packaged it under names like
ntp (Debian, Ubuntu) or ntp
(RHEL, Fedora). The configuration file was
/etc/ntp.conf, the service was
ntpd, the diagnostic was
ntpq -p. The world worked.
By the late 2010s, the consensus had begun to shift. The
ntpd codebase had a complicated history of
maintenance, several serious CVEs, and a configuration
syntax that newer admins found rather opaque. The Linux
Foundation funded a separate "Network Time Foundation"
maintenance effort which kept the lights on but did not
modernise the daemon in ways that distributions wanted. By
2026, every major distribution has moved on.
ntpd is still installable, still works, and
is still a perfectly reasonable choice for an
administrator who knows it. It is no longer what new
servers ship with.
Linux: chrony, the Modern Replacement
Richard
Curnow began work on chrony in 1997,
originally as a personal project for synchronising laptops
with intermittent network connectivity. After Curnow
stepped back from active development, Miroslav Lichvar at
Red
Hat picked it up, and chrony is now
developed under Red Hat sponsorship. By 2026 it is the
default time daemon on Fedora, RHEL, CentOS Stream, Rocky,
Alma, openSUSE, and Arch.
chrony is a complete NTP implementation. It
can act as a client, a server, or both. It supports
NTS
(Network Time Security, RFC 8915) for authenticated
time without the operational burden of NTP autokey. It
converges faster than ntpd on first start,
handles long network outages without drifting badly, and
behaves better on virtual machines whose hardware clock
cannot be trusted. The configuration file is
/etc/chrony.conf on RHEL-family systems and
/etc/chrony/chrony.conf on Debian-family
systems, because packagers disagreed on the right path.
The daemon is chronyd. The diagnostic is
chronyc tracking (current sync state) and
chronyc sources (list of upstream servers).
The service unit is sometimes chronyd,
sometimes chrony, depending on which
packaging tradition the distribution inherited.
If a Linux admin is asked to set up time synchronisation on
a server in 2026 and given a free hand, the answer is
almost always chrony. The accuracy is better,
the codebase is healthier, the maintainer is responsive,
and the documentation is current.
Linux: systemd-timesyncd, the Minimalist
The third answer was added by systemd in version 213
(December 2014).
systemd-timesyncd
is not a full NTP implementation; it is an SNTP client. It
queries one server at a time, accepts the answer, and sets
the clock. It does not triangulate from multiple sources,
it does not weight peers against each other, it does not
detect a single misconfigured upstream lying about the
time. It is also small, simple, and adequate for the case
it was built for: a desktop or a container that just needs
the clock to be roughly right.
Ubuntu adopted systemd-timesyncd as the
default in 18.04 (2018) and has kept it as the desktop
default ever since; Ubuntu Server installs
chrony by default in newer releases but
systemd-timesyncd was the documented standard
for several LTS cycles. Many container images use
systemd-timesyncd because it has fewer
dependencies than chrony. The configuration
file is /etc/systemd/timesyncd.conf, the
status command is timedatectl status, and the
daemon is part of systemd itself rather than a separate
package.
The trap with systemd-timesyncd is that it
ignores /etc/ntp.conf. An administrator who
inherits a server, sees /etc/ntp.conf with
carefully tuned upstream servers, and assumes those servers
are being used, may well be wrong: if
systemd-timesyncd is the active daemon, it is
reading /etc/systemd/timesyncd.conf, and
/etc/ntp.conf is decoration. The diagnostic
for "which daemon is actually running" on a Linux box is
to enumerate the candidates: systemctl status
chronyd, systemctl status ntpd,
systemctl status systemd-timesyncd, until one
of them returns "active". Two of them sometimes do. That
conversation is its own kind of fun.
OpenNTPD, the Quiet One
A footnote, but worth one.
OpenNTPD
was written by Henning Brauer for OpenBSD in 2003,
motivated by the same complaints about the reference
ntpd that eventually drove Linux distributions
toward chrony: complicated configuration, a
hard-to-audit codebase, and licensing that did not fit
OpenBSD's standards. OpenNTPD is included in OpenBSD base,
and is available on FreeBSD via the
net/openntpd port. It is a deliberately small
full-NTP implementation, with a configuration file the
size of a postcard. For administrators who want a simple
time daemon without the size of ntpd and
without depending on chrony, OpenNTPD is the
quiet third option that has worked steadily for over
twenty years.
The Point
The same problem (the clock drifts, set it from a network
source) has three answers on Linux because three different
communities, working on overlapping but not identical use
cases, arrived at three different daemons, and the
distributions that integrate them could not converge on a
single recommendation. Fedora chose chrony.
Ubuntu chose systemd-timesyncd for the desktop
and chrony for the server. Debian sat on
ntpd for years before transitioning. Arch let
the user decide.
FreeBSD did not have that argument. The base team picked
ntpd, kept it for two decades, and the rest
of the system was built around the choice. When OpenNTPD
became available, it went into ports as a clearly-labelled
alternative; it did not displace the in-base default.
The cost of three answers is paid every time a new admin inherits a Linux server and has to discover which daemon is currently running, which config file it is reading, and which it ought to be reading. The cost of one answer is a config file you have already seen, on a system you have already learned.
This is not a question of which daemon is best.
chrony is, by most measures, the best of the
four. The question is what it costs to need to know that,
every time, on every system, in a way that varies by
distribution and by year. On FreeBSD the answer to "what
time daemon does this server run" is in
/etc/rc.conf, has been since 2000, and is the
same on the next server too.
NTP since 1985 by David L. Mills.
ntpdin FreeBSD base since 4.x in 2000, one line in/etc/rc.conf, diagnosticntpq -p, unchanged for twenty-five years. On Linux:ntpdthe original (legacy by 2026),chronyby Curnow and Red Hat (default on Fedora/RHEL/Arch), andsystemd-timesyncdthe SNTP minimalist (default on Ubuntu since 18.04, ignores/etc/ntp.conf). Three answers because three groups disagreed and the distribution committees could not converge. The cost of three answers is paid every time an admin inherits a server.