SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-26

Почему на VPS сбивается время и как его синхронизировать

Узнайте, почему системные часы на виртуальном сервере отстают или спешат. Разберитесь в работе chronyc и timedatectl, чтобы устранить ошибки синхронизации и восстановить работу 2FA.

Почему на VPS сбиваются часы

Часы на VPS сбиваются, потому что их никто не корректирует. Ядро отсчитывает время по аппаратному счетчику, который работает чуть быстрее или медленнее нормы. Если клиент синхронизации времени не запущен, эта небольшая погрешность накапливается с каждым часом. Внутри виртуальной машины есть вторая причина: гостевая система делит физический процессор с другими гостями, поэтому моменты, когда она не получает процессорное время, становятся моментами, когда она не может вести отсчет.

На современных KVM-гостях сам счетчик редко является реальной проблемой. Паравиртуальный источник kvm-clock считывает значение, которое поддерживает хост, поэтому исправная гостевая система точно следует за временем хоста. Если часы показывают явно неверное время, причина обычно более прозаична. Либо не запущен демон синхронизации, либо запущены два и конфликтуют между собой, либо исходящий UDP порт 123 заблокирован в сети вашего провайдера. Гостевая система получает настройки времени от хоста или через NTP (network time protocol), а не от собственного осциллятора.

К чему приводит рассинхронизация системного времени

  • Коды двухфакторной аутентификации TOTP (time-based one-time password) перестают совпадать, из-за чего вы теряете доступ к серверу, даже если пароль и ключ верны.
  • Сертификат, выпущенный минуту назад, отклоняется, а curl выводит SSL certificate problem: certificate is not yet valid.
  • apt update отказывается работать с репозиторием, выдавая E: Release file for ... is not valid yet (invalid for another 1d 2h 3min 4s).
  • Запланированные задачи запускаются не вовремя, а скачок времени может привести к тому, что одна задача выполнится дважды, а другая будет пропущена.
  • Логи с двух разных серверов невозможно сопоставить, поэтому хронологию инцидента приходится восстанавливать методом догадок.

Допустимое отклонение меньше, чем принято считать. Приведенные ниже цифры являются задокументированными значениями по умолчанию, а не результатами измерений.

ChartHow far the clock can be off before something breaks (documented defaults)
The data behind this chart
[
  {
    "label": "TLS certificate boundary",
    "tolerance_seconds": 0,
    "documented_in": "RFC 5280"
  },
  {
    "label": "chrony steps instead of slewing",
    "tolerance_seconds": 1,
    "documented_in": "Debian and Ubuntu chrony.conf"
  },
  {
    "label": "TOTP code, one time step",
    "tolerance_seconds": 30,
    "documented_in": "RFC 6238"
  },
  {
    "label": "Kerberos clock skew",
    "tolerance_seconds": 300,
    "documented_in": "MIT krb5 default"
  }
]

Код TOTP вычисляется на основе счетчика, который обновляется каждые 30 секунды, при этом большинство систем проверки допускают погрешность в один шаг в любую сторону. Полминуты ошибки в каждом направлении — это весь доступный запас. Протокол Kerberos гораздо более терпим: стандартное допустимое отклонение составляет 300 секунд. Сертификаты же не допускают никакой гибкости: они проверяются по фиксированным временным меткам с льготным периодом в 0 секунд, поэтому часы, спешащие всего на одну секунду, приведут к отклонению абсолютно валидного сертификата.

Три типа часов и то, какие из них важны

Системные часы — это то, что действительно важно. Это CLOCK_REALTIME ядра: количество секунд, прошедших с 1 января 1970 года UTC, которое хранится в оперативной памяти и используется всеми процессами для простановки меток времени. Строки логов, проверка сертификатов, коды TOTP и время изменения файлов — всё это опирается на них. Когда говорят, что время на сервере неверное, имеют в виду именно эти часы.

