Time management with Linux: Chrony and Ansible for synchronizing multiple servers #
In the world of system administration, time management is a crucial factor. A precise time protocol is not only important for logging, but also for smooth communication between servers. This is where Chrony, a flexible Network Time Protocol (NTP) service, comes into play. In this article, I’ll show you how to install and configure Chrony manually. As a bonus, I’ll explain at the end how you can automate this configuration on multiple servers using Ansible.
What is Chrony? #
Chrony is a modern NTP client and server suitable for a wide range of use cases. It offers fast synchronization, low resource consumption and high accuracy - especially useful in environments where servers have unreliable or changing network connections.
Main advantages of Chrony:
- Fast synchronization: **Especially after boot.
- Interrupt friendly: Handles connections to intermittent time sources efficiently.
- Compact configuration: Easy to use and customizable.
Installation and basic configuration of Chrony #
1. Install Chrony #
The installation is straightforward and is carried out via the package manager of your Linux distribution:
# Debian/Ubuntu
sudo apt update && sudo apt install chrony
# CentOS/RHEL
sudo yum install chrony
# Fedora
sudo dnf install chrony
2. Configuration #
The main configuration file of Chrony is normally located under /etc/chrony/chrony.conf. A simple example of synchronization with the standard NTP servers:
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
# Allow from local network
allow 192.168.0.0/24 # Here you can specify your local network
# Activate Logs
logdir /var/log/chrony
After adjusting the configuration, restart the service and check its status:
sudo systemctl restart chronyd
sudo systemctl status chronyd
3. Check synchronization status #
You can check the synchronization with the chronyc command:
chronyc tracking
chronyc sources
Bonus: Scaling with Ansible #
If you manage multiple servers, Ansible can efficiently automate the configuration of Chrony. Below I outline a basic approach:
1. Preparing the Ansible structure #
First, create a directory in which you want to create your Ansible project and change to it. Then use ansible-galaxy init to create the role with the necessary folders and files:
mkdir -p ansible-project
cd ansible-project
ansible-galaxy init chrony
You should now have a folder structure that looks something like this:
chrony/
├── inventory.ini --> the file is still missing and must be created
├── playbook.yml --> this file as well
├── roles/
│ ├── chrony/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ ├── templates/
│ │ │ └── chrony.conf.j2
│ │ ├── files/
│ │ ├── vars/
│ │ │ └── main.yml
│ │ ├── defaults/
│ │ │ └── main.yml
│ │ ├── meta/
│ │ └── main.yml
2. Creating an inventory file #
So that you can configure several servers at the same time, you need an inventory file with the servers that you want to address. Create this as shown above and fill it as follows:
---
[chrony_servers]
server1 ansible_host=192.168.1.100
server2 ansible_host=192.168.1.101
3. Creating the playbook #
In order for Ansible to take over the configurations, you must create a playbook and fill it as follows. The storage location can also be found in section 1:
---
- name: Install and configure Chrony
hosts: chrony_servers
become: yes
roles:
- chrony
4. Ansible role #
We have now prepared everything to address the hosts in the inventory with the playbook, but Ansible does not yet know what exactly it should do. This is where the role configuration comes into play. You can find the role in the file roles/chrony/tasks/main.yml. Simply open it and edit it as follows:
---
# Remove standard NTP tools
- name: Remove standard NTP tools
ansible.builtin.package:
name: ntp
state: absent
# Install Chrony
- name: Install Chrony
ansible.builtin.package:
name: chrony
state: present
# Copy the Chrony configuration file
- name: Deploy Chrony configuration
ansible.builtin.template:
src: chrony.conf.j2
dest: /etc/chrony/chrony.conf
owner: root
group: root
mode: 0644
backup: yes
# Restart Chrony service
- name: Restart Chrony service
ansible.builtin.service:
name: chronyd
state: restarted
enabled: yes
5. Ansible templates #
You will have seen in the third section of the task file that a template is used here that we have not yet created / edited. Look in the Templates folder, then create the file chrony.conf.j2 and fill it in:
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
logdir /var/log/chrony
6. Ansible-Handler #
Now we need an Ansible handler that starts the “chrony” service at the end of the playbook. We also need a file for this, which is already in the handlers directory. Change it as follows:
---
- name: Restart chrony
ansible.builtin.service:
name: chronyd
state: restarted
7. Run the Ansible playbook #
Finally, we have all the files and can run the playbook as follows:
ansible-playbook -i inventory.ini playbook.yml
Conclusion #
Chrony offers a flexible and efficient method for time synchronization on Linux servers. With the manual method described, you can quickly configure Chrony on a single server. However, if you manage a larger number of servers, Ansible is a powerful tool to save time and minimize errors. Experiment with both approaches to tailor the synchronization perfectly to your requirements.