-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
systemd: improve the time synchronisation process at boot
Improve the reliability and robustness of time synchronisation during boot. A new time-set.target has been added (as per systemd versions since v242). The timeinit-rtc and timeinit-timestamp services have been added to the time-set.target. Chrony is now part of the time-sync.target and has a dependency on the time-set.target. New services have been added to the time-sync.target to ensure that system time is synchronised with a remote source before the time-sync.target is reached. The timesync-remote service is a blocking service that will only terminate if: a) NTP synchronisation has been achieved (via chrony), or b) time is successfully updated using ntpdate, or c) time is successfully updated from an HTTPS header (using curl). The timesync-https service is a background service that will periodically attempt to update the system time from an HTTPS header. The service will terminate if NTP synchronisation has been achieved (via chrony). This service provides a time synchronisation backup in cases where access to NTP port 123 is blocked. The openvpn service now pulls in the time-sync.target and will only start after initial time synchronisation has completed as described above. Change-type: minor Connects-to: #1852 #1776 #1337 Signed-off-by: Mark Corbin <mark@balena.io>
- Loading branch information
1 parent
abdd15e
commit 3c652f2
Showing
12 changed files
with
287 additions
and
11 deletions.
There are no files selected for viewing
16 changes: 15 additions & 1 deletion
16
meta-balena-common/recipes-connectivity/openvpn/files/openvpn.service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 5 additions & 2 deletions
7
meta-balena-common/recipes-core/chrony/files/chronyd.conf.systemd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,14 @@ | ||
[Unit] | ||
Before=time-sync.target | ||
Wants=time-sync.target var-volatile-lib.service | ||
After=var-volatile-lib.service | ||
Wants=time-set.target var-volatile-lib.service | ||
After=time-set.target var-volatile-lib.service | ||
|
||
[Service] | ||
Type=simple | ||
Restart=always | ||
RestartSec=10s | ||
ExecStart= | ||
ExecStart=/usr/sbin/chronyd -s -d | ||
|
||
[Install] | ||
WantedBy=time-sync.target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
meta-balena-common/recipes-core/systemd/timeinit/time-set.target
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# SPDX-License-Identifier: LGPL-2.1+ | ||
# | ||
# This file is part of systemd. | ||
# | ||
# systemd is free software; you can redistribute it and/or modify it | ||
# under the terms of the GNU Lesser General Public License as published by | ||
# the Free Software Foundation; either version 2.1 of the License, or | ||
# (at your option) any later version. | ||
|
||
[Unit] | ||
Description=System Time Set | ||
Documentation=man:systemd.special(7) | ||
RefuseManualStart=yes |
3 changes: 3 additions & 0 deletions
3
meta-balena-common/recipes-core/systemd/timeinit/time-sync.target.conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[Unit] | ||
After=time-set.target | ||
Wants=time-set.target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
meta-balena-common/recipes-core/systemd/timeinit/timesync-https.service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright 2020 Balena Ltd. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
[Unit] | ||
Description=Initialize system clock from a secure website | ||
DefaultDependencies=no | ||
After=chronyd.service network.target timesync-remote.service | ||
Before=time-sync.target | ||
|
||
[Service] | ||
Type=simple | ||
RemainAfterExit=yes | ||
ExecStart=/bin/sh /usr/bin/timesync-https.sh | ||
|
||
[Install] | ||
WantedBy=time-sync.target |
64 changes: 64 additions & 0 deletions
64
meta-balena-common/recipes-core/systemd/timeinit/timesync-https.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/bin/sh | ||
# | ||
# Copyright 2020 Balena Ltd. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
trap 'exit' INT | ||
|
||
# Synchronisation period in seconds | ||
SLEEP_INTERVAL=1800 | ||
|
||
HTTPS_SERVER=https://balena-cloud.com | ||
|
||
|
||
function set_system_date { | ||
local DATETIME="$(echo "$1" | awk '{string=substr($0, 5, 8); print string;}')" | ||
local YEAR="$(echo "$1" | awk '{string=substr($0, 1, 4); print string;}')" | ||
local SEC="$(echo "$1" | awk '{string=substr($0, 13, 2); print string;}')" | ||
date -u "${DATETIME}${YEAR}.${SEC}" > /dev/null 2>&1 | ||
} | ||
|
||
function exit_service { | ||
echo "[INFO] Exiting HTTPS time synchronisation service." | ||
exit 0 | ||
} | ||
|
||
|
||
echo "[INFO] Starting HTTPS time synchronisation service." | ||
|
||
while [ true ]; do | ||
# Test for NTP synchronisation | ||
echo "[INFO] Checking NTP synchronisation." | ||
chronyc waitsync 1 > /dev/null 2>&1 | ||
RESULT=$? | ||
|
||
if [ $RESULT -eq 0 ]; then | ||
echo "[INFO] NTP service synchronised." | ||
exit_service | ||
fi | ||
|
||
SYS_TIME=$(date -u "+%4Y%2m%2d%2H%2M%2S") | ||
SERVER_TIME_STRING=$(curl --silent -m5 -k -I "$HTTPS_SERVER" --stderr - | grep -i Date: | sed -e 's/[Dd]ate: //') | ||
|
||
echo "[INFO] Checking HTTPS header time." | ||
if [ ! -z "$SERVER_TIME_STRING" ]; then | ||
SERVER_TIME=$(date "+%4Y%2m%2d%2H%2M%2S" -d "$SERVER_TIME_STRING") | ||
if [ "$SYS_TIME" -lt "$SERVER_TIME" ]; then | ||
set_system_date $SERVER_TIME | ||
echo "[INFO] Time synchronised via HTTPS." | ||
fi | ||
fi | ||
|
||
sleep $SLEEP_INTERVAL | ||
done |
30 changes: 30 additions & 0 deletions
30
meta-balena-common/recipes-core/systemd/timeinit/timesync-remote.service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Copyright 2020 Balena Ltd. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
[Unit] | ||
Description=Initialize system clock from a remote source | ||
DefaultDependencies=no | ||
ConditionPathExists=!/dev/rtc | ||
ConditionPathExists=!/var/lib/chrony/drift | ||
Wants=network-online.target | ||
After=chronyd.service network-online.target | ||
Before=time-sync.target | ||
|
||
[Service] | ||
Type=oneshot | ||
RemainAfterExit=yes | ||
ExecStart=/bin/sh /usr/bin/timesync-remote.sh | ||
|
||
[Install] | ||
WantedBy=time-sync.target |
102 changes: 102 additions & 0 deletions
102
meta-balena-common/recipes-core/systemd/timeinit/timesync-remote.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#!/bin/sh | ||
# | ||
# Copyright 2020 Balena Ltd. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
trap 'exit' INT | ||
|
||
BURST_COUNT=5 | ||
BURST_WAITSYNC_DELAY=3 | ||
NTPDATE_SERVER=0.resinio.pool.ntp.org | ||
HTTPS_SERVER=https://balena-cloud.com | ||
|
||
|
||
BURST_COUNTER=1 | ||
|
||
function set_system_date { | ||
local DATETIME="$(echo "$1" | awk '{string=substr($0, 5, 8); print string;}')" | ||
local YEAR="$(echo "$1" | awk '{string=substr($0, 1, 4); print string;}')" | ||
local SEC="$(echo "$1" | awk '{string=substr($0, 13, 2); print string;}')" | ||
date -u "${DATETIME}${YEAR}.${SEC}" > /dev/null 2>&1 | ||
} | ||
|
||
function exit_service { | ||
echo "[INFO] Exiting remote time synchronisation service." | ||
exit 0 | ||
} | ||
|
||
|
||
echo "[INFO] Starting remote time synchronisation service." | ||
|
||
while [ true ]; do | ||
# Test for NTP synchronisation | ||
echo "[INFO] Checking NTP synchronisation." | ||
chronyc waitsync 1 > /dev/null 2>&1 | ||
RESULT=$? | ||
|
||
if [ $RESULT -eq 0 ]; then | ||
echo "[INFO] NTP service synchronised." | ||
exit_service | ||
fi | ||
|
||
# Run an NTP burst every BURST_COUNT times round the loop | ||
if [ $BURST_COUNTER -eq $BURST_COUNT ]; then | ||
echo "[INFO] Starting NTP burst sequence." | ||
# Wait for any active bursts to complete | ||
echo -n "[INFO] Waiting for active bursts to complete..." | ||
BURST_HOSTS=$(chronyc activity | grep burst.*online | awk '{ print $1 }') | ||
if [ ! -z "$BURST_HOSTS" ]; then | ||
until [ $BURST_HOSTS -eq 0 ]; do | ||
sleep 5 | ||
BURST_HOSTS=$(chronyc activity | grep burst.*online | awk '{ print $1 }') | ||
if [ -z "$BURST_HOSTS" ]; then | ||
break | ||
fi | ||
done | ||
fi | ||
echo "done." | ||
echo "[INFO] Triggering NTP burst." | ||
chronyc burst 4/8 > /dev/null 2>&1 | ||
chronyc waitsync $BURST_WAITSYNC_DELAY > /dev/null 2>&1 | ||
RESULT=$? | ||
if [ $RESULT -eq 0 ]; then | ||
echo "[INFO] NTP service synchronised." | ||
exit_service | ||
fi | ||
BURST_COUNTER=0 | ||
fi | ||
|
||
# Run ntpdate | ||
echo "[INFO] Running ntpdate." | ||
ntpdate $NTPDATE_SERVER > /dev/null 2>&1 | ||
RESULT=$? | ||
if [ $RESULT -eq 0 ]; then | ||
echo "[INFO] Time synchronised via ntpdate." | ||
exit_service | ||
fi | ||
|
||
SYS_TIME=$(date -u "+%4Y%2m%2d%2H%2M%2S") | ||
SERVER_TIME_STRING=$(curl --silent -m5 -k -I "$HTTPS_SERVER" --stderr - | grep -i Date: | sed -e 's/[Dd]ate: //') | ||
|
||
echo "[INFO] Checking HTTPS header time." | ||
if [ ! -z "$SERVER_TIME_STRING" ]; then | ||
SERVER_TIME=$(date "+%4Y%2m%2d%2H%2M%2S" -d "$SERVER_TIME_STRING") | ||
if [ "$SYS_TIME" -lt "$SERVER_TIME" ]; then | ||
set_system_date $SERVER_TIME | ||
echo "[INFO] Time synchronised via HTTPS." | ||
exit_service | ||
fi | ||
fi | ||
let BURST_COUNTER=BURST_COUNTER+1 | ||
done |