Improving Chrony Time Source Configuration in Ubuntu

Introduction

Chrony is a versatile implementation for the Network Time Protocol(NTP). It can be used to synchronize the system clock with NTP servers and reference clocks.[0]
Chrony is available as a package for Ubuntu, and it is pre-installed on Ubuntu images in multiple public clouds, such as GCP, AWS and Azure, where it functions as the system timekeeper.

Context and Motivation

When Chrony is installed on Ubuntu, it is configured to use the default Ubuntu time servers:

pool ntp.ubuntu.com        iburst maxsources 4
pool 0.ubuntu.pool.ntp.org iburst maxsources 1
pool 1.ubuntu.pool.ntp.org iburst maxsources 1
pool 2.ubuntu.pool.ntp.org iburst maxsources 2

These sources are configured in /etc/chrony/chrony.conf on Noble or earlier versions.

If a user wishes to not use any or all of the default Ubuntu time sources they need to modify /etc/chrony/chrony.conf. Since many Ubuntu cloud images use Chrony, some public clouds prefer to configure instances with cloud-specific time sources. These sources typically have lower latency and a smaller margin of error.
As a result, on some Ubuntu images and instances, the default Ubuntu time sources are removed, and cloud-specific sources are added to /etc/chrony/chrony.conf. This is either done during the image build process or at first boot by cloud-init. However, because /etc/chrony/chrony.conf is tracked by ucf, if the file is modified after installation, ucf may prompt users during any upgrades where Chrony is upgraded.

This behavior can pose problems for automating package and system upgrades. As part of a wider effort, configuration customizations are being moved to drop-in directories (*.d/ directories); but Chrony’s time source configuration directives like pool currently prevent disabling or removing the default Ubuntu time sources without directly editing /etc/chrony/chrony.conf.

In summary, what we needed was a way to allow removal of default Ubuntu time sources from Chrony configuration, without it resulting in any user prompts during future Chrony upgrades.

Approach #1: Introduce a negatory configuration directive

One proposed solution was to introduce a new Chrony configuration directive called disallowname, which would prevent Chrony from using a specific time source, effectively disabling its configuration entry. This directive could be used in a drop-in configuration file that is not tracked by ucf, allowing users to disable the default Ubuntu time sources and configure custom ones without modifying /etc/chrony/chrony.conf.
A debdiff of this approach is available here.

However, after discussion, it was concluded that a packaging-based solution would be more appropriate.

Approach #2: Packaging based solution

The second approach involved moving the default Ubuntu time sources from /etc/chrony/chrony.conf to a drop-in file located in /etc/chrony/sources.d, such as default-ntp-pools.sources. In an early revision of this approach, default-ntp-pools.sources was not tracked by ucf, allowing it to be deleted or modified without triggering ucf prompts during package upgrades. default-ntp-pools.sources was renamed to ubuntu-ntp-pools.sources in a subsequent iteration and its trackability by ucf was also changed.

Another consideration was to provide users with a choice of time sources during package configuration: either Ubuntu’s default sources or cloud-specific ones. However, including cloud-specific configurations in the package posed a risk. If these configurations needed updates in the future, it would require an SRU (Stable Release Update), adding complexity to the process.

Ultimately after a lot of refinement, and implementation help from Andreas Hasenack the following approach was implemented and landed in Oracular.

  1. The default Ubuntu time sources were removed from /etc/chrony/chrony.conf.
  2. A low-priority debconf question named chrony/configure_ubuntu_pools_in_sourcesd was introduced. Most users won’t be prompted with this question as it is low priority. The default value of the answer is true. The answer value can be changed using echo "chrony chrony/configure_ubuntu_pools_in_sourcesd boolean false" | sudo debconf-set-selections
  3. If chrony/configure_ubuntu_pools_in_sourcesd is true, the file /etc/chrony/sources.d/ubuntu-ntp-pools.sources is created, containing the default Ubuntu time sources. This file is tracked by ucf ensuring it is properly managed if an update to the default Ubuntu time sources is included in a package update.
  4. If chrony/configure_ubuntu_pools_in_sourcesd is set to false, the file /etc/chrony/sources.d/ubuntu-ntp-pools.sources is not created and Chrony is not configured with the default Ubuntu time sources. Cloud specific sources can be configured in a separate drop-in configuration file .
  5. If /etc/chrony/sources.d/ubuntu-ntp-pools.sources exists and is tracked by ucf, but chrony/configure_ubuntu_pools_in_sourcesd is set to false, the file will be deleted during the next Chrony upgrade and subsequent upgrades will not create it.

Initially, the plan was to land the solution in Debian and then pull it into Ubuntu. However, since these changes mainly affect the Chrony delta that Ubuntu already maintains, it was deemed unnecessary to propose them to Debian.

A quick note on cloud-init
Currently, cloud-init configures Chrony by replacing /etc/chrony/chrony.conf with another version containing the desired configuration which does not include sources from /etc/chrony/sources.d/*. However, a future change to cloud-init is planned to better utilize the Chrony updates described above.

Launchpad bug: LP #2048876
Merge proposal: #469064

2 Likes