← Voltar para o Blog

Relógio errado no servidor: NTP, fuso e o que quebra

Certificado que "venceu" sem ter vencido, token recusado, log fora de ordem e backup no horário errado. Todos têm a mesma causa, e ela não aparece em nenhum log de erro.

Equipe EasyOps Cloud · · 7 min de leitura

O certificado TLS foi emitido ontem e o navegador diz que ele ainda não é válido. O token de autenticação é recusado assim que gerado. O log da aplicação mostra eventos fora de ordem. O backup marcado para as 2h roda às 23h.

São quatro sintomas distintos com a mesma causa: o relógio do servidor está errado. E é um problema especialmente ingrato porque nada registra "a hora está errada" — cada sistema apenas reporta a consequência, e a consequência parece um bug de outra coisa.

Descobrir o estado atual

timedatectl

A saída responde tudo de uma vez: hora local, hora UTC, fuso configurado, e — a linha mais importante — se a sincronização está ativa.

               Local time: Mon 2026-08-10 14:32:11 -03
           Universal time: Mon 2026-08-10 17:32:11 UTC
                Time zone: America/Sao_Paulo (-03, -0300)
System clock synchronized: yes
              NTP service: active

System clock synchronized: no ou NTP service: inactive significam que o relógio está à deriva. Compare com uma referência externa para saber o tamanho do desvio:

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

Poucos segundos de diferença são normais. Minutos indicam que a sincronização não está funcionando há um tempo.

Por que o relógio sai do lugar

Todo relógio de computador tem deriva — o oscilador não é perfeito e acumula erro de alguns segundos por dia. Em máquina virtual isso é pior, porque a VM não tem acesso direto ao relógio físico e depende do hospedeiro.

Três situações aceleram o problema:

  • Máquina restaurada de snapshot. Ela volta com a hora do momento da captura, e pode estar horas ou dias atrasada.
  • VM pausada e retomada. O tempo passou lá fora e não passou lá dentro.
  • Sincronização desligada por alguém que "não achou necessário", ou bloqueada por firewall de saída.

Esse último merece atenção. Se você aplicou regra de saída restritiva, como sugerido no artigo sobre firewall, o NTP usa UDP na porta 123 — bloqueá-lo faz o relógio derivar em silêncio por semanas até alguém notar pelo sintoma errado.

Configurar a sincronização

A maioria das distribuições modernas já traz o systemd-timesyncd, que é suficiente para servidor comum:

sudo systemctl enable --now systemd-timesyncd
timedatectl show-timesync --all | head

Para escolher servidores mais próximos, o que reduz o erro:

# /etc/systemd/timesyncd.conf
[Time]
NTP=a.st1.ntp.br b.st1.ntp.br
FallbackNTP=pool.ntp.org
sudo systemctl restart systemd-timesyncd

Os servidores do NTP.br são mantidos pelo NIC.br e são a referência oficial de hora legal brasileira — para servidor no Brasil, entregam menor latência e melhor precisão que o pool global.

Quando a precisão importa mais — sistema financeiro, correlação fina de log entre máquinas, cluster de banco —, o chrony é superior: converge mais rápido, lida melhor com rede instável e corrige a deriva do oscilador em vez de só ajustar a hora:

sudo apt install chrony
# /etc/chrony/chrony.conf
server a.st1.ntp.br iburst
server b.st1.ntp.br iburst
pool pool.ntp.org iburst maxsources 3
makestep 1.0 3
sudo systemctl enable --now chrony
chronyc tracking
chronyc sources -v

O makestep 1.0 3 permite um salto abrupto nas três primeiras atualizações, se o desvio for maior que 1 segundo. Isso resolve o caso da máquina restaurada de snapshot, que precisa corrigir horas de uma vez em vez de convergir lentamente.

Os dois serviços conflitam. Rode um ou outro:

sudo systemctl disable --now systemd-timesyncd

Fuso horário: UTC ou local?

A recomendação padrão para servidor é manter o sistema em UTC. Os motivos são concretos:

  • Não há horário de verão. Mudanças de política de fuso — que acontecem, e aconteceram no Brasil — não afetam nada.
  • Correlação entre máquinas fica trivial quando todas registram no mesmo referencial.
  • Serviços externos e bibliotecas assumem UTC por padrão.
sudo timedatectl set-timezone UTC

O contra-argumento legítimo é operacional: ler log em UTC exige conversão mental, e às três da manhã ninguém quer fazer conta. Para servidor de aplicação com equipe brasileira, America/Sao_Paulo é uma escolha defensável desde que consistente entre todas as máquinas.

sudo timedatectl set-timezone America/Sao_Paulo
timedatectl list-timezones | grep Sao_Paulo

O que não funciona é misturar: uma máquina em UTC, outra em horário local, e o banco em um terceiro. Aí a correlação de eventos vira adivinhação.

