Correção de horario e implantação da geração de Romaneio

This commit is contained in:
2026-08-27 16:21:56 -03:00
parent a0aafe62fc
commit ad1a071e4b
51 changed files with 3450 additions and 46 deletions

135
deploy/ntp-seguro.sh Executable file
View File

@@ -0,0 +1,135 @@
#!/usr/bin/env bash
#
# Relógio do SERVIDOR sincronizado com NTP autenticado (NTS).
# Rodar UMA VEZ no servidor, como root: sudo bash deploy/ntp-seguro.sh
#
# ─── POR QUE NO HOST E NÃO NO CONTAINER ──────────────────────────────────────
# Container não tem relógio próprio: ele lê o clock do kernel do host. Rodar
# chrony/ntpd dentro do container exigiria CAP_SYS_TIME e mudaria a hora do
# SERVIDOR INTEIRO a partir de dentro de um processo da aplicação — por isso
# não se faz. Dentro do container a gente fixa só o FUSO (TZ, no Dockerfile);
# a HORA vem daqui.
#
# ─── POR QUE NTS E NÃO NTP COMUM ─────────────────────────────────────────────
# NTP puro é UDP sem autenticação: qualquer um no caminho pode responder no
# lugar do servidor e empurrar a hora da máquina. Isso não é teórico para este
# sistema — hora errada muda o dia da consolidação, o recorte do período
# financeiro e a validade de sessão/cookie. NTS (RFC 8915) faz uma troca de
# chaves por TLS (porta TCP 4460) e assina os pacotes NTP, então uma resposta
# forjada é descartada. O `chronyc authdata` no fim mostra se está valendo.
#
# ─── REDE ────────────────────────────────────────────────────────────────────
# Precisa de saída para: UDP 123 (NTP) e TCP 4460 (NTS-KE).
# Se o firewall bloquear a 4460, o NTS não fecha e o chrony fica sem fonte.
set -euo pipefail
[ "$(id -u)" -eq 0 ] || { echo "ERRO: rode com sudo."; exit 1; }
command -v apt-get >/dev/null || { echo "ERRO: script escrito para Debian/Ubuntu."; exit 1; }
echo "==> Hora ANTES:"; date; echo
# ── 1. chrony ────────────────────────────────────────────────────────────────
# NTS só existe no chrony >= 4.0 (Debian 11+ / Ubuntu 22.04+ já têm).
if ! command -v chronyd >/dev/null; then
echo "==> Instalando chrony"
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y chrony
fi
versao="$(chronyd --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1)"
if [ "${versao%%.*}" -lt 4 ]; then
echo "ERRO: chrony $versao não fala NTS (precisa >= 4.0). Atualize o sistema."
exit 1
fi
echo "==> chrony $versao (NTS disponível)"
# ── 2. Fontes NTS ────────────────────────────────────────────────────────────
# Três fontes independentes de propósito: com uma só, ela cai e o relógio fica
# à deriva sem ninguém notar; com três, o chrony ainda descarta a que divergir.
CONF_NTS="$(cat <<'CONF'
# Gerado por deploy/ntp-seguro.sh — fontes de tempo AUTENTICADAS (NTS).
# `iburst`: acerta rápido no boot, em vez de levar minutos.
server time.cloudflare.com iburst nts
server nts.netnod.se iburst nts
server ptbtime1.ptb.de iburst nts
# Cache das chaves NTS: sem isto, todo restart refaz a troca TLS e o relógio
# demora a fechar quando a internet ainda não subiu.
ntsdumpdir /var/lib/chrony
# Sincroniza também o relógio de hardware (RTC), que é de onde a máquina lê a
# hora ao ligar — é o que evita voltar errado depois de um reboot/queda de luz.
rtcsync
# makestep: corrige de uma vez (em vez de "escorregar" devagar) quando o erro
# é grande, mas só nas 3 primeiras medições. É a linha certa para servidor
# físico. SE ESTE SERVIDOR FOR VM QUE HIBERNA/PAUSA e a hora só aparece errada
# depois de uma pausa longa, troque pela linha comentada abaixo — ela permite
# o salto a qualquer momento (inclusive para trás, então saiba o que ganha):
makestep 1.0 3
# makestep 1.0 -1
CONF
)"
CHRONY_CONF=/etc/chrony/chrony.conf
[ -f "$CHRONY_CONF" ] || CHRONY_CONF=/etc/chrony.conf
cp -n "$CHRONY_CONF" "$CHRONY_CONF.bak-ntp-seguro" 2>/dev/null || true
# Onde escrever: o Debian/Ubuntu moderno lê o diretório conf.d. Se essa linha
# não existir na config, escrever lá seria IGNORADO EM SILÊNCIO — nesse caso a
# gente anexa no próprio chrony.conf, entre marcadores, para continuar sendo
# possível rodar o script de novo sem duplicar.
if grep -qE '^\s*confdir\s+.*conf\.d' "$CHRONY_CONF" 2>/dev/null; then
mkdir -p /etc/chrony/conf.d
printf '%s\n' "$CONF_NTS" > /etc/chrony/conf.d/nts-reem.conf
echo "==> Fontes NTS em /etc/chrony/conf.d/nts-reem.conf"
else
sed -i '/# >>> nts-reem >>>/,/# <<< nts-reem <<</d' "$CHRONY_CONF"
{ echo "# >>> nts-reem >>>"; printf '%s\n' "$CONF_NTS"; echo "# <<< nts-reem <<<"; } >> "$CHRONY_CONF"
echo "==> Fontes NTS anexadas em $CHRONY_CONF"
fi
# ── 3. Desligar as fontes NÃO autenticadas ───────────────────────────────────
# Deixar o `pool` padrão junto anularia o ganho: o chrony poderia se decidir
# por uma fonte sem assinatura. Só comentamos (o .bak fica ao lado).
sed -i -E 's/^([[:space:]]*(pool|server)[[:space:]]+.*)$/# [nts-reem] \1/' "$CHRONY_CONF"
sed -i -E '/# >>> nts-reem >>>/,/# <<< nts-reem <<</ s/^# \[nts-reem\] (.*)$/\1/' "$CHRONY_CONF"
for f in /etc/chrony/sources.d/*.sources; do
[ -e "$f" ] || continue
mv "$f" "$f.desativado-ntp-seguro"
done
# ── 4. Um serviço de hora só ─────────────────────────────────────────────────
# systemd-timesyncd e chrony brigam pelo relógio; o timesyncd não fala NTS.
systemctl disable --now systemd-timesyncd 2>/dev/null || true
systemctl enable --now chrony 2>/dev/null || systemctl enable --now chronyd
echo "==> Reiniciando chrony"
systemctl restart chrony 2>/dev/null || systemctl restart chronyd
sleep 5
chronyc makestep >/dev/null 2>&1 || true
# ── 5. Conferência ───────────────────────────────────────────────────────────
echo
echo "==> Fontes (o '^*' marca a que está valendo):"
chronyc -N sources -v || true
echo
echo "==> NTS (queremos 'KeyID/Type/KLen' preenchido e Cook > 0 nas 3 linhas):"
chronyc -N authdata || true
echo
echo "==> Estado:"; chronyc tracking || true
timedatectl || true
echo
echo "==> Hora DEPOIS:"; date
cat <<'FIM'
Pronto. O relógio agora se mantém sozinho, inclusive depois de reboot.
Se a hora tinha saltado, reinicie os containers para os processos longos
pegarem o clock corrigido: docker compose restart
Para conferir depois, a qualquer momento:
chronyc tracking # 'System time' deve ficar em milissegundos
chronyc -N authdata # NTS ativo em cada fonte
FIM