Настройка часового пояса и синхронизации времени на Linux-сервере

Опубликовано 16 мин. чтения

Неверные часы сервера никогда не заявляют о себе как часы: они приходят отклонённым сертификатом, репозиторием, который не принимает apt, или cron-заданием не в тот час. Как задать часовой пояс и службу времени и как доказать, что синхронизация действительно работает.

На часы сервера никто не смотрит, пока они идут верно. Как только они сбиваются, о себе заявляют не часы, а отклонённый сертификат, репозиторий, который не принимает apt, cron-задание, сработавшее не в тот час, и журнал, который больше не удаётся сопоставить ни с одним другим.

Эта статья подробно разбирает шаг 5 из чек-листа для нового root-сервера. Кто выполнил там две команды, обязательную часть уже закрыл. Здесь речь идёт обо всём, что лежит за её пределами: о выборе службы времени, об аппаратных часах, об UTC против местного времени, о доказательстве синхронизации и о сообщениях об ошибках вокруг неё.

Все сведения относятся к Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS и Ubuntu 22.04 LTS. Команды написаны в расчёте на работу от имени root. Если вы работаете под обычным пользователем, добавляйте к каждой команде sudo.

Что на самом деле ломают неверные часы

Общий знаменатель у всех случаев один: ни одно из этих сообщений не говорит о часах.

  • TLS-сертификаты. У каждого сертификата есть окно действия. Если системное время оказалось раньше него, curl сообщает curl: (60) SSL certificate problem: certificate is not yet valid, если позже, то certificate has expired. Затронут при этом каждый исходящий вызов.
  • apt. В файлах Release записаны дата выпуска и дата истечения. Если часы отстают, приходит Release file for ... is not valid yet, если заметно спешат, то соответственно is expired. Сервер перестаёт получать обновления безопасности, и при этом ни одна служба не падает.
  • Журналы. Две машины с расхождением в пять минут уже не сопоставить друг с другом, а нужно это именно в такие моменты: при взломе или при сбое.
  • Cron-задания и таймеры systemd. cron считает в системном часовом поясе. Кто меняет пояс позже, сдвигает каждое задание. Если часы прыгают, задания выполняются дважды или не выполняются вовсе. Подробно об этом в статье настройка cron-задания.
  • Резервные копии. Почти любая схема резервного копирования называет каталоги по дате и удаляет их по возрасту. Часы, прыгнувшие на сутки назад, перезапишут вчерашнюю копию.
  • Одноразовые пароли на основе времени. TOTP считает окнами по 30 секунд с допуском обычно в одно окно в каждую сторону. Если часы сервера уходят дальше, отклоняется любой правильный код. Это единственный пункт списка, который действительно запирает вас снаружи.

Прежде чем что-то менять: путь назад и снимок состояния

Путь назад

Смена часового пояса не обрывает действующую SSH-сессию, и включение синхронизации тоже безобидно. Две вещи в этой статье безобидными не являются: часы, которые прыгают далеко, и смена службы времени. Большой прыжок назад временно делает действующие сертификаты недействительными и выбивает вход по TOTP из окна допуска. А смена службы времени удаляет старую раньше, чем заработает новая: если установка оборвётся посередине, у сервера вообще не останется синхронизации времени, и заметно это станет только через несколько дней.

У KVM root-серверов и выделенных серверов KernelHost нет ни IPMI, ни iDRAC. Доступ, который работает без сетевых служб внутри гостевой системы, это VNC-консоль в личном кабинете. Она относится к уровню виртуализации, соответственно к самому подключению, и неверные часы внутри гостевой системы на неё не влияют. Зайдите через эту консоль один раз заранее и проверьте, знаете ли вы пароль root.

Текущее состояние в четырёх командах

Запишите то, что действует сейчас. Без этой записи вы потом не поймёте, новое ли расхождение перед вами:

timedatectl
readlink -f /etc/localtime
date -u
systemctl is-active systemd-timesyncd chrony

Из семи строк вывода timedatectl важны три. Time zone называет пояс вместе с сокращением и смещением, например Europe/Vienna (CEST, +0200). System clock synchronized говорит, сверялись ли часы хоть раз. У NTP service есть три состояния, которые регулярно путают между собой:

