]> git.ipfire.org Git - thirdparty/dracut-ng.git/commitdiff
feat(chrony): introducing the chrony module
authorAntonio Alvarez Feijoo <antonio.feijoo@suse.com>
Tue, 12 May 2026 07:18:08 +0000 (09:18 +0200)
committerNeal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>
Sat, 25 Jul 2026 01:11:18 +0000 (18:11 -0700)
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.

13 files changed:
.github/labeler.yml
.github/workflows/daily-network.yml
.github/workflows/integration.yml
doc_site/modules/ROOT/pages/modules/network.adoc
man/dracut.cmdline.7.adoc
modules.d/74chrony/chrony-ntp-source.sh [new file with mode: 0755]
modules.d/74chrony/chrony-wait.service [new file with mode: 0644]
modules.d/74chrony/chrony.conf [new file with mode: 0644]
modules.d/74chrony/chronyd.service [new file with mode: 0644]
modules.d/74chrony/module-setup.sh [new file with mode: 0755]
modules.d/74chrony/parse-ntp.sh [new file with mode: 0755]
test/TEST-61-CHRONY/Makefile [new file with mode: 0644]
test/TEST-61-CHRONY/test.sh [new file with mode: 0755]

index 5328dd076fe79e96c9876297ea60f6c0abd31965..a946883ada6013dbda8c96f4c6042fbe19a56873 100644 (file)
@@ -88,6 +88,10 @@ caps:
     - changed-files:
           - any-glob-to-any-file: 'modules.d/[0-9][0-9]caps/*'
 
+chrony:
+    - changed-files:
+          - any-glob-to-any-file: 'modules.d/[0-9][0-9]chrony/*'
+
 cifs:
     - changed-files:
           - any-glob-to-any-file: 'modules.d/[0-9][0-9]cifs/*'
index 8c5b760eeba949c5c9bb19cff786993ae40ccc3f..a8c8f5f110f61a96c6e450158ad1a807b9468c65 100644 (file)
@@ -40,6 +40,7 @@ jobs:
                 test:
                     - "31"
                     - "60"
+                    - "61"
                 exclude:
                     - container: arch:latest
                       architecture: {runner: 'ubuntu-24.04-arm', tag: 'arm'}
@@ -50,6 +51,17 @@ jobs:
                     # https://github.com/dracut-ng/dracut/issues/1988
                     - container: debian:sid
                       architecture: {runner: 'ubuntu-24.04-arm', tag: 'arm'}
+                    # In Debian/Ubuntu both chrony and systemd-timesyncd provide
+                    # the virtual package time-daemon, so systemd-timesyncd
+                    # would have to be removed, breaking test 41.
+                    - container: debian:latest
+                      test: "61"
+                    - container: debian:sid
+                      test: "61"
+                    - container: ubuntu:devel
+                      test: "61"
+                    - container: ubuntu:rolling
+                      test: "61"
         container:
             image: ghcr.io/dracut-ng/${{ matrix.container }}
             options: '--device=/dev/kvm --privileged'
index 5a1449b15fed81d6ea95a7e5478e00b8682aa7bb..aa5c8de89b4cc329bdfdb34c1839a19367c66406 100644 (file)
@@ -190,6 +190,13 @@ jobs:
                 test:
                     - "31"
                     - "60"
+                    - "61"
+                exclude:
+                    # In Debian/Ubuntu both chrony and systemd-timesyncd provide
+                    # the virtual package time-daemon, so systemd-timesyncd
+                    # would have to be removed, breaking test 41.
+                    - container: ubuntu:devel
+                      test: "61"
         container:
             image: ghcr.io/dracut-ng/${{ matrix.container }}
             options: '--device=/dev/kvm'
index 04f0eb53b935dc078d3be88e22b45375abd1b738..9a300c0218bc366c383271a5267e2d519587e0a1 100644 (file)
@@ -6,6 +6,9 @@
 |===
 | Module | Description
 
