From 1aa54e3f0a6e473f7a5fa02b8dc2c714f2ebea81 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Tue, 12 Nov 2024 12:20:17 +0900 Subject: [PATCH 1/5] Add `boot/00-check-rtc-and-wait-ntp.sh` to cidata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In vz, the VM lacks an RTC when booting with a kernel image (see: https://developer.apple.com/forums/thread/760344). This causes incorrect system time until NTP synchronizes it, leading to TLS errors. To avoid TLS errors, this script waits for NTP synchronization if RTC is unavailable. This script does the following: - Exits with 0 if `/dev/rtc0` exists. - Exits with 0 if `systemctl` is not available. - Enables `systemd-time-wait-sync.service` to wait for NTP synchronization at an earlier stage on subsequent boots. - Waits for NTP synchronization within the script for the first boot. Log output during execution: ```console LIMA 2024-08-08T23:51:15+09:00| Executing /mnt/lima-cidata/boot/00-check-rtc-and-wait-ntp.sh Created symlink /etc/systemd/system/sysinit.target.wants/systemd-time-wait-sync.service → /usr/lib/systemd/system/systemd-time-wait-sync.service. TimeUSec=Thu 2024-08-08 23:51:15 JST, Waiting for NTP synchronization... TimeUSec=Thu 2024-08-08 23:51:16 JST, Waiting for NTP synchronization... ... TimeUSec=Thu 2024-08-08 23:51:41 JST, Waiting for NTP synchronization... TimeUSec=Thu 2024-08-08 23:51:42 JST, Waiting for NTP synchronization... TimeUSec=Tue 2024-11-12 11:43:37 JST, NTP synchronization complete. NTPMessage={ Leap=0, Version=4, Mode=4, Stratum=2, Precision=-25, RootDelay=991us, RootDispersion=259us, Reference=11FD1CFB, OriginateTimestamp=Thu 2024-08-08 23:51:43 JST, ReceiveTimestamp=Tue 2024-11-12 11:43:36 JST, TransmitTimestamp=Tue 2024-11-12 11:43:36 JST, DestinationTimestamp=Thu 2024-08-08 23:51:43 JST, Ignored=no, PacketCount=1, Jitter=0 } ``` Signed-off-by: Norio Nomura --- .../boot/00-check-rtc-and-wait-ntp.sh | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh new file mode 100644 index 00000000000..f8f6c6f63b5 --- /dev/null +++ b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -eu + +# In vz, the VM lacks an RTC when booting with a kernel image (see: https://developer.apple.com/forums/thread/760344). +# This causes incorrect system time until NTP synchronizes it, leading to TLS errors. +# To avoid TLS errors, this script waits for NTP synchronization if RTC is unavailable. +test ! -c /dev/rtc0 || exit 0 + +# This script is intended for services running with systemd. +command -v systemctl >/dev/null 2>&1 || exit 0 + +# Enable `systemd-time-wait-sync.service` to wait for NTP synchronization at an earlier stage. +systemctl enable systemd-time-wait-sync.service + +# For the first boot, where the above setting is not yet active, wait for NTP synchronization here. +until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && [ "${ntp_synchronized}" = "yes" ]; do + time_usec=$(timedatectl show --property=TimeUSec) + echo "${time_usec}, Waiting for NTP synchronization..." + sleep 1 +done +# Print the result of NTP synchronization +ntp_message=$(timedatectl show-timesync --property=NTPMessage) +time_usec=$(timedatectl show --property=TimeUSec) +echo "${time_usec}, NTP synchronization complete." +echo "${ntp_message}" From 804ebf3a3755ede0f2f4a866c0cde86f50d099d8 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Thu, 14 Nov 2024 10:31:18 +0900 Subject: [PATCH 2/5] 00-check-rtc-and-wait-ntp.sh: Add `max_retry` for the maximum number of sync attempts. Signed-off-by: Norio Nomura --- .../boot/00-check-rtc-and-wait-ntp.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh index f8f6c6f63b5..2a8e6649490 100644 --- a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh +++ b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh @@ -13,13 +13,22 @@ command -v systemctl >/dev/null 2>&1 || exit 0 systemctl enable systemd-time-wait-sync.service # For the first boot, where the above setting is not yet active, wait for NTP synchronization here. -until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && [ "${ntp_synchronized}" = "yes" ]; do +max_retry=60 retry=0 +until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && [ "${ntp_synchronized}" = "yes" ] || + [ "${retry}" -gt "${max_retry}" ]; do time_usec=$(timedatectl show --property=TimeUSec) echo "${time_usec}, Waiting for NTP synchronization..." + retry=$((retry + 1)) sleep 1 done # Print the result of NTP synchronization ntp_message=$(timedatectl show-timesync --property=NTPMessage) time_usec=$(timedatectl show --property=TimeUSec) -echo "${time_usec}, NTP synchronization complete." -echo "${ntp_message}" +if [ "${ntp_synchronized}" = "yes" ]; then + echo "${time_usec}, NTP synchronization complete." + echo "${ntp_message}" +else + echo "${time_usec}, NTP synchronization timed out." + echo "${ntp_message}" + exit 1 +fi From 5d69caaa734fd1d2b40dc2d8675aedddf825ef59 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Mon, 25 Nov 2024 14:11:24 +0900 Subject: [PATCH 3/5] 00-check-rtc-and-wait-ntp.sh: Set the system time to th modification time of the script The larger the difference between this system time and the NTP server time, the longer the NTP synchronization will take. By setting the system time to the modification time of this script, which is likely to be closer to the actual time, the NTP synchronization time can be shortened. Signed-off-by: Norio Nomura --- .../boot/00-check-rtc-and-wait-ntp.sh | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh index 2a8e6649490..2b6e1853782 100644 --- a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh +++ b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh @@ -9,6 +9,11 @@ test ! -c /dev/rtc0 || exit 0 # This script is intended for services running with systemd. command -v systemctl >/dev/null 2>&1 || exit 0 +echo_with_time_usec() { + time_usec=$(timedatectl show --property=TimeUSec) + echo "${time_usec}, ${1}" +} + # Enable `systemd-time-wait-sync.service` to wait for NTP synchronization at an earlier stage. systemctl enable systemd-time-wait-sync.service @@ -16,19 +21,43 @@ systemctl enable systemd-time-wait-sync.service max_retry=60 retry=0 until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && [ "${ntp_synchronized}" = "yes" ] || [ "${retry}" -gt "${max_retry}" ]; do - time_usec=$(timedatectl show --property=TimeUSec) - echo "${time_usec}, Waiting for NTP synchronization..." + if [ "${retry}" -eq 0 ]; then + # If /dev/rtc is not available, the system time set during the Linux kernel build is used. + # The larger the difference between this system time and the NTP server time, the longer the NTP synchronization will take. + # By setting the system time to the modification time of this script, which is likely to be closer to the actual time, + # the NTP synchronization time can be shortened. + echo_with_time_usec "Setting the system time to the modification time of ${0}." + + # To set the time to a specified time, it is necessary to stop systemd-timesyncd. + systemctl stop systemd-timesyncd + + # Since `timedatectl set-time` fails if systemd-timesyncd is not stopped, + # ensure that it is completely stopped before proceeding. + until pid_of_timesyncd=$(systemctl show systemd-timesyncd --property=MainPID --value) && [ "${pid_of_timesyncd}" -eq 0 ]; do + echo_with_time_usec "Waiting for systemd-timesyncd to stop..." + sleep 1 + done + + # Set the system time to the modification time of this script. + modification_time=$(stat -c %y "${0}") + echo_with_time_usec "Setting the system time to ${modification_time}." + timedatectl set-time "${modification_time}" + + # Restart systemd-timesyncd + systemctl start systemd-timesyncd + else + echo_with_time_usec "Waiting for NTP synchronization..." + fi retry=$((retry + 1)) sleep 1 done # Print the result of NTP synchronization ntp_message=$(timedatectl show-timesync --property=NTPMessage) -time_usec=$(timedatectl show --property=TimeUSec) if [ "${ntp_synchronized}" = "yes" ]; then - echo "${time_usec}, NTP synchronization complete." + echo_with_time_usec "NTP synchronization complete." echo "${ntp_message}" else - echo "${time_usec}, NTP synchronization timed out." + echo_with_time_usec "NTP synchronization timed out." echo "${ntp_message}" exit 1 fi From 0539eb6890081f3abd363bb0f5ad59b5da8b9145 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Tue, 26 Nov 2024 09:23:09 +0900 Subject: [PATCH 4/5] 00-check-rtc-and-wait-ntp.sh: Remove enabling systemd-time-wait-sync.service Because it is slower than setting the system time to the modification time of this script. Signed-off-by: Norio Nomura --- pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh index 2b6e1853782..d266ca15328 100644 --- a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh +++ b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh @@ -14,9 +14,6 @@ echo_with_time_usec() { echo "${time_usec}, ${1}" } -# Enable `systemd-time-wait-sync.service` to wait for NTP synchronization at an earlier stage. -systemctl enable systemd-time-wait-sync.service - # For the first boot, where the above setting is not yet active, wait for NTP synchronization here. max_retry=60 retry=0 until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && [ "${ntp_synchronized}" = "yes" ] || From c92b979223fb5e221bde77dbdf0f27961e300117 Mon Sep 17 00:00:00 2001 From: Norio Nomura Date: Wed, 27 Nov 2024 10:19:34 +0900 Subject: [PATCH 5/5] 00-check-rtc-and-wait-ntp.sh: change the file used to read the modification time from the script itself to `user-data` Signed-off-by: Norio Nomura --- .../boot/00-check-rtc-and-wait-ntp.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh index d266ca15328..c799e9c1b13 100644 --- a/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh +++ b/pkg/cidata/cidata.TEMPLATE.d/boot/00-check-rtc-and-wait-ntp.sh @@ -21,9 +21,12 @@ until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && if [ "${retry}" -eq 0 ]; then # If /dev/rtc is not available, the system time set during the Linux kernel build is used. # The larger the difference between this system time and the NTP server time, the longer the NTP synchronization will take. - # By setting the system time to the modification time of this script, which is likely to be closer to the actual time, + # By setting the system time to the modification time of the reference file, which is likely to be closer to the actual time, + reference_file="${LIMA_CIDATA_MNT:-/mnt/lima-cidata}/user-data" + [ -f "${reference_file}" ] || reference_file="${0}" + # the NTP synchronization time can be shortened. - echo_with_time_usec "Setting the system time to the modification time of ${0}." + echo_with_time_usec "Setting the system time to the modification time of ${reference_file}." # To set the time to a specified time, it is necessary to stop systemd-timesyncd. systemctl stop systemd-timesyncd @@ -35,8 +38,8 @@ until ntp_synchronized=$(timedatectl show --property=NTPSynchronized --value) && sleep 1 done - # Set the system time to the modification time of this script. - modification_time=$(stat -c %y "${0}") + # Set the system time to the modification time of the reference file. + modification_time=$(stat -c %y "${reference_file}") echo_with_time_usec "Setting the system time to ${modification_time}." timedatectl set-time "${modification_time}"