Аппаратные часы, также называемые RTC (real time clock), — это отдельный счетчик, который продолжает работать при выключенном питании. На физическом сервере это микросхема с питанием от батарейки. Внутри виртуальной машины они эмулируются гипервизором, поэтому по большей части являются артефактом хоста. Linux считывает их один раз при загрузке для получения начального значения, а затем ведет собственный отсчет. timedatectl выводит их значение в строке RTC time. Не используйте эту строку для отладки на VPS, так как она показывает представление о времени хоста, а не состояние синхронизации ваших системных часов. В контейнере /dev/rtc обычно отсутствует, поэтому hwclock --show завершается с ошибкой hwclock: Cannot access the Hardware Clock via any known method..

Источник времени (clocksource) — это механизм, с помощью которого ядро ведет отсчет между считываниями. Узнайте у своего ядра, какой источник оно выбрало:

cat /sys/devices/system/clocksource/clocksource0/current_clocksource
cat /sys/devices/system/clocksource/clocksource0/available_clocksource

В KVM вы обычно увидите kvm-clock. Он считывает значение, поддерживаемое хостом, поэтому гостевая система KVM даже без NTP-клиента некоторое время сохраняет относительную точность. tsc — это собственный счетчик процессора. Гостевые системы Xen сообщают о xen, а гостевые системы Hyper-V — об источнике hyperv. Не меняйте эту настройку без веских причин, подтвержденных измерениями, так как ядро уже выбрало лучший источник, которому оно доверяет на данном оборудовании.

Некоторые хосты также предоставляют гостевой системе устройство PTP (precision time protocol), которое позволяет chrony считывать время хоста напрямую, а не через сеть. Это стоит проверить, хотя на обычном VPS такая возможность часто недоступна:

sudo modprobe ptp_kvm
ls /dev/ptp*
cat /sys/class/ptp/ptp0/clock_name

Если modprobe завершается ошибкой или устройство не найдено, значит, ваш хост его не предоставляет, и единственным решением остается сетевой NTP. Если clock_name указывает на виртуальные часы KVM, chrony может использовать их с помощью директивы refclock PHC /dev/ptp0 poll 2 в своем конфигурационном файле.

Проверка состояния времени на вашей машине

Начните с одной команды. Она отвечает на вопрос «поддерживается ли точность часов» на одном экране.

timedatectl

Изучите эти строки, вместо того чтобы полагаться на запомненное число:

  • Local time и Universal time — это один и тот же момент времени, выведенный в вашем часовом поясе и в UTC. Если они идентичны, машина уже работает в UTC.
  • RTC time — это аппаратные часы, описанные выше. На VPS их можно игнорировать.
  • Time zone — это формат, который система использует для отображения локального времени.
  • System clock synchronized — это собственный флаг ядра. Демон времени устанавливает его, как только начинает доверять своим источникам, поэтому no означает, что с момента загрузки часы не корректировались.
  • NTP service сообщает о состоянии systemd-timesyncd. n/a — это норма для машины, где запущен chrony, так как timesyncd там не установлен. System clock synchronized: yes вместе с NTP service: n/a означает, что chrony выполняет свою работу, а ядро подтверждает её корректность.

Затем узнайте, насколько велико отклонение. Не сравнивайте время «на глаз» с телефоном. Если запущен chrony:

chronyc tracking
chronyc sources -v

chronyc tracking выводит числа, отвечающие на этот вопрос. System time — это текущее смещение относительно времени NTP, за которым следует слово fast или slow. Last offset — это размер последней коррекции. Frequency — это ошибка частоты, которую chrony измерил в ваших часах и уже компенсирует. Leap status должно содержать Normal. Если там указано Not synchronised, а Reference ID равно 00000000 (), значит, chrony еще не выбрал источник синхронизации.

