NTP Server Setup

This document serves two purposes.  The first is to document the setup of an NTP server (not an NTP client.)  The second is to allow other to see how to monitor NTP.

Enable syncing with upstream servers from pool.ntp.org. You should be as geographically specific as you can, since closer servers theoretically give more accurate results, but you also should make sure you’re pulling from a large enough pool. These settings are in /etc/ntp.conf

# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# Limiting to three servers as requested by pool.ntp.org
server 0.north-america.pool.ntp.org
server 1.north-america.pool.ntp.org
server 2.north-america.pool.ntp.org

Now we need to make sure our time is somewhat accurate – within a minute or so. But before we do that we have to stop the ntpd daemon.

service ntpd stop

Now sync time

ntpdate -u pool.ntp.org

Make sure the NTP daemon is enabled

chkconfig --list ntpd
ntpd           	0:off	1:off	2:off	3:off	4:off	5:off	6:off

If it’s not, enable it

chkconfig --level 2345 ntpd on

and verify

chkconfig --list ntpd
ntpd           	0:off	1:off	2:on	3:on	4:on	5:on	6:off

Restart the daemon

service ntpd start

Now we need to make sure time is syncing correctly. We can do this with ntpq -p (or use -np for ip’s, and not names.) This provided you with a list of time servers and the delay, offset and jitter that your server is experiencing with them. The delay and offset values should be non-zero and the jitter value should be under 100. The times are in milliseconds (1/1000 of a second.) The important thing to look for is the * you see in the first line. The * means you are syncing with a server on the internet. If you don’t see it right away, wait a few minutes and try again.  It may take up to 15 minute for the local clock to get in sync with the remote server.  Patience is your friend.

ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
+mickey.linocomm     2 u   41 1024  377  439.135  -90.283  30.760
*echelon.no-such       2 u  102 1024  377  290.252  -36.630  50.411
+blwest.com      2 u  998 1024  377  391.356  -88.067  11.724
 LOCAL(0)        .LOCL.          10 l   62   64  377    0.000    0.000   0.001

The first character in the leftmost column (remote) indicates the status of the peer, followed by the name or IP of the peer

“*” selected for synchronization
“o” selected for synchronization, PPS signal in use.
“+” included in the final selection set;
discarded as unreachable, synchronized to this server (synch loop) or outrageous synchronization distance;
“x” designated falsticker by the intersection algorithm;
“.” culled from the end of the candidate list;
“-” discarded by the clustering algorithm;
“#” selected for synchronization but distance exceeds maximum;

The third column (st) is the stratum of your peer.  LOCAL is a loopback address used for when no other clocks are available, and has a default setting of 10.  Valid values are between 1 and 15.  A value of 16 is a invalid stratum value representing “this server is not considered as a time provider”. This can be for various reasons, the most common reasons are “time provider not synchronized”, “configured source does not exist” or “ntp server not running”.

The fourth column (t) indicates the type of server it is, and isn’t of much concern.

l = local (such as a GPS, WWVB)
u = unicast (most common)
m = multicast
b = broadcast
– = netaddr

The fifth column (when) is the time since the last update.

The sixth column (poll) indicates how often the upstream server is polled, in seconds.   This is configurable in the ntp.conf file, but the default setting should be more than adequate.  As confidence grows in the source, the polling time will slow down, eventually reaching 1024 (seconds.)  The default minimal setting is 64 seconds.  Time will be updated when the column when equals poll.

The seventh column indicates reach, and should be at 377. An explanation of why from Linux Journal

Each remote server or peer is assigned its own buffer by ntpd. This buffer represents the status of the last eight NTP transactions between the NTP daemon and a given remote time server. Each bit is a boolean value, where a 1 indicates a successful transaction and a 0 indicates a failure. Each time a new packet is sent, the entire eight-bit register is shifted one bit left as the newest bit enters from the right.

The net result is that dropped packets can be tracked over eight poll intervals before falling off the end of the register to make room for new data. This recycling of space in the register is why it’s called a circular buffer, but it may make more sense to think of it in linear terms, as a steady, leftward march–eight small steps, and then the bit ends up wherever bits go when they die.

For reasons that seemed good to the developers, this register is displayed to the user in octal values instead of binary, decimal or even hex. The maximum value of an eight-bit binary number is 11111111, which is 377 in octal, 255 in decimal and 0xFF in hex.