+| chrony
+| Adds support for synchronizing the internal clock via Network Time Protocol (NTP)
+
 | cifs
 | https://docs.kernel.org/admin-guide/cifs/index.html[CIFS], https://repology.org/project/cifs-utils[cifs-utils]
 
index 43dbafd948dbb6fc5666ade15bae659327a45d4b..82ac51944bb1f7083cb8989494725bda9cf6374f 100644 (file)
@@ -729,6 +729,27 @@ interface name. Better name it "bootnet" or "bluesocket".
     list of physical (ethernet) interfaces. Bridge without parameters assumes
     bridge=br0:eth0
 
+NTP
+~~~
+Requires the dracut 'chrony' module.
+
+**rd.ntp=**__{server|pool|peer}__:__<hostname-or-ip>__[:__<option>__[,<option>...]]::
+    This parameter can be specified multiple times.
+    IPv6 addresses have to be put in brackets.
+    See man:chrony.conf[5,external] for more information about server, pool and
+    peer options.
++
+[listing]
+.Examples
+--
+    rd.ntp=pool:2.europe.pool.ntp.org:iburst
+    rd.ntp=server:185.177.150.95:iburst,prefer
+    rd.ntp=server:[2600:1f18:631e:db00:363d:d9d7:5c80:d560]:iburst,maxdelay,0.3
+--
+
+**rd.ntp.nodhcp**::
+    Disable using NTP sources from DHCP.
+
 NFS
 ~~~
 Requires the dracut 'nfs' module.