chronyc sources -v выводит легенду над списком, чтобы вам не пришлось запоминать символы. Два столбца несут основную информацию. Символ состояния в начале каждой строки показывает, как chrony оценивает этот источник: * отмечает источник, который используется в данный момент, а ? в каждой строке означает, что источник не отвечает. Reach — это история ответов последних восьми опросов в восьмеричном виде: 377 означает, что все восемь ответили, 0 — что не ответил никто.

Если за синхронизацию отвечает systemd-timesyncd:

timedatectl timesync-status
timedatectl show-timesync --all

timesync-status выводит сервер, с которым идет обмен данными, интервал опроса и значение Offset. Если команда возвращает ошибку службы вместо вывода статуса, значит, timesyncd не является активным демоном на этой машине, что само по себе является ответом на ваш вопрос.

Для грубой проверки относительно внешнего мира без дополнительных инструментов сравните свои часы с заголовком HTTP Date, который передается в GMT с точностью до одной секунды:

date -u
curl -sI https://www.cloudflare.com | grep -i '^date:'

Разница в одну или две секунды здесь нормальна и ничего не значит. Разница в минуту — это ваша ошибка.

chrony или systemd-timesyncd на VPS

В Ubuntu и Debian по умолчанию используется systemd-timesyncd. Это SNTP-клиент (simple network time protocol): он опрашивает один сервер за раз и постепенно подстраивает системные часы. Для машины, которая постоянно находится в сети и имеет изначально верное время, этого достаточно, а потребление ресурсов минимально.

chrony — это полноценная реализация NTP, которая лучше подходит для виртуальных машин, что видно по результатам её работы. Она опрашивает несколько источников одновременно и отбрасывает недостоверные. chrony измеряет погрешность хода часов и записывает её в drift-файл, что позволяет корректировать тенденцию отклонения, а не просто подгонять время под каждый отдельный отсчёт. Она также быстро восстанавливается после событий, характерных для виртуальных машин, но не для физических серверов: приостановка работы хостом или миграция на другой хост во время работы. Если хост предоставляет PTP-устройство, именно chrony считывает с него данные.

sudo apt update && sudo apt install -y chrony
systemctl status chrony --no-pager
chronyc sources -v
chronyc tracking

Следите за выводом apt во время установки. В Debian и Ubuntu пакеты chrony и systemd-timesyncd предоставляют time-daemon, поэтому apt удаляет timesyncd при установке chrony. Это корректное и ожидаемое поведение. Никогда не запускайте оба сервиса одновременно: два демона, пытающиеся управлять одними часами, будут конфликтовать, и их показаниям смещения нельзя будет доверять. В Rocky и AlmaLinux используйте sudo dnf install -y chrony, где юнит называется chronyd, а не chrony.

Файл конфигурации находится по пути /etc/chrony/chrony.conf в Debian и Ubuntu, и /etc/chrony.conf в Rocky и Alma. Настройки по умолчанию подходят для VPS, поэтому меняйте их только при необходимости. Стоит понимать назначение двух директив:

  • Строки pool и server задают источники времени. Добавление iburst указывает chrony отправлять быстрый пакет при запуске, чтобы первая синхронизация произошла за секунды, а не за минуты.
  • makestep определяет, когда chrony выполняет скачок времени вместо плавного сдвига. Проверьте текущее значение с помощью grep -n makestep /etc/chrony/chrony.conf. Значение по умолчанию в Debian и Ubuntu, makestep 1 3, означает следующее: в течение первых трёх обновлений после запуска chronyd время будет скорректировано скачком, если отклонение превышает одну секунду, а в дальнейшем — только плавным сдвигом.

Если вы хотите защитить трафик времени от подмены на пути следования, chrony версии 4 и выше поддерживает NTS (network time security). Сначала подтвердите свою версию командой chronyd -v и учтите, что для NTS необходимо открыть исходящий TCP-порт 4460 в дополнение к UDP 123:

server time.cloudflare.com iburst nts

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

sudo systemctl restart chrony
chronyc sources -v
chronyc tracking

