Dia 26: Logs Centralizados no Linux — rsyslog, journald, Loki e ELK

Num servidor isolado, procurar um erro no /var/log/syslog funciona. Mas quando se gerem cinco, dez ou cinquenta máquinas — físicas, VMs ou containers — essa abordagem deixa de ser viável. Logs centralizados resolvem o problema: todos os eventos de todas as máquinas convergem para um único ponto, onde se pode pesquisar, alertar e correlacionar. Este artigo cobre as quatro peças que qualquer administrador Linux encontra neste percurso: journald (o logger nativo do systemd), rsyslog (o daemon tradicional ainda omnipresente), Grafana Loki (a abordagem moderna leve) e o ELK Stack (a solução completa da Elastic).

Nota: Este artigo assume conhecimento básico de systemd (Dia 7) e Docker (Dia 21). O Dia 25 cobriu monitoring com Prometheus e Grafana — Loki é a peça de logs que complementa essa stack.

Neste artigo

O que são logs centralizados e porquê

Logs centralizados significam enviar os registos de eventos de múltiplas máquinas para um servidor único — ou cluster — que os armazena, indexa e disponibiliza para pesquisa. Em vez de fazer SSH a cada máquina para ler /var/log/messages, o administrador abre um painel web e filtra por hostname, severidade ou texto.

As três razões principais para centralizar logs:

  • Correlação de incidentes — quando um serviço falha, o causa raiz pode estar noutra máquina (ex.: a base de dados caiu porque o disco encheu no servidor de backups);
  • Persistência após compromissão — um atacante com acesso root pode apagar logs locais, mas não os que já saíram da máquina;
  • Compliance e auditoria — PCI-DSS, ISO 27001 e NIS2 exigem retenção e centralização de logs de segurança.

No ecossistema Linux existem duas camadas: o logger local (journald e/ou rsyslog, que corre em cada máquina) e o backend central (rsyslog em modo servidor, Loki, ou Elasticsearch). O fluxo é sempre: aplicação → logger local → rede → backend central → interface de pesquisa.

journald — o logger nativo do systemd

O systemd-journald é o daemon de logging que corre por omissão em praticamente todas as distribuições Linux modernas (Ubuntu, Debian, RHEL, Rocky, Alma, Fedora, Arch). Recebe logs de todos os serviços geridos pelo systemd, do kernel e de aplicações via syslog. Guarda-os num formato binário indexado em /var/log/journal/ (ou em memória se esse directório não existir).

A ferramenta de leitura é o journalctl. As operações mais comuns para administrar logs locais antes de os centralizar:

# Ver todos os logs desde o último boot
journalctl -b

# Logs de um serviço específico
journalctl -u nginx.service

# Logs de hoje, com prioridade ERROR ou superior
journalctl --since today -p err

# Seguir logs em tempo real (equivalente a tail -f)
journalctl -f

# Logs entre duas datas
journalctl --since "2026-08-01" --until "2026-08-04 12:00:00"

# Ver quanto espaço o journal ocupa
journalctl --disk-usage

# Limitar o journal a 500 MB persistentes
journalctl --vacuum-size=500M

# Apagar logs com mais de 7 dias
journalctl --vacuum-time=7d

Os parâmetros principais: -b filtra apenas o boot actual; -u selecciona uma unidade systemd; -p define a prioridade mínima (emerge, alert, crit, err, warning, notice, info, debug); --vacuum-size e --vacuum-time controlam a retenção. A documentação completa está em man7.org — journalctl(1).

Para configurar a retenção permanente, cria-se ou edita-se o ficheiro /etc/systemd/journald.conf:

# /etc/systemd/journald.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=30day
ForwardToSyslog=yes

Storage=persistent garante que os logs sobrevivem a reboots (escreve em /var/log/journal/). ForwardToSyslog=yes permite que o rsyslog também receba uma cópia — fundamental para integrar journald com uma solução de centralização baseada em syslog. Depois de alterar, reiniciar o daemon com systemctl restart systemd-journald.

rsyslog — o daemon tradicional

