Skip to content

Commit db511bd

Browse files
committed
feat(chrony): introducing the chrony module
This new module relies on chrony to add support for NTP in the initrd. By default, it also uses NTP sources from DHCP. It provides two new kernel command line options: - `rd.ntp`: it can be used multiple times to specify server, pool and peer time sources. - `rd.ntp.nodhcp`: it disables the use of NTP sources from DHCP. In some environments, it's necessary to fetch live images from HTTPS URLs. The problem is that the hardware clock may be off, so the validation of the SSL certificates may fail if the time is out of sync. Also, some systems may not have access to DHCP for security reasons, that's why we need a way to configure them on the kernel command line.
1 parent 6f94b0d commit db511bd

9 files changed

Lines changed: 312 additions & 0 deletions

File tree

.github/labeler.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ caps:
8888
- changed-files:
8989
- any-glob-to-any-file: 'modules.d/[0-9][0-9]caps/*'
9090

91+
chrony:
92+
- changed-files:
93+
- any-glob-to-any-file: 'modules.d/[0-9][0-9]chrony/*'
94+
9195
cifs:
9296
- changed-files:
9397
- any-glob-to-any-file: 'modules.d/[0-9][0-9]cifs/*'

doc_site/modules/ROOT/pages/modules/network.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
|===
77
| Module | Description
88

9+
| chrony
10+
| Adds support for synchronizing the internal clock via Network Time Protocol (NTP)
11+
912
| cifs
1013
| https://docs.kernel.org/admin-guide/cifs/index.html[CIFS], https://repology.org/project/cifs-utils[cifs-utils]
1114

man/dracut.cmdline.7.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,27 @@ interface name. Better name it "bootnet" or "bluesocket".
729729
list of physical (ethernet) interfaces. Bridge without parameters assumes
730730
bridge=br0:eth0
731731
732+
NTP
733+
~~~
734+
Requires the dracut 'chrony' module.
735+
736+
**rd.ntp=**__{server|pool|peer}__:__<hostname-or-ip>__[:__<option>__[,<option>...]]::
737+
This parameter can be specified multiple times.
738+
IPv6 addresses have to be put in brackets.
739+
See man:chrony.conf[5,external] for more information about server, pool and
740+
peer options.
741+
+
742+
[listing]
743+
.Examples
744+
--
745+
rd.ntp=pool:2.europe.pool.ntp.org:iburst
746+
rd.ntp=server:185.177.150.95:iburst,prefer
747+
rd.ntp=server:[2600:1f18:631e:db00:363d:d9d7:5c80:d560]:iburst,maxdelay,0.3
748+
--
749+
750+
**rd.ntp.nodhcp**::
751+
Disable using NTP sources from DHCP.
752+
732753
NFS
733754
~~~
734755
Requires the dracut 'nfs' module.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/sh
2+
3+
command -v getargbool > /dev/null || . /lib/dracut-lib.sh
4+
5+
if getargbool 0 rd.ntp.nodhcp; then
6+
info "rd.ntp.nodhcp=1: not adding NTP sources from DHCP."
7+
return 0
8+
fi
9+
10+
_ifname=$1
11+
[ -n "$_ifname" ] || return 0
12+
13+
_dhcpopts_file="/tmp/dhclient.$_ifname.dhcpopts"
14+
[ -s "$_dhcpopts_file" ] || return 0
15+
16+
(
17+
# shellcheck disable=SC1090
18+
. "$_dhcpopts_file"
19+
[ -n "$new_ntp_servers" ] || [ -n "$new_dhcp6_ntp_servers" ] || return 0
20+
21+
info "Adding NTP sources from DHCP ($_ifname)."
22+
23+
[ -d /run/chrony-dhcp ] || mkdir -p /run/chrony-dhcp
24+
for _srv in $new_ntp_servers $new_dhcp6_ntp_servers; do
25+
echo "server $_srv iburst" >> "/run/chrony-dhcp/$_ifname.sources"
26+
done
27+
28+
chronyc reload sources > /dev/null 2>&1 \
29+
|| warn "chronyc failed to reload NTP sources"
30+
)
31+
32+
unset _ifname _dhcpopts_file
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[Unit]
2+
Description=Wait for chrony to synchronize system clock (initrd)
3+
AssertPathExists=/etc/initrd-release
4+
DefaultDependencies=no
5+
After=chronyd.service
6+
Requires=chronyd.service
7+
Before=time-sync.target
8+
Wants=time-sync.target
9+
10+
[Service]
11+
Type=oneshot
12+
# Wait for chronyd to update the clock and the remaining
13+
# correction to be less than 0.1 seconds
14+
ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 0 0.1 0.0 1
15+
# Wait for at most 3 minutes
16+
TimeoutStartSec=180
17+
RemainAfterExit=yes
18+
StandardOutput=null
19+
20+
CapabilityBoundingSet=
21+
DevicePolicy=closed
22+
DynamicUser=yes
23+
IPAddressAllow=localhost
24+
IPAddressDeny=any
25+
LockPersonality=yes
26+
MemoryDenyWriteExecute=yes
27+
PrivateDevices=yes
28+
PrivateUsers=yes
29+
ProtectClock=yes
30+
ProtectControlGroups=yes
31+
ProtectHome=yes
32+
ProtectHostname=yes
33+
ProtectKernelLogs=yes
34+
ProtectKernelModules=yes
35+
ProtectKernelTunables=yes
36+
ProtectProc=invisible
37+
ProtectSystem=strict
38+
RestrictAddressFamilies=AF_INET AF_INET6
39+
RestrictNamespaces=yes
40+
RestrictRealtime=yes
41+
SystemCallArchitectures=native
42+
SystemCallFilter=@system-service
43+
SystemCallFilter=~@privileged @resources
44+
UMask=0777