Почему часы, спешащие или отстающие на несколько минут, не корректируются автоматически

У демона синхронизации времени есть два способа устранения смещения. Плавная корректировка (slewing) ускоряет или замедляет ход часов до тех пор, пока ошибка не исчезнет; при этом время движется только вперед, а временные метки не повторяются и не пропускаются. Резкая корректировка (stepping) мгновенно устанавливает правильное значение; это происходит быстро, но может привести к переводу часов назад. Перевод времени назад опасен для любых процессов, измеряющих длительность событий по системным часам, поэтому оба типа демонов предпочитают плавную корректировку.

Именно из-за этого предпочтения часы с большой погрешностью могут долго оставаться неточными. chrony выполняет резкую корректировку только в пределах окна, заданного параметром makestep, которое по умолчанию открыто лишь в течение нескольких первых обновлений после запуска демона. Если chronyd проработал неделю, а затем обнаружил ошибку в 40 секунд, он будет устранять её плавно, а плавная корректировка 40 секунд занимает гораздо больше времени, чем вы готовы ждать. Выполните принудительную корректировку один раз, осознанно, в период низкой нагрузки:

sudo chronyc makestep
chronyc tracking

Теперь chronyc tracking должен показывать System time со значением, близким к нулю, а Last offset отобразит величину только что исправленного смещения. Подумайте перед выполнением этой операции на сервере с активной базой данных, так как скачок времени назад может нарушить работу программного обеспечения, рассчитанного на монотонное течение времени вперед. Перезапуск демона — более щадящий вариант того же исправления, так как окно makestep снова открывается при старте.

Контейнеры используют системные часы хоста

У контейнера нет собственных часов реального времени, поэтому внутри него нечего синхронизировать. Пространства имен времени (time namespaces) в Linux виртуализируют только монотонные часы и часы с момента загрузки. CLOCK_REALTIME не виртуализируется, а значит, контейнер считывает те же системные часы, что и хост, на котором он запущен. Исправьте время на хосте, и оно мгновенно станет верным во всех контейнерах на этом хосте.

Из этого следует несколько выводов. Не устанавливайте chrony или ntpd в образ, так как в лучшем случае это не принесет никакой пользы. Попытка изменить дату внутри непривилегированного контейнера завершится ошибкой date: cannot set date: Operation not permitted, поскольку ядро требует наличия CAP_SYS_TIME для выполнения этого вызова. Предоставление CAP_SYS_TIME не дает контейнеру независимых часов, а позволяет изменять время хоста, а следовательно, и время всех остальных контейнеров.

Разница в часовых поясах внутри контейнера не является проблемой часов. Образ, содержащий собственный файл /etc/localtime, выводит тот же момент времени, отформатированный для другого пояса, поэтому date выглядит неверно, хотя сами часы идут правильно. Установите TZ=UTC в переменные окружения контейнера, и путаница исчезнет. Выбранная вами среда выполнения (runtime) здесь ничего не меняет, а сравнение rootless Podman и Docker описывает то, на что она действительно влияет.

Часовые пояса: UTC на сервере, местное время для пользователей

Установите на машине UTC и не меняйте этот параметр.

timedatectl list-timezones | grep -i utc
sudo timedatectl set-timezone UTC
timedatectl

В UTC нет перехода на летнее время, и в этом заключается главный аргумент. Ежедневная задача, запланированная на 02:30 в часовом поясе с переходом на летнее время, в день перевода часов назад выполнится дважды, а в день перевода вперед — не выполнится вовсе. В man 8 cron описана специальная обработка для сдвигов менее чем на три часа: задачи, пропущенные из-за перевода часов вперед, запускаются сразу после изменения, а задачи, попавшие в повторяющийся час при переводе назад, второй раз не запускаются. Такое поведение логично, но вам не стоит тратить время на размышления о нем в 03:00. В UTC задача выполняется один раз в день, каждый день в году. Если ваша задача не выполняется вовсе, а не просто запускается в странное время, то причины, по которым cron-задача молча не запускается — более вероятное объяснение.