O rsyslog é o sucessor do syslog tradicional e ainda o daemon de logging mais usado em servidores Linux. Suporta TCP e UDP, TLS, filas em disco e módulos de saída para Elasticsearch, Kafka e ficheiros. Mesmo sistemas que usam journald por omissão mantêm frequentemente o rsyslog a correr para encaminhar logs para ficheiros tradicionais em /var/log/.

Instalar o rsyslog (se não estiver presente):

# Debian/Ubuntu
sudo apt install rsyslog

# RHEL/Rocky/Alma
sudo dnf install rsyslog

A configuração principal fica em /etc/rsyslog.conf e os ficheiros adicionais em /etc/rsyslog.d/. A sintaxe base segue o formato facility.priority action. Por exemplo, authpriv.* /var/log/secure envia todas as mensagens de autenticação privilegiada para esse ficheiro. A documentação oficial está em rsyslog.com/doc.

Configurar rsyslog como cliente remoto

Enviar logs de uma máquina cliente para um servidor central é a forma mais simples de centralização. Adiciona-se uma linha ao rsyslog do cliente que encaminha todas as mensagens para o IP do servidor. A comparação entre TCP e UDP é directa: UDP é mais rápido mas não garante entrega; TCP é fiável e é o recomendado para logs críticos.

# /etc/rsyslog.d/50-remote.conf
# Enviar todos os logs via TCP (porta 514) para o servidor central
*.* @@192.168.1.100:514

# Alternativa: via UDP (um @ em vez de dois)
# *.* @192.168.1.100:514

# Enviar apenas auth e authpriv (registos de segurança)
# authpriv.*;auth.* @@192.168.1.100:514

A convenção de prefixos: @ (um) = UDP; @@ (dois) = TCP. *.* significa todas as facilities e todas as prioridades. Depois de editar, reiniciar e verificar:

sudo systemctl restart rsyslog
sudo systemctl enable rsyslog

# Testar: gerar uma mensagem de log
logger -t teste "Mensagem de teste do cliente rsyslog"

# Verificar se chegou ao servidor (executar no servidor)
journalctl -t teste --since "1 min ago"
# ou
grep "Mensagem de teste" /var/log/syslog
Atenção: O tráfego rsyslog por TCP/UDP simples é não encriptado — qualquer sniffing na rede revela o conteúdo dos registos. Para produção, usar TLS (ver secção de erros comuns).

Configurar rsyslog como servidor central

No lado do servidor, o rsyslog precisa de: (1) abrir os módulos de recepção de rede, (2) criar directórios separados por hostname para organizar os logs de cada cliente, (3) garantir que a firewall permite tráfego na porta 514.

# /etc/rsyslog.conf — descomentar ou adicionar os módulos de rede

# Receção via UDP (porta 514)
module(load="imudp")
input(type="imudp" port="514")

# Receção via TCP (porta 514)
module(load="imtcp")
input(type="imtcp" port="514")

# Organizar logs por hostname remoto
$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%$YEAR%-%$MONTH%-%$DAY%.log"
*.* ?RemoteLogs

# Parar o processamento depois de escrever no ficheiro remoto
& stop

A directiva $template define um padrão de caminho que inclui o hostname da máquina origem — assim cada cliente tem o seu próprio directório. O & stop impede que os logs remotos sejam também escritos nos ficheiros locais (evita duplicação). Criar o directório e abrir a firewall:

sudo mkdir -p /var/log/remote
sudo chown syslog:adm /var/log/remote    # Debian/Ubuntu
# ou
sudo chown root:root /var/log/remote       # RHEL/Rocky

sudo systemctl restart rsyslog

# Abrir firewall — firewalld (RHEL/Rocky)
sudo firewall-cmd --permanent --add-port=514/tcp
sudo firewall-cmd --permanent --add-port=514/udp
sudo firewall-cmd --reload

# Abrir firewall — UFW (Ubuntu/Debian)
sudo ufw allow 514/tcp
sudo ufw allow 514/udp

A partir deste momento, cada cliente configurado na secção anterior envia os seus logs para o servidor, que os organiza em /var/log/remote/<hostname>/. Esta abordagem é suficiente para infraestruturas pequenas (até ~20 máquinas). Para volumes maiores ou necessidade de pesquisa full-text, passa-se para Loki ou ELK.