The eighth column (delay) is the RTT to the time server

The ninth column (offset) indicates the difference between the remote and the local clock in milliseconds, and should be less than 150.  This is the most important column for monitoring your time.

The tenth column (jitter or disp on some systems) is the “dispersion” in milliseconds of successive time values from the remote server. It is a measure of the stability (time-wise) of the network path to the remote server, and is also an important factor used by NTP in selecting the “best” server.

If you want to see how accurate your time is, you can use ntpdc -c loopinfo. This will display how far off the system time is in seconds, based upon the last time the remote server was contacted.

ntpdc -c loopinfo
offset:               -0.064429 s
frequency:            -19.206 ppm
poll adjust:          30
watchdog timer:       175 s

To see the remaining correction

ntpdc -c kerninfo
pll offset:           4294.91 s
pll frequency:        -19.206 ppm
maximum error:        0.437245 s
estimated error:      0.06018 s
status:               0001  pll
pll time constant:    6
precision:            1e-06 s
frequency tolerance:  512 ppm

You can get the same rough information from ntptime

ntp_gettime() returns code 0 (OK)
  time cd6e9ff0.43c3e000  Fri, Mar 20 2009 16:06:24.264, (.264708),
  maximum error 468477 us, estimated error 60180 us
ntp_adjtime() returns code 0 (OK)
  modes 0x0 (),
  offset -60495.000 us, frequency -19.206 ppm, interval 1 s,
  maximum error 468477 us, estimated error 60180 us,
  status 0x1 (PLL),
  time constant 6, precision 1.000 us, tolerance 512 ppm,

To query your time server, but not change it, you can use ntpdate -q. However, you’ll need to supply an IP address. I suggest you use the one with the * when you do an ntpq -np, as that is the one you are using for syncing.

ntpdate -q
server, stratum 2, offset -0.066910, delay 0.38264
20 Mar 16:06:53 ntpdate[12418]: adjust time server offset -0.066910 sec

You can also use ntpdate -d to look at the same information, but with debugging information.

ntpdate -d
20 Mar 16:07:28 ntpdate[12419]: ntpdate 4.2.2p1@1.1570-o Tue Jun 10 00:07:14 UTC 2008 (1)
Looking for host and service ntp
host found : echelon.no-such-agency.net
server, port 123
stratum 2, precision -19, leap 00, trust 000
refid [], delay 0.41891, dispersion 0.00674
transmitted 4, in filter 4
reference time:    cd6e9ea5.60041201  Fri, Mar 20 2009 16:00:53.375
originate timestamp: cd6ea032.07525071  Fri, Mar 20 2009 16:07:30.028
transmit timestamp:  cd6ea031.eb308355  Fri, Mar 20 2009 16:07:29.918
filter delay:  0.42224  0.48717  0.41891  0.42369
         0.00000  0.00000  0.00000  0.00000
filter offset: -0.08852 -0.11442 -0.08468 -0.08917
         0.000000 0.000000 0.000000 0.000000
delay 0.41891, dispersion 0.00674
offset -0.084680
20 Mar 16:07:30 ntpdate[12419]: adjust time server offset -0.084680 sec

You can also use ntptrace to watch the system time synchronization (the -n flag turns off name lookups.)

ntptrace -n stratum 2, offset -0.000011, synch distance 0.000702 stratum 1, offset 0.000003, synch distance 0.000456, refid 'GPS'

For the purpose of troubleshooting, some logging options have been enabled. This will allow the capture of various statistics. Daily is the most granular option. This is part of the /etc/ntp.conf configuration file.

# These should enable statistics to be kept
statsdir /var/log/ntp/
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable

Don’t forget to make the directory and make it readable by the ntp user (which the ntp daemon runs as.)

mkdir /var/log/ntp/
chown ntp:ntp /var/log/ntp

Now restart ntpd

service ntpd restart

Next we need to make the server listen to all request on it’s internal network. You can be as broad or as restrictive as you want. Once again this goes in your /etc/ntp.conf

# -- CLIENT NETWORK -------
# Permit systems on this network to synchronize with this
# time service.  Do not permit those systems to modify the
# configuration of this service.  Also, do not use those
# systems as peers for synchronization.

Restart ntpd

service ntpd restart