СтрокаЧто она означаетЧто делать
NTP service: activeСлужба времени установлена и работает.Ничего, но перепроверить всё равно стоит.
NTP service: inactiveСлужба времени установлена, но не запущена.Запустить службу, причину искать в журнале.
NTP service: n/aСлужба времени не установлена вообще.Доустановить timesyncd или chrony.

В третьем случае timedatectl show -p CanNTP --value выдаёт no, а любая попытка включить синхронизацию заканчивается сообщением Failed to set ntp: NTP not supported.

Часовой пояс и синхронизация времени: две разные вещи

Ядро ведёт ровно один счётчик: секунды с 1 января 1970 года, отсчитанные в UTC. Этот счётчик и есть системное время, никакого часового пояса он не знает, пояс — это лишь вопрос отображения. Отсюда следуют два вывода. Смена часового пояса не сдвигает ни одного мгновения, date -u выдаёт до и после одно и то же. А синхронизация часов меняет счётчик, но не отображение, поэтому неверно заданный пояс так и останется неверным. Две задачи, две проверки.

Шаг 1: задать часовой пояс

Имена поясов происходят из базы IANA и почти всегда имеют вид Континент/Город, причём в английском написании. Найдите нужное имя, а не угадывайте его:

timedatectl list-timezones | grep -i vienna
timedatectl set-timezone Europe/Vienna

Проверка результата:

timedatectl show -p Timezone --value
readlink -f /etc/localtime
date +%Z

Ожидаются Europe/Vienna, путь /usr/share/zoneinfo/Europe/Vienna и сокращение, соответствующее времени года: летом CEST, зимой CET.

Три подводных камня

Файл /etc/timezone ничего не решает. Debian 13 его больше не поставляет, там cat /etc/timezone заканчивается сообщением No such file or directory, и пакет tzdata его тоже не возвращает. В трёх остальных системах файл ещё есть, но решающей везде остаётся одна только символьная ссылка /etc/localtime.

Без tzdata поясов не существует. В облегчённых образах, особенно у Ubuntu, базы часовых поясов нет. Тогда даже правильно написанное имя обрывается ошибкой Failed to set time zone: Invalid or not installed time zone 'Europe/Vienna', а timedatectl list-timezones выводит всего одну строку. После установки пакета строк должно стать несколько сотен:

DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata
timedatectl list-timezones | wc -l

Запущенные службы помнят старый пояс. cron, базы данных и серверы приложений читают часовой пояс при запуске и после смены пояса продолжают писать в журнал по старому, пока их не перезапустят.

В окружениях без работающего systemd команды timedatectl нет. Классический путь приводит к тому же результату:

ln -sf /usr/share/zoneinfo/Europe/Vienna /etc/localtime
dpkg-reconfigure -f noninteractive tzdata
readlink -f /etc/localtime

UTC или местное время: осознанное решение

Многие операторы держат серверы на UTC, и для этого есть веские причины. UTC не знает летнего времени, а значит, не знает ни часа, который проходит дважды, ни часа, которого нет: в ночь перевода стрелок 02:30 по местному времени осенью существует дважды, а весной не существует вовсе, и это касается каждого задания, попавшего в это окно. С другой стороны, журналы читают люди, а окно обслуживания «по воскресеньям в 03:00» означает именно местное время. Рабочее правило звучит так: кто ведёт несколько серверов или несколько площадок, берёт UTC, а кто держит один сервер по офисным часам, берёт местное время. Неверно только одно: не знать, как оно настроено.

timedatectl set-timezone Etc/UTC

Чтобы просто разок взглянуть на другое время, системный часовой пояс трогать не нужно: хватает переменной TZ, и действует она только на этот вызов:

TZ=Europe/Vienna date
TZ=Europe/Vienna journalctl -u nginx --since "today"

Шаг 2: выбрать службу времени

Для Debian и Ubuntu наготове три кандидата, которые решают одну и ту же задачу с очень разным размахом.