diff --git a/modules.d/74chrony/chrony-ntp-source.sh b/modules.d/74chrony/chrony-ntp-source.sh
new file mode 100755 (executable)
index 0000000..3f9f79b
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+command -v getargbool > /dev/null || . /lib/dracut-lib.sh
+
+if getargbool 0 rd.ntp.nodhcp; then
+    info "rd.ntp.nodhcp=1: not adding NTP sources from DHCP."
+    return 0
+fi
+
+_ifname=$1
+[ -n "$_ifname" ] || return 0
+
+_dhcpopts_file="/tmp/dhclient.$_ifname.dhcpopts"
+[ -s "$_dhcpopts_file" ] || return 0
+
+(
+    # shellcheck disable=SC1090
+    . "$_dhcpopts_file"
+    [ -n "$new_ntp_servers" ] || [ -n "$new_dhcp6_ntp_servers" ] || return 0
+
+    info "Adding NTP sources from DHCP ($_ifname)."
+
+    [ -d /run/chrony-dhcp ] || mkdir -p /run/chrony-dhcp
+    for _srv in $new_ntp_servers $new_dhcp6_ntp_servers; do
+        echo "server $_srv iburst" >> "/run/chrony-dhcp/$_ifname.sources"
+    done
+
+    chronyc reload sources > /dev/null 2>&1 \
+        || warn "chronyc failed to reload NTP sources"
+)
+
+unset _ifname _dhcpopts_file
diff --git a/modules.d/74chrony/chrony-wait.service b/modules.d/74chrony/chrony-wait.service
new file mode 100644 (file)
index 0000000..c1027a6
--- /dev/null
@@ -0,0 +1,44 @@
+[Unit]
+Description=Wait for chrony to synchronize system clock (initrd)
+AssertPathExists=/etc/initrd-release
+DefaultDependencies=no
+After=chronyd.service
+Requires=chronyd.service
+Before=time-sync.target
+Wants=time-sync.target
+
+[Service]
+Type=oneshot
+# Wait for chronyd to update the clock and the remaining
+# correction to be less than 0.1 seconds
+ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 0 0.1 0.0 1
+# Wait for at most 3 minutes
+TimeoutStartSec=180
+RemainAfterExit=yes
+StandardOutput=null
+
+CapabilityBoundingSet=
+DevicePolicy=closed
+DynamicUser=yes
+IPAddressAllow=localhost
+IPAddressDeny=any
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+PrivateDevices=yes
+PrivateUsers=yes
+ProtectClock=yes
+ProtectControlGroups=yes
+ProtectHome=yes
+ProtectHostname=yes
+ProtectKernelLogs=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+ProtectProc=invisible
+ProtectSystem=strict
+RestrictAddressFamilies=AF_INET AF_INET6
+RestrictNamespaces=yes
+RestrictRealtime=yes
+SystemCallArchitectures=native
+SystemCallFilter=@system-service
+SystemCallFilter=~@privileged @resources
+UMask=0777
diff --git a/modules.d/74chrony/chrony.conf b/modules.d/74chrony/chrony.conf
new file mode 100644 (file)
index 0000000..9eaba80
--- /dev/null
@@ -0,0 +1,24 @@
+# This file is part of dracut chrony module.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Record the rate at which the system clock gains/losses time.
+driftfile /run/chrony/drift
+
+# Allow the system clock to be stepped in the first three updates
+# if its offset is larger than 1 second.
+makestep 1.0 3
+
+# Enable kernel synchronization of the real-time clock (RTC).
+rtcsync
+
+# Save NTS keys and cookies.
+ntsdumpdir /run/chrony
+
+# Specify directory for log files.
+logdir /run/chrony/log
+
+# First, use NTP sources parsed by dracut from the kernel command line.
+sourcedir /run/chrony/dracut.sources.d
+
+# Second, use NTP sources from DHCP.
+sourcedir /run/chrony-dhcp
diff --git a/modules.d/74chrony/chronyd.service b/modules.d/74chrony/chronyd.service
new file mode 100644 (file)
index 0000000..ad8e092
--- /dev/null
@@ -0,0 +1,46 @@
+[Unit]
+Description=NTP client/server (initrd)
+AssertPathExists=/etc/initrd-release
+DefaultDependencies=no
+After=dracut-cmdline.service network.target nss-lookup.target
+Before=time-sync.target
+Conflicts=ntpd.service systemd-timesyncd.service
+Wants=network.target time-sync.target
+ConditionCapability=CAP_SYS_TIME
+
+[Service]
+Type=notify
+PIDFile=/run/chrony/chronyd.pid
+Environment="OPTIONS="
+EnvironmentFile=-/etc/sysconfig/chronyd
+# The default location for chrony.conf can be set at build with the
+# --sysconfdir configuration option, so force /etc/chrony.conf with -f
+ExecStart=/usr/sbin/chronyd -f /etc/chrony.conf -n $OPTIONS
+
+CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
+CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
+CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_MKNOD CAP_SYS_ADMIN
+CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_CHROOT CAP_SYS_MODULE CAP_SYS_PACCT
+CapabilityBoundingSet=~CAP_SYS_PTRACE CAP_SYS_RAWIO CAP_SYS_TTY_CONFIG CAP_WAKE_ALARM
+DeviceAllow=char-pps rw
+DeviceAllow=char-ptp rw
+DeviceAllow=char-rtc rw
+DevicePolicy=closed
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+NoNewPrivileges=yes
+PrivateTmp=yes
+ProtectControlGroups=yes
+ProtectHome=yes
+ProtectHostname=yes
+ProtectKernelLogs=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+ProtectProc=invisible
+ProtectSystem=strict
+ReadWritePaths=/run
+RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
+RestrictNamespaces=yes
+RestrictSUIDSGID=yes
+SystemCallArchitectures=native
+SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @swap
diff --git a/modules.d/74chrony/module-setup.sh b/modules.d/74chrony/module-setup.sh
new file mode 100755 (executable)
index 0000000..0d52f84
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+check() {
+    require_binaries \
+        chronyd \
+        || return 1
+
+    return 255
+}
+
+depends() {
+    echo systemd network
+    return 0
+}
+
+install() {
+    # openSUSE/Fedora: chrony
+    # Ubuntu: _chrony
+    grep -s -E '^(_chrony|chrony):' "${dracutsysrootdir-}"/etc/passwd \
+        | sed 's/\/var\/lib\/chrony/\/run\/chrony/' >> "$initdir/etc/passwd"
+    grep -s -E '^(_chrony|chrony):' "${dracutsysrootdir-}"/etc/group >> "$initdir/etc/group"
+
+    inst_hook cmdline 01 "$moddir/parse-ntp.sh"
+    inst_hook initqueue/online 01 "$moddir/chrony-ntp-source.sh"
+
+    inst_multiple -o \
+        "$systemdntpunits"/50-chronyd.list \
+        "$systemdsystemunitdir"/time-sync.target \
+        chronyd chronyc mkdir chown
+
+    inst_simple "$moddir/chrony.conf" /etc/chrony.conf
+
+    for i in \
+        chronyd.service \
+        chrony-wait.service; do
+        inst_simple "$moddir/$i" "$systemdsystemunitdir/$i"
+        $SYSTEMCTL -q --root "$initdir" add-wants initrd.target "$i"
+    done
+
+    if [[ $hostonly ]]; then
+        local _i _directives _keyfile _source_dirs=()
+
+        # Install the file pointed by the "keyfile" directive, used for NTP
+        # authentication. This directive is intended to be unique, chrony would
+        # end up using the last one processed.
+        readarray -t _directives < <(grep -r -h '^keyfile ' "${dracutsysrootdir-}"/etc/chrony*)
+        if ((${#_directives[@]})); then
+            printf "\n# Specify file containing keys for NTP authentication.\n%s\n" "${_directives[-1]}" >> "$initdir/etc/chrony.conf"
+            _keyfile="${_directives[-1]/#keyfile /}"
+        fi
+
+        # chrony allows to configure directories with .sources files using the
+        # "sourcedir" directive, used to specify NTP sources (server, pool, and
+        # peer directives).
+        readarray -t _directives < <(grep -r -h '^sourcedir /etc' "${dracutsysrootdir-}"/etc/chrony*)
+        if ((${#_directives[@]})); then
+            printf "\n# Use NTP sources configured on the host.\n" >> "$initdir/etc/chrony.conf"
+            for _i in "${_directives[@]}"; do
+                echo "$_i" >> "$initdir/etc/chrony.conf"
+                _source_dirs+=("$(echo "$_i" | sed -e 's/sourcedir //' -e 's/$/\/*.sources/')")
+            done
+        fi
+
+        # We do not want to include /etc/chrony.conf or ".conf" files specified
+        # with "include" or "confdir" directives from the host, because they
+        # can override "driftfile", "ntsdumpdir" or "logdir" directives,
+        # intended to point to /run in the initrd.
+
+        inst_multiple -H -o "$_keyfile" "${_source_dirs[@]}" \
+            /etc/sysconfig/chronyd \
+            "$systemdsystemconfdir"/time-sync.target \
+            "$systemdsystemconfdir/time-sync.target.wants/*.target"
+    fi
+}
diff --git a/modules.d/74chrony/parse-ntp.sh b/modules.d/74chrony/parse-ntp.sh
new file mode 100755 (executable)
index 0000000..0446af6
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+command -v getargs > /dev/null || . /lib/dracut-lib.sh
+
+# format: rd.ntp={server|pool|peer}:<hostname-or-ip>[:<option>[,<option>...]]
+parse_ntp_source() {
+    local v="${1}":
+    local i
+    local src addr opts
+
+    set --
+    while [ -n "$v" ]; do
+        if [ "${v#\[*:*:*\]:}" != "$v" ]; then
+            # handle IPv6 address
+            i="${v%%\]:*}"
+            i="${i##\[}"
+            set -- "$@" "$i"
+            v=${v#\["$i"\]:}
+        else
+            set -- "$@" "${v%%:*}"
+            v=${v#*:}
+        fi
+    done
+
+    if [ $# -lt 2 ]; then
+        warn "Failed to parse NTP time source"
+        return 1
+    fi
+
+    case "$1" in
+        server | pool | peer)
+            src=$1
+            ;;
+        *)
+            warn "Invalid time source '$1'. Valid options: server, pool, peer"
+            return 1
+            ;;
+    esac
+
+    [ -n "$2" ] && addr=$2
+    [ -n "$3" ] && opts="$(str_replace "$3" "," " ")"
+
+    echo "${src} ${addr}${opts:+ $opts}"
+    return 0
+}
+
+mkdir -p -m 0750 /run/chrony
+chown chrony: /run/chrony
+mkdir /run/chrony/dracut.sources.d
+
+for _i in $(getargs rd.ntp); do
+    _src=$(parse_ntp_source "$_i")
+    if [ -n "$_src" ]; then
+        echo "$_src" >> /run/chrony/dracut.sources.d/dracut.sources
+    fi
+done
+
+if [ "$(ls -A /run/chrony/dracut.sources.d)" ] && ! getargbool 0 rd.neednet; then
+    echo "rd.neednet=1" > /etc/cmdline.d/01-chrony.conf
+    if ! getarg "ip="; then
+        echo "ip=dhcp" >> /etc/cmdline.d/01-chrony.conf
+    fi
+fi
+
+unset _i _src
diff --git a/test/TEST-61-CHRONY/Makefile b/test/TEST-61-CHRONY/Makefile
new file mode 100644 (file)
index 0000000..2dcab81
--- /dev/null
@@ -0,0 +1 @@
+-include ../Makefile.testdir
diff --git a/test/TEST-61-CHRONY/test.sh b/test/TEST-61-CHRONY/test.sh
new file mode 100755 (executable)
index 0000000..bdc934d
--- /dev/null
@@ -0,0 +1,154 @@
+#!/usr/bin/env bash
+set -eu
+
+[ -z "${USE_NETWORK-}" ] && USE_NETWORK="network"
+
+# shellcheck disable=SC2034
+TEST_DESCRIPTION="NTP support with chrony, systemd and $USE_NETWORK"
+
+# Fake time way off in the future, so SSL certificates will appear to have
+# expired
+FAKE_TIME="2100-01-01T00:00:00"
+
+# Name of the SSL certificate
+SSL_CERT="webserver.pem"
+
+test_check() {
+    local binary
+
+    for binary in chronyd openssl; do
+        if ! type -p "$binary" &> /dev/null; then
+            echo "Test needs $binary... Skipping"
+            return 1
+        fi
+    done
+
+    command -v systemctl &> /dev/null
+}
+
+client_run() {
+    local nook="$1"
+    local test_name="$2"
+    local append="$3"
+
+    client_test_start "$test_name"
+
+    # Comments about some qemu options:
+    # - -rtc "base=...,clock=vm" allows to disconnect vm time from host time
+    # - initcall_blacklist=rtc_cmos_init (x86_64) / efi_rtc_init (aarch64)
+    #   instructs the kernel to avoid trying to sync the clock
+    "$testdir"/run-qemu \
+        "${disk_args[@]}" \
+        -rtc "base=$FAKE_TIME,clock=vm" \
+        -device "virtio-net-pci,netdev=lan0" \
+        -netdev "user,id=lan0,net=10.0.2.0/24,dhcpstart=10.0.2.15" \
+        -append "root=LABEL=dracut initcall_blacklist=rtc_cmos_init initcall_blacklist=efi_rtc_init $append $TEST_KERNEL_CMDLINE" \
+        -initrd "$TESTDIR/initramfs.testing"
+
+    # The "nook" variable controls whether a failed test is considered good
+    if [[ $nook != 1 ]]; then
+        check_qemu_log
+    else
+        check_qemu_log || :
+    fi
+
+    client_test_end
+}
+
+test_run() {
+    declare -a disk_args=()
+
+    qemu_add_drive disk_args "$TESTDIR"/root.img root
+
+    start_webserver "HTTPS" "$SSL_CERT"
+
+    client_run 1 \
+        "Fetch file from HTTPS with the system clock out of sync" \
+        "rd.neednet=1 ip=dhcp"
+
+    # 2606:4700:f1::1 should be Cloudflare
+    # "prefer" pool.ntp.org
+    client_run 0 \
+        "Fetch file from HTTPS after sync time via NTP" \
+        "rd.ntp=server:[2606:4700:f1::1]:iburst rd.ntp=pool:pool.ntp.org:iburst,prefer"
+}
+
+test_setup() {
+    # Create plain root filesystem
+    build_client_rootfs "$TESTDIR/rootfs"
+
+    # Create an ext4 image with the rootfs
+    build_ext4_image "$TESTDIR/rootfs" "$TESTDIR/root.img" dracut
+
+    # Create a file to be downloaded from the initrd
+    echo "dracut-chrony-success" > "$TESTDIR/remote-file.txt"
+
+    # We have to trick systemd to avoid taking its build time, see man
+    # systemd(1) for more details
+    touch -d "$FAKE_TIME" "$TESTDIR/clock-epoch"
+
+    # Create a certificate, we need to add it to the initrd, so we can call curl
+    # with the --cacert option, otherwise it fails with the error:
+    # "curl: (60) SSL certificate OpenSSL verify result: self-signed certificate (18)"
+    openssl req \
+        -quiet \
+        -new -x509 \
+        -keyout "$TESTDIR/$SSL_CERT" \
+        -subj "/CN=10.0.2.2/" \
+        -out "$TESTDIR/$SSL_CERT" \
+        -days 365 \
+        -nodes
+
+    # We will add a drop-in for dracut-pre-pivot.service, ordering it after
+    # time-sync.target, so it will wait until the system time is synchronized
+    {
+        echo "[Unit]"
+        echo "After=time-sync.target"
+    } > "$TESTDIR/dracut-wait.conf"
+
+    # Install a pre-pivot hook to fetch "remote-file.txt" using HTTPS, if the
+    # system clock is out of sync, curl will fail with the error:
+    # "curl: (60) SSL certificate OpenSSL verify result: certificate has expired (10)"
+    # and the script will unmount /sysroot, so the test should fail as well
+    # shellcheck disable=SC2016
+    {
+        echo "#!/bin/sh"
+        echo "command -v warn > /dev/null || . /lib/dracut-lib.sh"
+        echo 'warn "$(systemctl status chronyd.service)"'
+        echo "remote_file_content=\$(curl --cacert /etc/$SSL_CERT \"https://10.0.2.2:4443/remote-file.txt\")"
+        echo 'if [ "$remote_file_content" = "dracut-chrony-success" ]; then'
+        echo '    warn "$remote_file_content"'
+        echo "else"
+        echo '    warn "Failed to fetch remote-file.txt using HTTPS"'
+        echo "    umount /sysroot"
+        echo "fi"
+    } > "$TESTDIR/fetch-remote-file.sh"
+    chmod +x "$TESTDIR/fetch-remote-file.sh"
+
+    # Synchronizing the clock via NTP usually takes ~30s, if we want to test
+    # that fetching from HTTPS fails when the clock is out of sync, we would
+    # have to wait the default 3-minute timeout for a systemd service, so with
+    # the following drop-in we can reduce the time spent in the test
+    {
+        echo "[Service]"
+        echo "TimeoutSec=1min"
+    } > "$TESTDIR/chrony-less-timeout.conf"
+
+    # Build non-hostonly initrd to avoid adding local chrony configuration,
+    # pointing to a variety of NTP servers depending on the distribution
+    test_dracut \
+        --no-hostonly \
+        -i "$TESTDIR/clock-epoch" "/usr/lib/clock-epoch" \
+        -i "$TESTDIR/$SSL_CERT" "/etc/$SSL_CERT" \
+        -i "$TESTDIR/dracut-wait.conf" "/usr/lib/systemd/system/dracut-pre-pivot.service.d/dracut-wait.conf" \
+        -i "$TESTDIR/fetch-remote-file.sh" "/var/lib/dracut/hooks/pre-pivot/10-fetch-remote-file.sh" \
+        -i "$TESTDIR/chrony-less-timeout.conf" "/usr/lib/systemd/system/chrony-wait.service.d/chrony-less-timeout.conf" \
+        -a "chrony url-lib ${USE_NETWORK}"
+}
+
+test_cleanup() {
+    stop_webserver
+}
+
+# shellcheck disable=SC1090
+. "$testdir"/test-functions