modules.d/74chrony/chrony.conf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# This file is part of dracut chrony module.
2+
# SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
# Record the rate at which the system clock gains/losses time.
5+
driftfile /run/chrony/drift
6+
7+
# Allow the system clock to be stepped in the first three updates
8+
# if its offset is larger than 1 second.
9+
makestep 1.0 3
10+
11+
# Enable kernel synchronization of the real-time clock (RTC).
12+
rtcsync
13+
14+
# Save NTS keys and cookies.
15+
ntsdumpdir /run/chrony
16+
17+
# Specify directory for log files.
18+
logdir /run/chrony/log
19+
20+
# First, use NTP sources parsed by dracut from the kernel command line.
21+
sourcedir /run/chrony/dracut.sources.d
22+
23+
# Second, use NTP sources from DHCP.
24+
sourcedir /run/chrony-dhcp

modules.d/74chrony/chronyd.service

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[Unit]
2+
Description=NTP client/server (initrd)
3+
AssertPathExists=/etc/initrd-release
4+
DefaultDependencies=no
5+
After=dracut-cmdline.service network.target nss-lookup.target
6+
Before=time-sync.target
7+
Conflicts=ntpd.service systemd-timesyncd.service
8+
Wants=network.target time-sync.target
9+
ConditionCapability=CAP_SYS_TIME
10+
11+
[Service]
12+
Type=notify
13+
PIDFile=/run/chrony/chronyd.pid
14+
Environment="OPTIONS="
15+
EnvironmentFile=-/etc/sysconfig/chronyd
16+
ExecStart=/usr/sbin/chronyd -n $OPTIONS
17+
18+
CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
19+
CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
20+
CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_MKNOD CAP_SYS_ADMIN
21+
CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_CHROOT CAP_SYS_MODULE CAP_SYS_PACCT
22+
CapabilityBoundingSet=~CAP_SYS_PTRACE CAP_SYS_RAWIO CAP_SYS_TTY_CONFIG CAP_WAKE_ALARM
23+
DeviceAllow=char-pps rw
24+
DeviceAllow=char-ptp rw
25+
DeviceAllow=char-rtc rw
26+
DevicePolicy=closed
27+
LockPersonality=yes
28+
MemoryDenyWriteExecute=yes
29+
NoNewPrivileges=yes
30+
PrivateTmp=yes
31+
ProtectControlGroups=yes
32+
ProtectHome=yes
33+
ProtectHostname=yes
34+
ProtectKernelLogs=yes
35+
ProtectKernelModules=yes
36+
ProtectKernelTunables=yes
37+
ProtectProc=invisible
38+
ProtectSystem=strict
39+
ReadWritePaths=/run
40+
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
41+
RestrictNamespaces=yes
42+
RestrictSUIDSGID=yes
43+
SystemCallArchitectures=native
44+
SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @swap