Independentemente da escolha, armazene sempre em UTC no banco. Coluna com fuso (timestamptz no Postgres) e conversão apenas na exibição é a única abordagem que sobrevive a mudança de política e a usuário em outro país.

Onde o cron mora nessa história

Tarefa agendada usa o fuso do sistema. Uma entrada marcada para 0 3 * * * em máquina UTC roda à meia-noite em Brasília — o que pode ser exatamente o que você não queria para um fechamento contábil.

Vale conferir antes de assumir:

timedatectl | grep 'Time zone'
systemctl list-timers --all

Com timers do systemd, é possível declarar o fuso na própria unit, sem alterar o sistema inteiro:

[Timer]
OnCalendar=Mon..Fri 03:00
Timezone=America/Sao_Paulo

Essa é uma vantagem real sobre o cron, que não tem esse recurso — assunto tratado no artigo sobre por que o cron não roda.

O que quebra quando a hora está errada

Vale conhecer a lista, porque reconhecer o padrão economiza horas:

  • TLS. Certificado tem data de início e de fim. Relógio adiantado faz um certificado válido parecer vencido; atrasado faz um recém-emitido parecer ainda não válido. É a causa de boa parte dos casos em que a renovação de SSL "não funcionou".
  • Tokens. JWT e assinaturas de API têm janela de validade curta, às vezes de poucos minutos. Alguns segundos de desvio já causam recusa.
  • Autenticação de dois fatores. O código TOTP é derivado do horário. Desvio acima de 30 segundos invalida todos os códigos.
  • Backup e retenção. Política de "manter 7 dias" com relógio errado apaga o que não devia.
  • Log. Eventos fora de ordem tornam a investigação de incidente inviável.
  • Replicação de banco. Vários mecanismos dependem de ordenação temporal consistente.

O check de rotina

Depois de configurar, confirme e siga em frente:

timedatectl
chronyc tracking | grep -E 'System time|Last offset'

System time mostra o desvio atual em relação à referência. Abaixo de alguns milissegundos é excelente; abaixo de um segundo é suficiente para praticamente tudo.

Vale incluir o desvio no que você acompanha. É uma daquelas métricas que ficam irrelevantes por meses e, no dia em que saem do lugar, explicam quatro incidentes aparentemente independentes de uma vez.

Servidor que pula no tempo

Existe uma diferença entre corrigir o relógio devagar e corrigi-lo de uma vez, e ela importa mais do que parece.

O ajuste gradual — chamado de *slew* — acelera ou desacelera levemente o relógio até alcançar a hora certa. Leva mais tempo e tem uma propriedade valiosa: o tempo nunca anda para trás.

O salto corrige na hora e pode fazer o relógio retroceder. Um relógio que anda para trás quebra premissas em vários lugares: registro de log fora de ordem, cálculo de duração que dá negativo, cache que expira antes da hora, e agendamento que executa duas vezes.

Por isso o padrão dos serviços de sincronização é usar salto apenas na partida, quando o desvio inicial pode ser grande, e ajuste gradual dali em diante. É exatamente o que a diretiva makestep 1.0 3 do chrony expressa: salto nas três primeiras correções, gradual depois.

O caso em que isso morde é a máquina restaurada de snapshot ou retomada após pausa longa. Ela volta com desvio de horas, e a correção — necessária — vai fazer o tempo saltar. Vale reiniciar os serviços sensíveis depois de uma restauração, em vez de supor que tudo se ajustou sozinho.

Consistência entre máquinas importa mais que precisão absoluta

Para a maior parte das operações, estar 200 ms atrás da hora legal não causa problema nenhum. O que causa problema é uma máquina estar 200 ms atrás e a outra 400 ms à frente.

Correlacionar log de duas máquinas com relógios divergentes leva a conclusões erradas sobre causa e efeito — o evento que aparece primeiro no relatório pode ter acontecido depois na realidade.

Por isso a recomendação prática é usar as mesmas fontes de tempo em todas as máquinas do ambiente. Elas derivam juntas, na mesma direção, e continuam consistentes entre si mesmo que se afastem um pouco da referência global.

Em container, a hora vem do host

Um detalhe que evita investigação inútil: container não tem relógio próprio. Ele compartilha o do sistema hospedeiro, e não há como sincronizar por dentro — tentar rodar um cliente NTP dentro do container falha por falta de permissão, e é uma tentativa comum.

A consequência prática é que corrigir a hora do host corrige todos os containers de uma vez. E que um container com hora errada é sempre um sintoma de host com hora errada.

O fuso, por outro lado, é independente. A maioria das imagens base vem em UTC, mesmo que o host esteja em horário local:

services:
  api:
    environment:
      TZ: America/Sao_Paulo

Isso explica o caso em que o log da aplicação sai três horas adiantado em relação ao log do sistema, na mesma máquina — e é resolvido declarando o fuso, não mexendo em sincronização.

Suba um servidor em minutos

Preço em real, suporte em português e dados no Brasil.

Criar conta