СлужбаЧто она умеетКогда она подходит
systemd-timesyncdЧистый клиент по SNTP, спрашивает время у одного сервера и переключается при его отказеОбычный случай для одиночного сервера
chronyПолноценный NTP-клиент и NTP-сервер, комбинирует несколько источников, приносит с собой средство диагностики chronyc, владеет NTSКогда вам нужно доказывать точность или искать ошибки
ntpsecПреемник эталонной реализации ntpdУнаследованные системы и особые случаи

Все три заявляют пакетной системе одну и ту же роль: Provides: time-daemon и одновременно Conflicts: time-daemon. Кто запросит две из них одной командой, получит отказ:

The following packages have unmet dependencies:
 chrony : Conflicts: time-daemon
 systemd-timesyncd : Conflicts: time-daemon
E: Unable to correct problems, you have held broken packages.

Кто ставит chrony при работающем timesyncd, не должен пропустить строку The following packages will be REMOVED: systemd-timesyncd. Так и задумано: два процесса, крутящие одни и те же часы, хуже, чем ни одного. Сразу после установки проверьте, работает ли новая служба.

Два имени пакетов из старых руководств отжили своё: ntp и ntpdate. В Debian 12 и в обеих версиях Ubuntu это лишь переходные пакеты, ведущие к ntpsec, а в Debian 13 apt-cache policy ntp просто сообщает Candidate: (none).

Вариант A: systemd-timesyncd

Пакет systemd во всех четырёх системах рекомендует systemd-timesyncd | time-daemon. Значит, обычная установка службу с собой приносит, а минимальный образ без рекомендованных пакетов нет.

DEBIAN_FRONTEND=noninteractive apt-get install -y systemd-timesyncd
systemctl enable --now systemd-timesyncd

Поставляемый файл /etc/systemd/timesyncd.conf содержит исключительно закомментированные значения по умолчанию. Собственным значениям место в дополняющем файле, каталога для которого из коробки не существует:

mkdir -p /etc/systemd/timesyncd.conf.d
cat > /etc/systemd/timesyncd.conf.d/10-kernelhost.conf <<'EOF'
[Time]
NTP=0.at.pool.ntp.org 1.at.pool.ntp.org 2.at.pool.ntp.org
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org
EOF
systemctl restart systemd-timesyncd

В NTP= перечислены серверы, у которых спрашивают время. FallbackNTP= вступает в дело только тогда, когда не отвечает ни один из них; из коробки там стоит в Debian пул Debian, а в Ubuntu ntp.ubuntu.com.

Проверка результата:

systemd-analyze cat-config systemd/timesyncd.conf
systemctl is-active systemd-timesyncd
timedatectl timesync-status

Первая команда показывает собранную конфигурацию, и ваш дополняющий файл должен появиться в ней с полным путём. Третья называет используемый сервер, интервал опроса и последнее измеренное смещение. Если вместо этого она отвечает Failed to query server: Connection timed out, значит timesyncd не работает. Это сообщение приходит через 25 секунд.

Вариант B: chrony

apt-get install -y chrony
systemctl enable --now chrony

Во всех четырёх дистрибутивах юнит называется chrony.service и дополнительно носит псевдоним chronyd.service. Поставляемый файл /etc/chrony/chrony.conf уже заполнен вполне пригодными значениями: Debian опрашивает pool 2.debian.pool.ntp.org iburst, Ubuntu опрашивает ntp.ubuntu.com плюс три записи из пула Ubuntu. Этот файл не меняйте. Через confdir /etc/chrony/conf.d он подключает каталог, который обновления пакетов оставляют нетронутым:

cat > /etc/chrony/conf.d/10-kernelhost.conf <<'EOF'
pool 0.at.pool.ntp.org iburst
EOF
systemctl restart chrony

Проверка результата командой chronyc tracking, вот как она выглядит на нормально работающем сервере:

Reference ID    : A29FC801 (time.cloudflare.com)
Stratum         : 4
Ref time (UTC)  : Thu Sep 03 17:53:29 2026
System time     : 0.000135970 seconds fast of NTP time
Last offset     : +0.000042723 seconds
RMS offset      : 0.000086483 seconds
Frequency       : 13.967 ppm fast
Residual freq   : +0.002 ppm
Skew            : 0.073 ppm
Root delay      : 0.008282715 seconds
Root dispersion : 0.000613841 seconds
Update interval : 1038.4 seconds
Leap status     : Normal

В повседневной работе хватает трёх строк. System time — это текущее расхождение, здесь около 136 микросекунд. Leap status должен быть Normal, а при Not synchronised у chrony ещё нет пригодного источника. Stratum говорит, насколько далеко вы от эталонных часов, и значения от 2 до 4 нормальны. Второй взгляд достаётся самим источникам, командой chronyc -n sources:

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^- 217.175.198.239               3  10   377   748   +114us[ +153us] +/-   19ms
^- 46.102.157.67                 2  10   377   558   +151us[ +192us] +/-   28ms
^* 162.159.200.1                 3  10   377   335   -251us[ -208us] +/- 4463us
^+ 152.53.132.244                2   9   377   231   +335us[ +335us] +/- 5626us

Два знака в самом начале строки и есть настоящий результат. ^* отмечает источник, по которому выставляются часы, ^+ тот, который тоже учитывается, ^- тот, который не комбинируется, ^? недостижимый, а ^x противоречивый. В колонке Reach стоит восьмеричное значение по последним восьми опросам: 377 означает, что ответили все восемь, 0 означает, что не пришёл ни один ответ.

Начиная с версии 4 chrony владеет Network Time Security, то есть аутентифицированным временем поверх TLS. Для этого нужны две вещи, которые легко упустить: пакет ca-certificates и открытый исходящий TCP-порт 4460. Если корневых сертификатов нет, сверка обрывается сообщением Error in the certificate verification. The certificate is NOT trusted. The certificate issuer is unknown.

apt-get install -y ca-certificates
cat > /etc/chrony/conf.d/20-nts.conf <<'EOF'
server time.cloudflare.com iburst nts
EOF
systemctl restart chrony
chronyc authdata

Аппаратные часы

Кроме системного времени есть вторые часы: аппаратные, сокращённо RTC. Именно они дают при запуске первое значение времени, задолго до того, как заработает служба времени. На KVM root-сервере это часы, предоставляемые уровнем виртуализации, и в выводе timedatectl они стоят в строке RTC time. Важна ровно одна настройка, последняя строка вывода:

timedatectl set-local-rtc 0
timedatectl | grep "RTC in local TZ"

Если там стоит yes, аппаратные часы читаются как местное время. Это уступка машинам, на которых параллельно запускается Windows, и на сервере она бессмысленна. Вред проявляется дважды в год: при переводе стрелок аппаратные часы, ведущиеся по местному времени, на один час перестают быть однозначными, и перезагрузка внутри этого окна может поднять сервер со временем, ошибающимся на час.

В обратную сторону действует такое правило: chrony благодаря настройке по умолчанию rtcsync регулярно записывает исправленное время обратно в аппаратные часы, и эта строка есть в поставляемом chrony.conf всех четырёх дистрибутивов. У systemd-timesyncd подобной возможности нет. Вручную это делается командой hwclock --systohc. В Debian 12, Debian 13 и Ubuntu 24.04 она приходит из пакета util-linux-extra; если оболочка отвечает hwclock: command not found, доустановите его. В Ubuntu 22.04 команда входит в util-linux.

Шаг 3: доказать, что синхронизация работает

То, что команда отработала без ошибок, ещё не доказательство. Доказательство — это следующие пять проверок:

  1. Общее состояние. timedatectl показывает System clock synchronized: yes и NTP service: active. Обе строки вместе, а не одна из них.
  2. Сама служба. systemctl is-enabled chrony и systemctl is-active chrony отвечают enabled и active, для timesyncd соответственно. Одно только enabled означает лишь то, что служба запустилась бы при следующей загрузке.
  3. Источник действительно достижим. У chrony в выводе chronyc -n sources должна стоять хотя бы одна строка со знаком ^*, а колонка Reach должна уйти от 0. У timesyncd команда timedatectl timesync-status называет конкретный сервер.
  4. Смещение невелико. chronyc tracking должен показывать в строке System time микросекунды или миллисекунды. Целые секунды означают, что коррекция ещё идёт или что-то заело.
  5. Всё это переживает перезагрузку. Перезагрузите сервер один раз и повторите проверки с 1 по 4. Это единственная проверка, которая отвечает на вопрос окончательно.

Строка, которой нельзя доверять в одиночку: System clock synchronized: yes отражает флаг в ядре, выставленный тем процессом, который последним переводил часы. Этот флаг не исчезает, когда служба времени падает. Значит, сервер может показывать эту строку и при этом часами работать без сверки.

Службы, которым при запуске обязательно нужны верные часы, вы упорядочиваете через After=time-sync.target. Чтобы эта цель достигалась только после сверки, нужен дополнительно ожидающий юнит: systemd-time-wait-sync.service у timesyncd и chrony-wait.service у chrony. Последний поставляют Debian 12, Debian 13 и Ubuntu 24.04, а Ubuntu 22.04 нет. Как устроен собственный юнит, описано в статье создание собственной systemd-службы.

Файрвол и сеть

NTP уходит наружу через UDP-порт 123, для NTS добавляется TCP 4460. В настройках UFW по умолчанию исходящий трафик разрешён, так что делать ничего не нужно. Кто задал ufw default deny outgoing, должен открыть порт, иначе часы встанут, и при этом ни одна служба не напишет сообщения об ошибке:

ufw allow out 123/udp comment 'NTP'

Остальное про файрвол описано в статье настройка файрвола UFW. В обратном направлении действует другое правило: служба времени, отвечающая на запросы из интернета, работает усилителем для атак с отражением. chrony и systemd-timesyncd из коробки не отвечают никому, и только строка allow в конфигурации chrony превращает клиента в сервер. Задавайте её только с ограничением на вашу собственную сеть. Фильтрация на подступах в дата-центре maincubes во Франкфурте-на-Майне такой трафик перехватывает, но лучшим усилителем остаётся тот, которого вообще нет.

Когда часы ушли далеко

Обычно службы времени исправляют расхождение не прыжком, а минимальным ускорением или замедлением хода часов. Поэтому расхождение в минуту не исчезает за секунду, и это правильно: прыжок назад приводит к тому, что отметки времени встречаются дважды.

Для только что запущенных систем в поставляемом chrony.conf всех четырёх дистрибутивов стоит строка makestep 1 3: она разрешает настоящий прыжок при смещении больше секунды, и только для первых трёх сверок. Ровно такой случай возникает у виртуальной машины, склонированной из образа или поднятой из снимка. Если этого не хватает, вызовите прыжок принудительно и дождитесь результата:

chronyc makestep
chronyc waitsync 10

Измерить, ничего не меняя, позволяет ключ -Q: он опрашивает настроенные источники, сообщает расхождение и завершается, не трогая часы. Интересующая вас строка выглядит тогда примерно так: System clock wrong by 0.000363 seconds (ignored):

chronyd -Q -f /etc/chrony/chrony.conf

Чего делать не стоит, так это выставлять часы вручную через date -s при работающей службе времени. timedatectl set-time прямо отказывается это делать с сообщением Failed to set time: Automatic time synchronization is enabled, потому что иначе одни и те же часы крутили бы сразу две инстанции.

Частые ошибки и их решения

Failed to set time zone: Invalid or not installed time zone 'Europe/Wien': такого имени пояса не существует. База IANA ведёт английские названия городов, поэтому правильно Europe/Vienna, Europe/Zurich и Europe/Prague. Если то же самое сообщение приходит на правильно написанное имя, значит отсутствует база часовых поясов: контрольная проверка это timedatectl list-timezones | wc -l, и если остаётся одна-единственная строка, доустановите tzdata.

Failed to set ntp: NTP not supported: служба времени не установлена вовсе, и timedatectl show -p CanNTP --value выдаёт тогда no. Ключ set-ntp управляет только теми службами, которые зарегистрировались в /usr/lib/systemd/ntp-units.d/: timesyncd файлом 80-systemd-timesync.list, chrony файлом 50-chrony.list.

timedatectl set-ntp true отрабатывает без ошибок, а NTP service всё равно остаётся inactive: команда сообщает лишь о том, что она дала юниту указание, а не о том, что он работает. Причина стоит в журнале, например по journalctl -u systemd-timesyncd -n 20.

506 Cannot talk to daemon: chronyc не достучался до службы, потому что chronyd не работает. Причину называет systemctl status chrony. Это сообщение одинаково приходит на любую подкоманду chronyc.

chrony.service - chrony, an NTP client/server was skipped because of an unmet condition check (ConditionCapability=CAP_SYS_TIME).: системе вообще не разрешено переводить часы. У VPS на контейнерной основе (LXC, OpenVZ) это нормальное положение вещей, там время задаёт хост-система. На KVM root-сервере гостевая система вправе выставлять свои часы сама, и там такое сообщение указывает на настоящую неисправность. Со стороны timesyncd тот же случай выглядит так: systemd-timesyncd.service - Network Time Synchronization was skipped because of an unmet condition check (ConditionVirtualization=!container).

Release file for ... is not valid yet при apt update: часы отстают. Сначала выправьте время, затем повторите apt update. И наоборот, is expired указывает на спешащие часы, реже на устаревшее зеркало.

Failed to query server: Connection timed out при timedatectl timesync-status: timesyncd не работает или его заменил chrony. Если активная служба это chrony, данная команда так и остаётся без ответа, и это не ошибка. Правильный инструмент в таком случае называется chronyc tracking.

Различия между дистрибутивами одним взглядом

ПунктDebian 13Debian 12Ubuntu 24.04Ubuntu 22.04
Версия chrony4.6.14.34.54.2
Источник в chrony.confпул Debianпул Debianntp.ubuntu.com плюс пул Ubuntuntp.ubuntu.com плюс пул Ubuntu
/etc/timezoneбольше нетестьестьесть
hwclock из пакетаutil-linux-extrautil-linux-extrautil-linux-extrautil-linux
chrony-wait.serviceдададанет
ntp и ntpdateбольше не существуютпереходные пакетыпереходные пакетыпереходные пакеты

Зато везде одинаково следующее: часовой пояс держится исключительно на символьной ссылке /etc/localtime, а одна служба времени исключает любую другую.

Короткая версия

Для только что выданного root-сервера, который должен работать по местному времени и которому хватает стандартной службы:

DEBIAN_FRONTEND=noninteractive apt-get install -y systemd-timesyncd tzdata
timedatectl set-timezone Europe/Vienna
timedatectl set-local-rtc 0
systemctl enable --now systemd-timesyncd
timedatectl

В конце ожидаются Time zone: Europe/Vienna, System clock synchronized: yes, NTP service: active и RTC in local TZ: no. Если эти четыре строки выглядят так же и после перезагрузки, с часами этого сервера покончено.

Частые вопросы

