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).
Neste artigo
- O que são logs centralizados e porquê
- journald — o logger nativo do systemd
- rsyslog — o daemon tradicional
- Configurar rsyslog como cliente remoto
- Configurar rsyslog como servidor central
- Grafana Loki — logs modernos e leves
- ELK Stack — Elasticsearch, Logstash e Kibana
- Comparação das soluções
- Erros comuns e soluções
- Checklist de verificação
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
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:
- journald persistente em todas as máquinas:
journalctl --disk-usagemostra espaço ocupado e/var/log/journal/existe; - rsyslog activo:
systemctl status rsyslogmostra active (running) em cliente e servidor; - Firewall aberta:
ss -tlnp | grep 514mostra rsyslog à escuta no servidor; - Teste de fluxo end-to-end: executar
logger -t teste "fluxo $(date)"no cliente e confirmar que aparece no servidor dentro de 5 segundos; - Loki/ELK saudável:
curl http://localhost:3100/ready(Loki) oucurl http://localhost:9200/_cluster/health?pretty(ELK) retornam status verde/amarelo; - Retenção configurada: definir
--vacuum-timeno journald, logrotate no rsyslog, ou ILM policies no Elasticsearch — sem retenção, o disco enche; - 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;
- 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
- Dia 25: Monitoring com Prometheus e Grafana — a stack de métricas que se complementa com Loki para logs
- Dia 7: Systemd no Linux — Services, Timers e journalctl — base do journald coberta em detalhe
- Dia 21: Docker — Containers, Images, Volumes e Networks — necessário para correr Loki e ELK via Docker Compose
- Dia 9: Firewalls Linux — iptables, nftables, UFW e firewalld — abrir portas de logging de forma segura
- Dia 5: Processos e Jobs no Linux — diagnosticar processos de logging que consomem CPU/RAM excessiva