Como corrigir o relógio atrasado ou adiantado do VPS
Descubra por que o relógio do VPS deriva, interprete chronyc e timedatectl e corrija a sincronização NTP que causa falhas no login com 2FA.
Por que o relógio do seu VPS fica atrasado ou adiantado
O relógio de um VPS fica atrasado ou adiantado porque nada o está corrigindo. O kernel conta o tempo a partir de um contador de hardware que funciona um pouco mais depressa ou mais devagar. Sem um cliente de sincronização de tempo em execução, esse pequeno erro aumenta a cada hora. Numa máquina virtual, existe uma segunda causa: o guest partilha uma CPU física com outros guests. Durante os períodos em que não é escalonado, não consegue contar o tempo.
Num guest KVM atual, o contador raramente é o verdadeiro problema. A fonte kvm-clock paravirtualizada lê um valor mantido pelo host. Por isso, um guest em boas condições acompanha de perto o relógio do host. Relógios claramente incorretos costumam estar errados por um motivo mais simples. Não há nenhum daemon de sincronização em execução, há dois em execução e estão a entrar em conflito, ou a porta UDP de saída 123 nunca sai da rede do seu fornecedor. Um guest ajusta o próprio relógio a partir do host ou do NTP (protocolo de tempo da rede), e não do seu próprio oscilador.
O que um relógio incorreto realmente interrompe
- Os códigos TOTP (palavra-passe descartável baseada no tempo) deixam de corresponder, e você fica impedido de aceder a um servidor cuja palavra-passe e chave estão corretas.
- Um certificado emitido há um minuto é rejeitado, e
curlapresentaSSL certificate problem: certificate is not yet valid. apt updaterecusa um repositório comE: Release file for ... is not valid yet (invalid for another 1d 2h 3min 4s).- As tarefas agendadas são executadas no momento errado, e um salto do relógio pode fazer com que uma tarefa seja executada duas vezes enquanto outra é ignorada.
- Não é possível alinhar os logs de dois servidores, e a linha temporal de um incidente tem de ser reconstruída por estimativa.
A margem de tolerância é menor do que a maioria das pessoas espera. Os valores abaixo são predefinições documentadas, não medições de um teste.
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"
}
]Um código TOTP é calculado a partir de um contador que avança a cada 30 segundos, e a maioria dos verificadores aceita um intervalo de um passo para cada lado. Trinta segundos de erro em cada direção representam todo o limite disponível. O Kerberos é muito mais tolerante, com uma margem de desvio predefinida de 300 segundos. Um certificado não tem qualquer tolerância: é validado contra instantes fixos, com um período de tolerância de 0 segundos, pelo que um relógio atrasado um segundo rejeita um certificado perfeitamente válido.
Os três relógios e qual deles importa
O relógio do sistema é o que importa. É o CLOCK_REALTIME do kernel: a contagem de segundos desde 1 January 1970 UTC, mantida na memória e lida por tudo o que regista uma hora. As linhas de log, as verificações de certificados, os códigos TOTP e as horas de modificação dos ficheiros vêm dele. Quando alguém diz que a hora do servidor está errada, refere-se a este relógio.
O relógio de hardware, também chamado RTC (real time clock), é um contador separado que continua a funcionar enquanto a máquina está desligada. Numa máquina física, é um chip alimentado por bateria. Dentro de um guest, é emulado pelo hypervisor, pelo que é em grande parte um artefacto do host. O Linux lê-o uma vez durante o boot para obter um valor inicial e depois mantém a sua própria contagem. timedatectl apresenta-o na linha RTC time. Não faça troubleshooting a partir dessa linha num VPS, porque ela mostra a noção de hora do host, não o estado de sincronização do relógio do sistema. Num container, normalmente não existe /dev/rtc, pelo que hwclock --show falha com hwclock: Cannot access the Hardware Clock via any known method.
A clocksource é o mecanismo que o kernel usa para contar entre essas leituras. Consulte qual foi escolhida pelo kernel:
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
cat /sys/devices/system/clocksource/clocksource0/available_clocksourceNo KVM, normalmente verá kvm-clock. Este mecanismo lê um valor mantido pelo host. É por isso que um guest KVM sem qualquer cliente NTP continua aproximadamente certo durante algum tempo. tsc é o contador do próprio CPU. Os guests Xen indicam xen e os guests Hyper-V indicam uma source hyperv. Não altere esta definição sem uma razão comprovada, porque o kernel já escolhe a melhor source em que confia nesse hardware.
Alguns hosts também disponibilizam um dispositivo PTP (precision time protocol) ao guest. Isso permite que o chrony leia diretamente o relógio do host, em vez de o fazer através da rede. Vale a pena verificar, embora esta opção esteja frequentemente indisponível num VPS partilhado:
sudo modprobe ptp_kvm
ls /dev/ptp*
cat /sys/class/ptp/ptp0/clock_nameSe modprobe falhar ou não aparecer nenhum dispositivo, o host não o disponibiliza e o NTP de rede é a solução. Se clock_name indicar o relógio virtual KVM, o chrony pode utilizá-lo com uma linha refclock PHC /dev/ptp0 poll 2 na sua configuração.
Leia o estado da hora na sua própria máquina
Comece com um comando. Ele responde à pergunta "há algo a manter este relógio certo" numa única tela.
timedatectlLeia estas linhas em vez de confiar num número de que se lembra:
Local timeeUniversal timerepresentam o mesmo instante no seu fuso horário e em UTC. Se forem idênticos, a máquina já está em UTC.RTC timeé o relógio de hardware descrito acima. Numa VPS, ignore-o.Time zoneindica o que o sistema usa para formatar a hora local.System clock synchronizedé a própria flag do kernel. Um daemon de hora define-a quando passa a confiar nas suas fontes. Portanto,nosignifica que nenhum daemon sincronizou este relógio desde o boot.NTP serviceapresenta o estado especificamente do systemd-timesyncd.n/aé normal numa máquina que executa chrony, porque o timesyncd não está instalado nela.System clock synchronized: yesjuntamente comNTP service: n/asignifica que o chrony está a fazer o trabalho e que o kernel concorda com ele.
Em seguida, verifique quanto o relógio está adiantado ou atrasado. Não faça uma estimativa comparando-o com o telemóvel. Se o chrony estiver em execução:
chronyc tracking
chronyc sources -vchronyc tracking apresenta os números que respondem à pergunta. System time é o desvio atual em relação à hora NTP, seguido da palavra fast ou slow. Last offset é o tamanho da correção mais recente. Frequency é o erro de frequência que o chrony mediu no seu relógio e já está a compensar. Leap status deve apresentar Normal. Se apresentar Not synchronised e Reference ID for 00000000 (), o chrony ainda não escolheu uma fonte estável.
chronyc sources -v apresenta uma legenda acima da lista, para não ter de memorizar os símbolos. Duas colunas contêm a maior parte da informação. O caractere de estado no início de cada linha indica como o chrony avalia essa fonte. * identifica a fonte que está a ser usada atualmente, enquanto ? em todas as linhas significa que nenhuma fonte está a responder. Reach é o histórico das respostas dos últimos oito polls, apresentado em octal: 377 significa que as oito consultas tiveram resposta; 0 significa que nenhuma teve.
Se o systemd-timesyncd estiver a gerir a sincronização:
timedatectl timesync-status
timedatectl show-timesync --alltimesync-status apresenta o servidor com que está a comunicar, o intervalo entre polls e um valor Offset. Se o comando devolver um erro sobre o serviço em vez de apresentar o estado, o timesyncd não é o daemon responsável nesta máquina. Essa é, por si só, a resposta à sua pergunta.
Para uma verificação aproximada com o exterior e sem ferramentas adicionais, compare o seu relógio com um cabeçalho HTTP público Date, fornecido em GMT com resolução de um segundo:
date -u
curl -sI https://www.cloudflare.com | grep -i '^date:'Uma diferença de um ou dois segundos é normal e não significa nada. Uma diferença de um minuto é um problema no seu sistema.
chrony ou systemd-timesyncd numa VPS
Ubuntu e Debian incluem o systemd-timesyncd por predefinição. É um cliente SNTP (simple network time protocol): consulta um servidor de cada vez e ajusta gradualmente o relógio na direção desse servidor. Numa máquina que permanece online e começa com a hora aproximadamente correta, isso é suficiente e o custo de execução é praticamente nulo.
O chrony é uma implementação completa de NTP e constitui a melhor opção predefinida numa máquina virtual, por motivos que podem ser observados na própria saída do programa. Consulta várias fontes ao mesmo tempo e descarta as que apresentam valores divergentes. Mede o erro de frequência do relógio e grava-o num ficheiro de drift, corrigindo a tendência do relógio em vez de seguir cada amostra. Também recupera rapidamente das duas situações que uma VM pode enfrentar e uma máquina física não: pode ser pausada pelo host e pode ser movida para outro host enquanto está em execução. Quando é disponibilizado um dispositivo PTP do host, é o chrony que o lê.
sudo apt update && sudo apt install -y chrony
systemctl status chrony --no-pager
chronyc sources -v
chronyc trackingLeia a saída do apt enquanto o comando é executado. Em Debian e Ubuntu, os pacotes chrony e systemd-timesyncd fornecem ambos time-daemon, por isso o apt remove o timesyncd ao instalar o chrony. Esse comportamento é correto e pretendido. Nunca execute ambos, porque dois daemons a configurar o mesmo relógio entram em conflito e não é possível confiar no offset comunicado por nenhum deles enquanto isso acontece. No Rocky e no AlmaLinux, instale com sudo dnf install -y chrony, onde a unidade se chama chronyd em vez de chrony.
O ficheiro de configuração é /etc/chrony/chrony.conf no Debian e no Ubuntu, e /etc/chrony.conf no Rocky e no Alma. A configuração predefinida da distribuição já é adequada para uma VPS, por isso altere-a apenas quando houver um motivo. Vale a pena compreender duas diretivas:
- As linhas
pooleserveridentificam as fontes de tempo. Adicionariburstinstrui o chrony a enviar uma sequência rápida de pedidos no arranque, para que a primeira sincronização aconteça em segundos em vez de minutos. makestepdetermina quando o chrony salta o relógio em vez de o ajustar gradualmente. Consulte o valor configurado comgrep -n makestep /etc/chrony/chrony.conf. O valor predefinido no Debian e no Ubuntu,makestep 1 3, significa o seguinte: durante as três primeiras atualizações depois de o chronyd arrancar, avançar ou recuar o relógio se este estiver desfasado em mais de um segundo; depois disso, corrigir apenas por ajuste gradual.
Se quiser autenticar o tráfego de tempo contra adulterações no caminho, o chrony 4 e versões posteriores suportam NTS (network time security). Confirme primeiro a versão com chronyd -v e tenha em conta que o NTS também precisa da porta TCP de saída 4460 aberta, além da porta UDP 123:
server time.cloudflare.com iburst ntsReinicie e verifique o serviço antes de confiar nele. Uma configuração que não possa ser analisada deixa o sistema sem qualquer daemon de tempo, e o relógio não o informará desse problema.
sudo systemctl restart chrony
chronyc sources -v
chronyc trackingPor que um relógio com um desvio de vários minutos continua errado
Um daemon de tempo tem duas formas de corrigir um desvio. O ajuste gradual acelera ou abranda o relógio até eliminar o erro. Assim, o tempo continua sempre a avançar e nenhum timestamp é repetido ou ignorado. O ajuste direto salta imediatamente para o valor correto. É rápido, mas pode fazer o relógio recuar. Um recuo é perigoso para qualquer sistema que meça o tempo decorrido a partir do relógio de parede. Por isso, ambos os daemons preferem o ajuste gradual.
Essa preferência explica por que um relógio muito errado pode continuar incorreto durante muito tempo. O chrony só faz um ajuste direto dentro da janela makestep permitida. Por predefinição, essa janela corresponde às primeiras atualizações depois do arranque do daemon. Se um chronyd estiver em execução há uma semana e detetar um erro de quarenta segundos, fará um ajuste gradual. Corrigir quarenta segundos dessa forma demora muito mais do que seria desejável. Force a correção uma vez, de forma deliberada, num momento de pouca atividade:
sudo chronyc makestep
chronyc trackingchronyc tracking deve agora indicar um desvio System time próximo de zero, e Last offset deve mostrar a dimensão da correção efetuada. Pondere antes de executar isto num servidor de base de dados ativo, porque um relógio que recua pode confundir software que pressupõe que o tempo só avança. Reiniciar o daemon é uma versão mais suave da mesma correção, porque a janela makestep volta a abrir no arranque.
Os containers partilham o relógio do host
Um container não tem um relógio próprio, por isso não há nada para sincronizar no seu interior. Os namespaces de tempo do Linux virtualizam apenas os relógios monotónico e de tempo de arranque. CLOCK_REALTIME não é virtualizado, o que significa que um container lê o mesmo relógio do sistema que o host onde é executado. Corrija o relógio no host e todos os containers desse host serão corrigidos no mesmo momento.
Isto tem algumas consequências. Não instale chrony ou ntpd numa imagem, porque, na melhor das hipóteses, isso não faz nada. Definir a data dentro de um container sem privilégios falha com date: cannot set date: Operation not permitted, porque o kernel exige CAP_SYS_TIME para essa chamada. Conceder CAP_SYS_TIME não dá ao container um relógio privado. Dá-lhe a capacidade de alterar o relógio do host e, por isso, também o relógio de todos os outros containers.
Um fuso horário diferente dentro de um container não é um problema do relógio. Uma imagem que contenha o seu próprio /etc/localtime apresenta o mesmo instante formatado para outro fuso, pelo que date parece errado enquanto o relógio está correto. Defina TZ=UTC no ambiente do container para eliminar a confusão. O runtime escolhido não altera nada neste caso, e a comparação entre Podman e Docker rootless explica o que ele altera.
Fusos horários: UTC no servidor, hora local para as pessoas
Configure a máquina para UTC e mantenha-a assim.
timedatectl list-timezones | grep -i utc
sudo timedatectl set-timezone UTC
timedatectlO UTC não tem horário de verão, e esse é o argumento principal. Uma tarefa diária às 02:30 num fuso que observa o horário de verão é executada duas vezes no dia em que os relógios atrasam, e não é executada no dia em que avançam. man 8 cron documenta o tratamento especial para mudanças inferiores a três horas: as tarefas ignoradas por um avanço são executadas pouco depois da mudança, e as tarefas apanhadas dentro de uma hora repetida por um recuo não são executadas uma segunda vez. Esse comportamento é razoável, mas não deve ser necessário analisá-lo às 03:00. Com UTC, a tarefa é executada uma vez por dia, todos os dias do ano. Se uma tarefa sua não for executada de todo, em vez de ser executada a uma hora inesperada, as razões pelas quais uma tarefa cron nunca é executada silenciosamente são a explicação mais provável.
O mesmo argumento aplica-se à leitura de logs. journalctl formata os timestamps no fuso horário do sistema, e journalctl --utc força o UTC. Dois servidores em dois fusos transformam cada incidente num exercício de conversão, e as conversões feitas sob pressão levam a interpretações erradas da cronologia. Mantenha os sistemas em UTC, armazene os timestamps em UTC e converta-os uma vez, no momento em que uma pessoa os consulta. Quem quiser consultar a hora local num comando pode fazê-lo sem alterar a máquina:
TZ=Europe/Berlin dateMais uma linha no output de timedatectl pertence a esta secção. RTC in local TZ deve apresentar no. Defini-la como yes é uma solução alternativa para arrancar Windows e Linux em dual boot num portátil. Num servidor, apenas acrescenta um desfasamento que poderá causar problemas mais tarde. Quando está definida, timedatectl apresenta um aviso de que o sistema está configurado para ler a hora do RTC no fuso horário local.
Diagnóstico por sintoma
O código de autenticação de dois fatores é recusado num servidor. Verifique o relógio antes de qualquer outra coisa. O código é gerado a partir de um contador que avança a cada 30 segundos. Por isso, um servidor atrasado 90 segundos calcula um código correspondente a um intervalo que o seu telefone já ultrapassou. timedatectl mostrará System clock synchronized: no, ou chronyc tracking indicará um desvio System time elevado. Esta falha é diferente de uma chave rejeitada diretamente, que apresenta a sua própria mensagem e é abordada no guia sobre falhas de autenticação com publickey.
apt update indica que um ficheiro Release ainda não é válido. A mensagem completa identifica o repositório e durante quanto tempo ele permanecerá inválido, por exemplo, is not valid yet (invalid for another 1d 2h 3min 4s). O relógio está atrasado em relação à data contida no ficheiro Release do repositório. Essa duração mede diretamente o atraso. Corrija o relógio. Não desative a verificação de data do apt para ultrapassar o erro, porque essa verificação impede que alguém lhe forneça um índice de pacotes desatualizado.
Todas as linhas de origem mostram o estado inacessível e Reach é 0. Não há nenhuma resposta. Por isso, verifique o tráfego de saída em vez da configuração. O NTP usa UDP na porta 123 para tráfego de saída, e algumas redes filtram ou redirecionam esse tráfego. sudo chronyc ntpdata apresenta contadores por origem, incluindo Total TX e Total RX. Um contador TX que aumenta enquanto RX permanece em zero significa que os pacotes saem, mas nenhuma resposta regressa. Isto aponta para uma firewall entre o sistema e a origem.
O relógio estava correto e depois saltou. Eventos no host podem causar isto. Um snapshot restaurado, um guest pausado ou uma migração em tempo real para outro host pode deixar a noção de tempo do guest atrasada em relação à hora real. O chrony deteta a diferença na sondagem seguinte e corrige-a. O systemd-timesyncd pode primeiro aguardar um intervalo de sondagem longo. Confirme que o daemon arranca no boot com systemctl is-enabled chrony, porque um daemon iniciado manualmente deixa de estar ativo depois do reboot seguinte.
O desvio é pequeno, mas nunca estabiliza. Verifique o CPU steal. Um guest que não é agendado quando a sua interrupção de temporizador deveria ocorrer recebe as amostras com atraso. Por isso, o desvio varia em vez de convergir. top mostra isto como o valor st na linha da CPU. Como interpretar o CPU steal time num host partilhado explica o significado desse valor e as medidas possíveis.
Um certificado que acabou de emitir é rejeitado como ainda não válido. curl apresenta SSL certificate problem: certificate is not yet valid, e os browsers mostram algo semelhante. O certificado está correto. O relógio que o valida está atrasado. Qualquer uma das máquinas pode ser responsável, por isso verifique o cliente e o servidor. Se o servidor que emitiu o certificado for o que tem o relógio incorreto, o guia de certificados do certbot e do nginx aborda a renovação na mesma configuração.
Adicione-o às verificações que já executa
A sincronização da hora é uma configuração aplicada no arranque que pode falhar silenciosamente meses mais tarde. É exatamente o tipo de problema que uma rotina deteta, mas que a memória não retém. timedatectl e chronyc tracking levam dois segundos a consultar em conjunto. Execute-os como parte dos primeiros dez minutos num novo VPS e novamente ao seguir a lista de verificação regular de manutenção de servidores Linux. Se preferir que a verificação seja executada automaticamente e emita um alerta quando o desvio aumentar, escrever um serviço e um timer do systemd apresenta o padrão para uma unidade pequena que gera relatórios segundo um calendário.
FAQ
Como verifico se o relógio do meu VPS está sincronizado?
Execute timedatectl e leia a linha System clock synchronized. Essa é a própria flag do kernel, definida pelo daemon que está a sincronizar o relógio. Por isso, yes juntamente com NTP service: n/a é normal e indica um estado saudável numa máquina com chrony. Para saber o tamanho do erro, execute chronyc tracking e leia System time. Em alternativa, execute timedatectl timesync-status e leia Offset se o systemd-timesyncd estiver a gerir a sincronização. Para comparar com algo externo à máquina, compare date -u com o cabeçalho Date devolvido por qualquer site HTTPS.
Devo usar chrony ou systemd-timesyncd num VPS?
Use chrony em qualquer sistema importante. O systemd-timesyncd é um cliente SNTP que segue um único servidor. É adequado para uma máquina que permanece online e começa com a hora quase correta. O chrony consulta várias fontes, rejeita as que divergem, aprende o erro de frequência do relógio e recupera rapidamente depois de uma pausa do host ou de uma migração a quente. A instalação do chrony em Debian ou Ubuntu remove automaticamente o systemd-timesyncd, porque ambos os pacotes fornecem time-daemon. Nunca execute dois daemons de sincronização de hora ao mesmo tempo.
Por que os meus códigos TOTP falham num servidor, mas funcionam em todo o lado?
Porque um código TOTP é uma função da hora atual. O código é obtido a partir de um contador que avança a cada 30 segundos. Por isso, o servidor e o telefone têm de concordar sobre o intervalo atual. A maioria dos verificadores aceita o intervalo imediatamente anterior ou seguinte. Isso proporciona uma margem de aproximadamente meio minuto em cada direção. Verifique timedatectl nesse servidor. Se System clock synchronized ler no, corrija a sincronização. Os códigos voltarão a coincidir sem alterar o segredo partilhado.
Posso definir a hora dentro de um contentor Docker?
Não, e não precisa de o fazer. Um contentor partilha o CLOCK_REALTIME do host, porque os namespaces de tempo do Linux virtualizam apenas os relógios monotónico e de tempo de arranque. Um contentor sem privilégios recebe date: cannot set date: Operation not permitted. Adicionar CAP_SYS_TIME permite-lhe alterar o relógio do host, em vez de lhe atribuir um relógio próprio. Sincronize o host. Uma hora local diferente dentro de um contentor é uma definição de fuso horário. Por isso, defina TZ no ambiente do contentor.
Um servidor deve usar UTC ou a hora local?
UTC, aplicando a hora local no momento em que uma pessoa lê o resultado. A hora UTC nunca muda devido ao horário de verão. Assim, uma tarefa diária é executada uma vez por dia durante todo o ano, e os timestamps de servidores diferentes ficam alinhados sem conversão. Defina-a com sudo timedatectl set-timezone UTC. Quem precisar de ver a hora local pode acrescentar um prefixo a um único comando, por exemplo TZ=America/New_York date. Isso não altera o relógio do sistema.