How to configure a Linux server as an NTP time client
Install and configure the Chrony or NTP package to synchronize your Ubuntu or AlmaLinux server with public or private time servers.
This tutorial shows you how to configure your Linux server to act as an NTP client that synchronizes its system clock with external time sources. The steps apply to Ubuntu 24.04 and AlmaLinux 9 using the Chrony package, which is preferred for its reliability on VPS instances. You will install the service, configure the server addresses, and restart the daemon to apply changes.
Prerequisites
- Access to a fresh Linux server running Ubuntu 24.04 or AlmaLinux 9.
- Root or sudo privileges to install packages and modify configuration files.
- Network connectivity to public NTP servers (e.g., pool.ntp.org) or your internal time server.
- Installed package manager (apt for Ubuntu, dnf for AlmaLinux).
Step 1: Install the Chrony package
Update your package index to ensure you get the latest version of Chrony. Then install the package using the native package manager for your distribution.
sudo apt update && sudo apt install chrony -y
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
chrony
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,245 kB of archives.
After this operation, 3,456 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 chrony amd64 4.4+dfsg-1ubuntu1.1 [1,245 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 1,245 kB in 2s (638 kB/s)
Selecting previously unselected package chrony.
(Reading database ... 12345678 files in database)
Preparing to unpack .../chrony_4.4+dfsg-1ubuntu1.1_amd64.deb ...
Unpacking chrony (4.4+dfsg-1ubuntu1.1) ...
Setting up chrony (4.4+dfsg-1ubuntu1.1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/chrony.service → /lib/systemd/system/chrony.service.
Processing triggers for systemd (255.4-1ubuntu8.12) ...
For AlmaLinux 9, run the following command instead:
sudo dnf install chrony -y
Already up-to-date.
Resolving Dependencies
--> Running transaction check
---> Package chrony.x86_64 0:0.4.4-1.el9 will be installed
---> Package ntp.x86_64 0:4.2.6p15-1.el9_3 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
=====================================================================================================================================
Package Arch Version Repository Size
=====================================================================================================================================
Installing:
chrony x86_64 0.4.4-1.el9 appstream 246 k
Installing dependencies:
ntp x86_64 4.2.6p15-1.el9_3 appstream 5.3 M
=====================================================================================================================================
Total 5.5 M
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : chrony-0.4.4-1.el9.x86_64
Installing : ntp-4.2.6p15-1.el9_3.x86_64
Verifying : ntp-4.2.6p15-1.el9_3.x86_64
Verifying : chrony-0.4.4-1.el9.x86_64
Installed
Step 2: Configure the NTP servers
Edit the main configuration file to specify your time sources. Use public servers like pool.ntp.org or internal servers if you have them. Add your preferred servers to the list in the file.
sudo nano /etc/chrony/chrony.conf
Add the following lines to the file, replacing the example servers with your own if necessary:
allow 127.0.0.1
allow ::1
rtcsync
pool 0.pool.ntp.org iburst
pool 1.pool.ntp.org iburst
pool 2.pool.ntp.org iburst
pool 3.pool.ntp.org iburst
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst
server 0.nist.gov iburst
server 1.nist.gov iburst
server 2.nist.gov iburst
server 3.nist.gov iburst
If you have an internal NTP server, add it with the server directive and specify its IP address or hostname:
server 192.168.1.10 iburst
Save the file and exit the editor. Ensure the line `allow 127.0.0.1` is present to allow local time queries.
Step 3: Start and enable the Chrony service
Start the Chrony service immediately and enable it to start on boot. This ensures your server synchronizes time from the first boot.
sudo systemctl start chrony
sudo systemctl enable chrony
● chrony.service - NTP client
Loaded: loaded (/lib/systemd/system/chrony.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-05-01 10:00:00 UTC; 1s ago
Docs: man:chrony(8)
https://chrony.net/documentation/
Main PID: 1234 (chronyd)
Tasks: 1 (limit: 24915)
Memory: 1.2M
CPU: 100ms
CGroup: /system.slice/chrony.service
├─1234 /usr/sbin/chronyd -f /etc/chrony/chrony.conf
└─1235 /usr/sbin/chronyd -f /etc/chrony/chrony.conf
Verify the service status with:
sudo systemctl status chrony
Verify the installation
Check that your system time is synchronized correctly. Use the `chronyc tracking` command to view the current offset and root delay. This shows how far your clock is from the reference time.
chronyc tracking
leap_filename: /etc/chrony/leap-seconds
leap_status: 0 (no leap second pending)
reference_id: 0.pool.ntp.org
reference_time: 2024-05-01 10:00:00.000000000 UTC
nominal_tai_offset: 32
system_tai_offset: 32
tai_offset: 32
ntptime_sync: 0
ntp_adj: 0
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000000
ntptime_offset: 0.000