Debian GNU/Linux · Services

Configure systemd-timesyncd with approved time servers and keep it running

When it fails: systemd-timesyncd uses built-in fallback servers or is not running. The clock follows whatever servers were compiled in, or is not synchronized at all.

CB-DEB-SVC-015lowactiveautomatedautomated fixprofile core

As released in v0.1.1 beta · pre-release. Current state.

Description

systemd-timesyncd is a simple SNTP client. Its servers are set with NTP= in /etc/systemd/timesyncd.conf or in a drop-in under /etc/systemd/timesyncd.conf.d/. Without NTP=, it only uses the FallbackNTP= list compiled into the package. The service must be enabled and running.

The check reads the merged configuration with systemd-analyze cat-config and keeps the last NTP= line, which is the one systemd applies. Debian ships no NTP= line, so the control fails on a fresh install. The fix writes /etc/systemd/timesyncd.conf.d/60-cirsec.conf.

Check and swap the default servers. time_servers defaults to the public Debian pool so that the fix works everywhere. It is not an approved source: replace it in the tailoring file with your organization's own time servers (internal NTP, domain controllers, or a provider you trust) before applying the fix in production.

Rationale

Explicit servers make the time source a documented choice: internal servers for isolated networks, or a public pool the organization trusts. A stopped client lets the clock drift, which breaks log correlation and time-based authentication.

Impact

The system contacts the configured servers on UDP port 123; the firewall must allow it. When the default list is kept, the servers are the public Debian pool.

Applies when

Detected: when: systemd-timesyncd is installed A scanner reports the control not applicable when one is false.

Setting

Location/etc/systemd/timesyncd.conf.d/60-cirsec.conf
DefaultNo NTP= line (compiled-in fallback servers)
RecommendedNTP={{ time_servers }}

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
time_serversstring. Space-separated list of approved NTP servers, written by the fix.0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org

The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.

Audit

  1. Run systemd-analyze cat-config systemd/timesyncd.conf. The last NTP= line must list at least one approved server.
  2. systemctl is-enabled systemd-timesyncd must print enabled and systemctl is-active systemd-timesyncd must print active.

Automated: every check must pass. Scanners report each check by its id.

servers

Time servers set with NTP= in the merged configuration.

script: |
  o=$(systemd-analyze cat-config systemd/timesyncd.conf 2>/dev/null | grep -E '^[[:space:]]*NTP=' | tail -n 1)
  v=$(printf '%s' "$o" | sed 's/^[[:space:]]*NTP=[[:space:]]*//')
  echo "NTP=${v:-<not set>}"
  [ -n "$v" ]

enabled

systemd-timesyncd is enabled.

unit: systemd-timesyncd.service
state: enabled

active

systemd-timesyncd is running.

script: systemctl is-active systemd-timesyncd.service || exit 1

Remediation

Create /etc/systemd/timesyncd.conf.d/60-cirsec.conf containing:

[Time]
NTP={{ time_servers }}

then run systemctl enable systemd-timesyncd and systemctl restart systemd-timesyncd. Check with timedatectl timesync-status.

Restartservice: systemd-timesyncd
Disruptionnone

Rollback

Delete /etc/systemd/timesyncd.conf.d/60-cirsec.conf and restart systemd-timesyncd.

enabled

Generated from check enabled: the engine writes the fix for every output, it sets the expected value and the check runs again after.

servers

f=/etc/systemd/timesyncd.conf.d/60-cirsec.conf
want=$(printf '# Written by CIRSEC Baselines CB-DEB-SVC-015\n[Time]\nNTP=%s' "$CB_TIME_SERVERS")
if [ "$(cat "$f" 2>/dev/null)" != "$want" ]; then
  cb_backup "$f"
  mkdir -p /etc/systemd/timesyncd.conf.d
  printf '%s\n' "$want" >"$f"
fi
systemctl is-active --quiet systemd-timesyncd.service || systemctl start systemd-timesyncd.service

Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.

References

Mappings

FrameworkIDRelation
NIST SP 800-53 Rev. 55.1.1AU-8(1)partial

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 12, Proxmox VM, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. Fails on fresh image (no NTP=), fix writes the drop-in and restarts timesyncd, audit passes, timedatectl uses the configured server; state kept after reboot.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. Fails on fresh image (no NTP=), fix writes the drop-in and restarts timesyncd, audit passes, timedatectl uses the configured server; state kept after reboot.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr