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 |
| Default | No NTP= line (compiled-in fallback servers) |
| Recommended | NTP={{ time_servers }} |
Parameters
| Parameter | Core | Server | Server hardened | Desktop | Desktop hardened | Bounds |
|---|---|---|---|---|---|---|
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.org | 0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org | 0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org | 0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org | 0.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
- Run
systemd-analyze cat-config systemd/timesyncd.conf. The lastNTP=line must list at least one approved server. systemctl is-enabled systemd-timesyncdmust printenabledandsystemctl is-active systemd-timesyncdmust printactive.
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.
| Restart | service: systemd-timesyncd |
| Disruption | none |
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
- timesyncd.conf(5), Debian manual pages Debian, vendor-doc, accessed 2026-10-18
- systemd-timesyncd.service(8), Debian manual pages Debian, vendor-doc, accessed 2026-10-18
- Debian Wiki - NTP Debian, vendor-doc, accessed 2026-10-18
Mappings
| Framework | ID | Relation |
|---|---|---|
| NIST SP 800-53 Rev. 55.1.1 | AU-8(1) | partial |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
| Taxonomy | ID |
|---|---|
| MITRE ATT&CK | T1070.006 |
Related controls
- related
CB-DEB-SVC-014Run exactly one time synchronization daemon
People and lifecycle
| Authors |
|
| Verified | 2026-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. |
| Verified | 2026-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 in | v0.1.0 |
| Created, updated | 2026-10-18, 2026-10-18 |
| Translations | fr |