Тот же аргумент применим к чтению логов. journalctl форматирует метки времени в системном часовом поясе, а journalctl --utc принудительно использует UTC. Наличие двух серверов в разных часовых поясах превращает каждый инцидент в упражнение по конвертации, а конвертация в условиях спешки — это то, как люди неправильно интерпретируют хронологию событий. Держите системы в UTC, храните метки времени в UTC и выполняйте конвертацию только в момент, когда их читает человек. Любой, кому нужно увидеть местное время для одной команды, может сделать это, не меняя настройки машины:

TZ=Europe/Berlin date

К этому разделу относится еще одна строка в выводе timedatectl. Параметр RTC in local TZ должен иметь значение no. Установка его в yes — это обходное решение для ноутбуков с двойной загрузкой Windows, а на сервере это лишь добавляет смещение, из-за которого кто-то может ошибиться в будущем. Когда этот параметр установлен, timedatectl выводит предупреждение о том, что система настроена на чтение времени RTC в местном часовом поясе.

Устранение неполадок по симптомам

Ваш двухфакторный код отклоняется на одном из серверов. Прежде всего проверьте системное время. Код генерируется на основе счетчика, который обновляется каждые 30 секунд, поэтому если часы сервера отстают на 90 секунд, он вычисляет код для шага, который ваш телефон уже прошел. timedatectl покажет System clock synchronized: no, или chronyc tracking сообщит о значительном System time смещении. Это не то же самое, что отклонение ключа, которое сопровождается собственным сообщением об ошибке и рассматривается в руководстве по ошибкам аутентификации с использованием открытого ключа.

apt update сообщает, что файл Release еще не действителен. Полное сообщение содержит название репозитория и время, в течение которого он будет оставаться недействительным, например is not valid yet (invalid for another 1d 2h 3min 4s). Ваши часы отстают от даты, указанной в файле Release репозитория, и этот интервал точно показывает величину отставания. Исправьте время. Не отключайте проверку даты в apt, чтобы обойти ошибку, так как эта проверка защищает вас от получения устаревшего индекса пакетов.

Каждая строка источника показывает состояние недоступности, а Reach равен 0. Ни один сервер не отвечает, поэтому проверьте исходящий трафик, а не конфигурацию. NTP использует исходящий UDP-порт 123, который в некоторых сетях фильтруется или перенаправляется. sudo chronyc ntpdata выводит счетчики по каждому источнику, включая Total TX и Total RX. Если счетчик TX растет, а RX остается на нуле, значит, ваши пакеты уходят, но ответы не приходят; это указывает на наличие брандмауэра между вами и источником.

Время было верным, но затем произошел скачок. Это случается при событиях на хосте. Восстановление из снимка (snapshot), приостановка гостевой системы или «живая» миграция на другой хост могут привести к тому, что время в гостевой системе начнет отставать от реального. chrony обнаруживает это при следующем опросе и корректирует время; systemd-timesyncd может сначала дождаться завершения длительного интервала опроса. Убедитесь, что демон запускается при загрузке с помощью systemctl is-enabled chrony, так как демон, запущенный вручную, перестанет работать после следующей перезагрузки.

Смещение небольшое, но не стабилизируется. Проверьте CPU steal. Если гостевая система не получает процессорное время в момент прерывания таймера, выборки задерживаются, и смещение начинает «плавать» вместо того, чтобы стабилизироваться. top отображает это как значение st в строке CPU. Чтение времени CPU steal на общем хосте объясняет, что означает это число и что можно предпринять.

Только что выпущенный сертификат отклоняется как еще не действительный. curl выводит SSL certificate problem: certificate is not yet valid, браузеры выдают аналогичное сообщение. С сертификатом все в порядке, просто часы, проверяющие его, отстают. Ошибка может быть на любой из сторон, поэтому проверьте и клиент, и сервер. Если неверное время установлено на сервере, выпустившем сертификат, руководство по certbot и сертификатам nginx описывает процесс обновления для такой конфигурации.