Grafana Loki — logs modernos e leves

O Grafana Loki é um sistema de agregação de logs inspirado no Prometheus. A diferença fundamental face ao ELK: Loki não indexa o conteúdo dos logs — indexa apenas metadata (labels como hostname, aplicação, ambiente). O texto completo fica comprimido em blocos. Isto reduz drasticamente o consumo de RAM e disco, tornando-o adequado para PMEs que não têm recursos para manter um cluster Elasticsearch.

A forma mais rápida de colocar Loki a correr é via Docker Compose, combinando três componentes: Loki (backend), Promtail (agente que lê logs locais e envia para Loki) e Grafana (interface web). O fluxo é análogo a Prometheus+Grafana para métricas, mas para logs.

# docker-compose.yml — stack Loki + Promtail + Grafana
version: "3.8"

services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - loki-data:/loki
    restart: unless-stopped

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - ./promtail-config.yml:/etc/promtail/config.yml
    command: -config.file=/etc/promtail/config.yml
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-data:/var/lib/grafana
    restart: unless-stopped

volumes:
  loki-data:
  grafana-data:

O Promtail precisa de um ficheiro de configuração que define quais logs ler e que labels associar:

# promtail-config.yml
server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: syslog
    static_configs:
      - targets:
          - localhost
        labels:
          job: syslog
          host: servidor-central
          __path__: /var/log/syslog

  - job_name: journal
    journal:
      labels:
        job: systemd-journal
        host: servidor-central
    relabel_configs:
      - source_labels: ["__journal__systemd_unit"]
        target_label: unit

As labels job e host são o que Loki indexa — são elas que se usam para filtrar na query. O __path__ define que ficheiros o Promtail lê. Para máquinas remotas, instala-se o Promtail em cada cliente apontando para o IP do servidor Loki. Iniciar a stack:

docker compose up -d

# Verificar se o Loki responde
curl http://localhost:3100/ready

# Aceder ao Grafana: http://localhost:3000
# Login: admin / admin
# Adicionar data source: Loki (URL: http://loki:3100)

Depois de adicionar Loki como data source no Grafana, pode-se pesquisar logs com LogQL — uma linguagem semelhante ao PromQL do Prometheus. Exemplo: {job="syslog"} |= "error" filtra todos os logs do job syslog que contêm “error”. A documentação completa está em grafana.com/docs/loki.

ELK Stack — Elasticsearch, Logstash e Kibana

O ELK Stack (ou Elastic Stack) é a solução mais completa de logs centralizados. Elasticsearch é o motor de pesquisa e armazenamento (indexa texto completo, suporta pesquisa difusa e aggregações). Logstash é o pipeline de ingestão (recebe, filtra, transforma e encaminha). Kibana é a interface web de visualização e dashboards.

A diferença face ao Loki é significativa: o ELK indexa cada campo de cada log, o que oferece pesquisas muito mais ricas mas consponde consideravelmente mais recursos (RAM e disco). Para ambientes com milhares de eventos/segundo, um cluster Elasticsearch precisa tipicamente de 16+ GB de RAM dedicados à JVM heap. A documentação está em elastic.co — Elasticsearch e elastic.co — Kibana.

Uma stack ELK mínima via Docker Compose:

# docker-compose.yml — ELK Stack mínimo
version: "3.8"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data
    restart: unless-stopped

  logstash:
    image: docker.elastic.co/logstash/logstash:8.15.0
    ports:
      - "5044:5044"
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    depends_on:
      - elasticsearch
    restart: unless-stopped

  kibana:
    image: docker.elastic.co/kibana/kibana:8.15.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
    restart: unless-stopped

volumes:
  es-data:

O Logstash precisa de um pipeline que define como receber e processar os logs. Para receber syslog de clientes rsyslog e enviar para Elasticsearch:

# logstash.conf
input {
  syslog {
    port => 5044
  }
}

filter {
  # Adicionar campo geoip para IPs públicos (opcional)
  geoip {
    source => "host"
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "syslog-%{+YYYY.MM.dd}"
  }
}

O input syslog escuta na porta 5044 e faz parse automático do formato syslog. O output cria um índice diário em Elasticsearch (syslog-YYYY.MM.dd) — esta rotação por data facilita a retenção e expurgo. Iniciar e verificar:

docker compose up -d

# Verificar Elasticsearch
curl http://localhost:9200

# Verificar Kibana: http://localhost:5601
# Criar index pattern: syslog-* no menu Stack Management

# No cliente rsyslog, apontar para o Logstash:
# *.* @@IP_DO_SERVIDOR:5044

Após criar o index pattern no Kibana, os logs ficam disponíveis no menu Discover, onde se pode pesquisar por texto livre, filtrar por campos estruturados e criar dashboards. Para clientes sem rsyslog, a Elastic oferece o Filebeat — um agente leve que lê ficheiros de log e envia directamente para Elasticsearch ou Logstash.

Comparação das soluções

A escolha depende do volume de logs, recursos disponíveis e complexidade da infraestrutura. A tabela seguinte resume as quatro opções cobertas:

Solução RAM mínima Pesquisa Complexidade Ideal para
rsyslog central 128 MB grep / journalctl Baixa 1-20 máquinas, sem pesquisa full-text
Grafana Loki 512 MB LogQL (labels + texto) Média 20-200 máquinas, integração com Grafana
ELK Stack 4 GB+ (JVM) Full-text + agregações Alta 100+ máquinas, compliance, dashboards ricos
journald (local) 0 (nativo) journalctl (local) Nenhuma Single server, sem centralização

Para a maioria das PMEs que já usam Prometheus+Grafana (como vimos no Dia 25), Loki é a escolha natural — partilha a mesma interface, a mesma linguagem de query e os mesmos conceitos de labels. O ELK justifica-se quando há requisitos de compliance que exigem pesquisa full-text com retenção legal longa.

Erros comuns e soluções

Problema Causa Solução
Logs não chegam ao servidor central Firewall bloqueia porta 514; rsyslog usa UDP e há perda de pacotes Verificar com tcpdump -i any port 514 no servidor; mudar para TCP (@@)
journald perde logs após reboot Storage=auto (default) — apenas guarda em memória se /var/log/journal não existir Definir Storage=persistent em /etc/systemd/journald.conf e reiniciar
Loki: erro “too many outstanding requests” Rate limit excedido — Promtail envia logs demasiado rápido Ajustar ingestion_rate_mb e ingestion_burst_size_mb no config do Loki
Elasticsearch: cluster status red Shards não alocados — disco cheio ou JVM heap insuficiente Verificar curl localhost:9200/_cluster/health?pretty; aumentar -Xmx ou libertar disco
Tráfego de logs visível em texto limpo na rede rsyslog TCP/UDP sem encriptação Activar TLS com module(load="imtcp" StreamDriver="gtls" StreamDriver.Mode="1") e certificados
Kibana mostra “No data matches your search” Index pattern não criado ou time filter incorrecto Stack Management → Index Patterns → criar syslog-* com @timestamp

Checklist de verificação

Antes de considerar a stack de logs centralizados operacional, confirmar cada ponto:

  1. journald persistente em todas as máquinas: journalctl --disk-usage mostra espaço ocupado e /var/log/journal/ existe;
  2. rsyslog activo: systemctl status rsyslog mostra active (running) em cliente e servidor;
  3. Firewall aberta: ss -tlnp | grep 514 mostra rsyslog à escuta no servidor;
  4. Teste de fluxo end-to-end: executar logger -t teste "fluxo $(date)" no cliente e confirmar que aparece no servidor dentro de 5 segundos;
  5. Loki/ELK saudável: curl http://localhost:3100/ready (Loki) ou curl http://localhost:9200/_cluster/health?pretty (ELK) retornam status verde/amarelo;
  6. Retenção configurada: definir --vacuum-time no journald, logrotate no rsyslog, ou ILM policies no Elasticsearch — sem retenção, o disco enche;
  7. TLS em produção: se os logs contêm dados sensíveis (PII, credenciais), o tráfego entre cliente e servidor tem de ir encriptado;
  8. Alertas básicos: configurar pelo menos um alerta para “sem logs de um host há mais de 10 minutos” — silêncio total é tão grave como um erro explícito.

Artigos Relacionados