Что ломается, если часы сервера идут неверно?
Заметными становятся не сами часы, а последствия. У каждого TLS-сертификата есть окно действия: если системное время оказалось раньше него, curl сообщает «curl: (60) SSL certificate problem: certificate is not yet valid», если позже, то «certificate has expired». apt отклоняет файлы Release сообщением «Release file for ... is not valid yet», и сервер перестаёт получать обновления безопасности, при этом ни одна служба не падает. К этому добавляются журналы, которые больше не сопоставить друг с другом, cron-задания не в тот час, резервные копии, названные по дате и перезаписывающие вчерашние, а также одноразовые пароли на основе времени. TOTP считает окнами по 30 секунд с допуском обычно в одно окно в каждую сторону, поэтому часы сервера, ушедшие дальше, действительно запирают вас снаружи.
Меняется ли время на сервере, если я сменю часовой пояс?
Нет. Ядро ведёт ровно один счётчик, секунды с 1 января 1970 года в UTC, а часовой пояс — это исключительно вопрос отображения. Команда date -u выдаёт до и после смены один и тот же результат. Обратное тоже верно: синхронизация меняет счётчик, но не отображение, поэтому неверно заданный пояс так и останется неверным. Это две задачи и две проверки. Учтите к тому же, что cron, базы данных и серверы приложений читают часовой пояс при запуске и до своего перезапуска продолжают писать в журнал по старому поясу.
Почему timedatectl сообщает «Failed to set time zone: Invalid or not installed time zone»?
Причин две. Либо такого имени не существует: база IANA ведёт английские названия городов, поэтому правильно Europe/Vienna, а не Europe/Wien, и точно так же Europe/Zurich и Europe/Prague. Либо отсутствует база часовых поясов, что встречается в облегчённых образах, особенно у Ubuntu. Контрольная проверка это timedatectl list-timezones | wc -l: если остаётся одна-единственная строка, доустановите tzdata, после чего строк должно стать несколько сотен. Решающей для пояса, кстати, является одна только символьная ссылка /etc/localtime, а не файл /etc/timezone, который Debian 13 вообще больше не поставляет.
systemd-timesyncd или chrony: какую службу времени выбрать?
systemd-timesyncd это чистый клиент по SNTP, он спрашивает время у одного сервера и переключается при его отказе. Для одиночного сервера это обычный случай. chrony это полноценный NTP-клиент и NTP-сервер, он комбинирует несколько источников, приносит с собой средство диагностики chronyc и владеет Network Time Security, то есть аутентифицированным временем поверх TLS. Берите chrony, если вам нужно доказывать точность или искать ошибки. Обе службы вместе поставить нельзя: каждая заявляет пакетной системе «Provides: time-daemon» и одновременно «Conflicts: time-daemon». Поэтому установка chrony удаляет systemd-timesyncd, что видно по строке «The following packages will be REMOVED: systemd-timesyncd». Сразу после этого проверьте, работает ли новая служба.
timedatectl set-ntp обрывается ошибкой «Failed to set ntp: NTP not supported». Чего не хватает?
Служба времени не установлена вообще. В выводе timedatectl в строке NTP service стоит тогда значение n/a, а timedatectl show -p CanNTP --value выдаёт no. Ключ set-ntp управляет только теми службами, которые зарегистрировались в /usr/lib/systemd/ntp-units.d/: timesyncd файлом 80-systemd-timesync.list, chrony файлом 50-chrony.list. Доустановите одну из двух. От этого случая надо отличать NTP service: inactive, когда служба есть, но не запущена, и причина стоит в журнале.
chrony не запускается на моём VPS и сообщает о невыполненном условии. Это ошибка?
В журнале стоит тогда «was skipped because of an unmet condition check (ConditionCapability=CAP_SYS_TIME)», то есть системе вообще не разрешено переводить часы. У VPS на контейнерной основе (LXC, OpenVZ) это нормальное положение вещей, там время задаёт хост-система. На KVM root-сервере гостевая система вправе выставлять свои часы сама, и там такое сообщение указывает на настоящую неисправность. Со стороны timesyncd тот же случай выглядит как условие ConditionVirtualization=!container.
Как доказать, что синхронизация времени действительно работает?
Одной строки System clock synchronized: yes недостаточно. Она отражает флаг в ядре, выставленный тем процессом, который последним переводил часы, и этот флаг не исчезает, когда служба времени падает. Поэтому проверьте пять вещей: что рядом стоит NTP service: active, что systemctl is-enabled и is-active отвечают для службы enabled и active, что источник действительно достижим (у chrony строка со знаком ^* в chronyc -n sources и колонка Reach, отличная от 0, у timesyncd конкретный сервер в timedatectl timesync-status), что chronyc tracking показывает в строке System time микросекунды или миллисекунды, и что всё это переживает перезагрузку. Окончательный ответ на вопрос даёт только последняя проверка.
Сервер должен работать на UTC или по местному времени?
Кто ведёт несколько серверов или несколько площадок, берёт UTC, а кто держит один сервер по офисным часам, берёт местное время. За UTC говорит то, что он не знает летнего времени: в ночь перевода стрелок 02:30 по местному времени осенью существует дважды, а весной не существует вовсе, и это касается каждого задания в этом окне. С другой стороны, журналы читают люди, а окно обслуживания в воскресенье в 03:00 означает местное время. Неверно только одно: не знать, как оно настроено. Чтобы просто разок взглянуть, системный часовой пояс трогать не нужно, TZ=Europe/Vienna date действует только на этот вызов. Независимо от этого решения аппаратные часы должны стоять на UTC: timedatectl set-local-rtc 0, и в выводе должно быть RTC in local TZ: no.

Часовой пояс NTP timedatectl chrony systemd-timesyncd Linux Debian Ubuntu