Добавьте это в список выполняемых проверок

Синхронизация времени — это настройка, выполняемая при загрузке, сбои которой могут оставаться незамеченными месяцами. Именно такие проблемы выявляются регулярными проверками, а не памятью администратора. timedatectl и chronyc tracking читаются за две секунды. Выполняйте их в рамках первых десяти минут работы с новым VPS, а также при прохождении регулярного списка задач по обслуживанию Linux-сервера. Если вы хотите, чтобы проверка выполнялась автоматически и уведомляла вас при увеличении смещения, написание systemd service и timer описывает шаблон для небольшого юнита, который работает по расписанию. Такая проверка представляет собой короткий скрипт, а не полноценный демон, поэтому для неё требуется Type=oneshot вместо значения по умолчанию. Обзор типов systemd service объясняет, почему выбор неверного типа приводит к тому, что юнит отчитывается об успехе, которого не было.

FAQ

Как проверить, синхронизировано ли время на VPS?

Запустите timedatectl и изучите строку System clock synchronized. Это флаг самого ядра, который устанавливается демоном, отвечающим за синхронизацию времени, поэтому наличие yes вместе с NTP service: n/a является нормальным и здоровым состоянием для системы с chrony. Чтобы узнать величину ошибки, запустите chronyc tracking и посмотрите на System time, либо запустите timedatectl timesync-status и посмотрите на Offset, если используется systemd-timesyncd. Для проверки по внешнему источнику сравните date -u с заголовком Date, который возвращает любой HTTPS-сайт.

Что использовать на VPS: chrony или systemd-timesyncd?

Используйте chrony для всех важных задач. systemd-timesyncd — это SNTP-клиент, который работает с одним сервером; он подходит для машин, которые постоянно находятся в сети и изначально имеют точное время. chrony опрашивает несколько источников, отбрасывает недостоверные, вычисляет погрешность хода часов и быстро восстанавливается после приостановки работы хоста или «живой» миграции. Установка chrony в Debian или Ubuntu автоматически удаляет systemd-timesyncd, так как оба пакета предоставляют time-daemon. Никогда не запускайте два демона времени одновременно.

Почему TOTP-коды не работают на одном сервере, но работают везде?

Потому что TOTP-код зависит от текущего времени. Код генерируется на основе счетчика, который меняется каждые 30 секунд, поэтому сервер и ваш телефон должны быть синхронизированы. Большинство систем проверки допускают отклонение на один шаг в любую сторону, что дает примерно полминуты запаса. Проверьте timedatectl на этом сервере. Если System clock synchronized показывает no, исправьте синхронизацию, и коды снова начнут подходить без изменения общего секретного ключа.

Можно ли настроить время внутри Docker-контейнера?

Нет, и в этом нет необходимости. Контейнер использует CLOCK_REALTIME хоста, так как пространства имен времени в Linux виртуализируют только монотонные часы и часы с момента загрузки. Непривилегированный контейнер получает date: cannot set date: Operation not permitted, а добавление CAP_SYS_TIME позволяет ему изменять время хоста, а не дает собственные часы. Синхронизируйте время на хосте. Разное местное время внутри контейнера — это вопрос настройки часового пояса, поэтому задайте TZ в переменных окружения контейнера.

Должен ли сервер использовать UTC или местное время?

UTC, а местное время следует применять только при выводе данных для пользователя. UTC не меняется при переходе на летнее время, поэтому ежедневные задачи выполняются один раз в сутки круглый год, а временные метки с разных серверов выстраиваются в хронологическом порядке без конвертации. Установите его с помощью sudo timedatectl set-timezone UTC. Если кому-то нужно увидеть местное время, можно добавить префикс к команде, например TZ=America/New_York date, что никак не повлияет на системные часы.