modules.d/74chrony/module-setup.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
check() {
5+
require_binaries \
6+
chronyd \
7+
|| return 1
8+
9+
return 255
10+
}
11+
12+
depends() {
13+
echo systemd network
14+
return 0
15+
}
16+
17+
install() {
18+
# openSUSE/Fedora: chrony
19+
# Ubuntu: _chrony
20+
grep -s -E '^(_chrony|chrony):' "${dracutsysrootdir-}"/etc/passwd \
21+
| sed 's/\/var\/lib\/chrony/\/run\/chrony/' >> "$initdir/etc/passwd"
22+
grep -s -E '^(_chrony|chrony):' "${dracutsysrootdir-}"/etc/group >> "$initdir/etc/group"
23+
24+
inst_hook cmdline 01 "$moddir/parse-ntp.sh"
25+
inst_hook initqueue/online 01 "$moddir/chrony-ntp-source.sh"
26+
27+
inst_multiple -o \
28+
"$systemdntpunits"/50-chronyd.list \
29+
"$systemdsystemunitdir"/time-sync.target \
30+
chronyd chronyc mkdir chown
31+
32+
inst_simple "$moddir/chrony.conf" /etc/chrony.conf
33+
34+
for i in \
35+
chronyd.service \
36+
chrony-wait.service; do
37+
inst_simple "$moddir/$i" "$systemdsystemunitdir/$i"
38+
$SYSTEMCTL -q --root "$initdir" add-wants initrd.target "$i"
39+
done
40+
41+
if [[ $hostonly ]]; then
42+
local _i _directives _keyfile _source_dirs=()
43+
44+
# Install the file pointed by the "keyfile" directive, used for NTP
45+
# authentication. This directive is intended to be unique, chrony would
46+
# end up using the last one processed.
47+
readarray -t _directives < <(grep -r -h '^keyfile ' "${dracutsysrootdir-}"/etc/chrony*)
48+
if ((${#_directives[@]})); then
49+
printf "\n# Specify file containing keys for NTP authentication.\n%s\n" "${_directives[-1]}" >> "$initdir/etc/chrony.conf"
50+
_keyfile="${_directives[-1]/#keyfile /}"
51+
fi
52+
53+
# chrony allows to configure directories with .sources files using the
54+
# "sourcedir" directive, used to specify NTP sources (server, pool, and
55+
# peer directives).
56+
readarray -t _directives < <(grep -r -h '^sourcedir /etc' "${dracutsysrootdir-}"/etc/chrony*)
57+
if ((${#_directives[@]})); then
58+
printf "\n# Use NTP sources configured on the host.\n" >> "$initdir/etc/chrony.conf"
59+
for _i in "${_directives[@]}"; do
60+
echo "$_i" >> "$initdir/etc/chrony.conf"
61+
_source_dirs+=("$(echo "$_i" | sed -e 's/sourcedir //' -e 's/$/\/*.sources/')")
62+
done
63+
fi
64+
65+
# We do not want to include /etc/chrony.conf or ".conf" files specified
66+
# with "include" or "confdir" directives from the host, because they
67+
# can override "driftfile", "ntsdumpdir" or "logdir" directives,
68+
# intended to point to /run in the initrd.
69+
70+
inst_multiple -H -o "$_keyfile" "${_source_dirs[@]}" \
71+
/etc/sysconfig/chronyd \
72+
"$systemdsystemconfdir"/time-sync.target \
73+
"$systemdsystemconfdir/time-sync.target.wants/*.target"
74+
fi
75+
}

modules.d/74chrony/parse-ntp.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/bin/sh
2+
3+
command -v getargs > /dev/null || . /lib/dracut-lib.sh
4+
5+
# format: rd.ntp={server|pool|peer}:<hostname-or-ip>[:<option>[,<option>...]]
6+
parse_ntp_source() {
7+
local v="${1}":
8+
local i
9+
local src addr opts
10+
11+
set --
12+
while [ -n "$v" ]; do
13+
if [ "${v#\[*:*:*\]:}" != "$v" ]; then
14+
# handle IPv6 address
15+
i="${v%%\]:*}"
16+
i="${i##\[}"
17+
set -- "$@" "$i"
18+
v=${v#\["$i"\]:}
19+
else
20+
set -- "$@" "${v%%:*}"
21+
v=${v#*:}
22+
fi
23+
done
24+
25+
if [ $# -lt 2 ]; then
26+
warn "Failed to parse NTP time source"
27+
return 1
28+
fi
29+
30+
case "$1" in
31+
server | pool | peer)
32+
src=$1
33+
;;
34+
*)
35+
warn "Invalid time source '$1'. Valid options: server, pool, peer"
36+
return 1
37+
;;
38+
esac
39+
40+
[ -n "$2" ] && addr=$2
41+
[ -n "$3" ] && opts="$(str_replace "$3" "," " ")"
42+
43+
echo "${src} ${addr}${opts:+ $opts}"
44+
return 0
45+
}
46+
47+
mkdir -p -m 0750 /run/chrony
48+
chown chrony: /run/chrony
49+
mkdir /run/chrony/dracut.sources.d
50+
51+
for _i in $(getargs rd.ntp); do
52+
_src=$(parse_ntp_source "$_i")
53+
if [ -n "$_src" ]; then
54+
echo "$_src" >> /run/chrony/dracut.sources.d/dracut.sources
55+
fi
56+
done
57+
58+
if [ "$(ls -A /run/chrony/dracut.sources.d)" ] && ! getargbool 0 rd.neednet; then
59+
echo "rd.neednet=1" > /etc/cmdline.d/01-chrony.conf
60+
if ! getarg "ip="; then
61+
echo "ip=dhcp" >> /etc/cmdline.d/01-chrony.conf
62+
fi
63+
fi
64+
65+
unset _i _src

0 commit comments

Comments
 (0)