logrotate: gerenciar logs na VPS

Logs sem rotação enchem o disco silenciosamente até o servidor parar de funcionar. logrotate é a solução nativa do Linux, rotaciona, comprime e expira logs automaticamente para todos os serviços. Configurado corretamente, você nunca mais vai acordar com um servidor parado por falta de espaço em /var/log.

Entender o logrotate e sua configuração

Como o logrotate funciona e onde ficam as configurações:

bash
# Verificar instalação (já vem no Ubuntu):
which logrotate
logrotate --version

# Arquivos de configuração:
# /etc/logrotate.conf          — configuração global
# /etc/logrotate.d/            — configurações por serviço (um arquivo cada)
# /var/lib/logrotate/status    — registro do último rotate por arquivo

# Executado diariamente pelo cron:
cat /etc/cron.daily/logrotate

# Testar sem executar de verdade:
sudo logrotate --debug /etc/logrotate.conf

# Forçar rotação agora (ignorar data do último rotate):
sudo logrotate --force /etc/logrotate.d/nginx

# Ver status da última execução:
sudo cat /var/lib/logrotate/status | grep nginx

Configurar rotação para Nginx e aplicações

Templates de configuração para os serviços mais comuns:

bash
# /etc/logrotate.d/nginx — sobrescrever o padrão:
/var/log/nginx/*.log {
    daily                   # rotacionar diariamente
    missingok               # não errar se arquivo não existir
    rotate 14               # manter 14 arquivos rotacionados
    compress                # comprimir com gzip
    delaycompress           # comprimir na próxima rotação (não na atual)
    notifempty              # não rotacionar se arquivo vazio
    create 0640 www-data adm  # criar novo arquivo com essas permissões
    sharedscripts
    postrotate
        # Reabrir os arquivos de log sem reiniciar o Nginx:
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 $(cat /var/run/nginx.pid)
        fi
    endscript
}

# /etc/logrotate.d/minha-api — logs da aplicação Node.js:
/var/log/minha-api/*.log {
    daily
    missingok
    rotate 30               # manter 30 dias
    compress
    delaycompress
    notifempty
    su ubuntu ubuntu        # executar como usuário ubuntu
    postrotate
        # Recarregar PM2 para reabrir o arquivo de log:
        pm2 reloadLogs 2>/dev/null || true
    endscript
}

Controlar logs do Docker

Configurar limite de tamanho nos logs de containers:

json
# Configuração global para todos os containers:
# /etc/docker/daemon.json:
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",   # máximo de 10 MB por arquivo
    "max-file": "3"      # manter 3 arquivos (30 MB total por container)
  }
}

# Aplicar: sudo systemctl reload docker

# Configurar por container no docker-compose.yml:
services:
  api:
    image: minha-api:latest
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "5"     # 250 MB total para este container

# Ver uso de disco de logs do Docker:
sudo du -sh /var/lib/docker/containers/*/
sudo du -sh /var/lib/docker/containers/ --total

# Limpar logs antigos de containers manualmente:
sudo truncate -s 0 /var/lib/docker/containers/**/*-json.log

# Para containers antigos que não têm limite configurado:
# Parar, recriar com novas configurações de log

Monitorar uso de disco por logs

Alertar antes que os logs encham o disco:

bash
#!/bin/bash
# /opt/scripts/monitor-disco.sh

TELEGRAM_TOKEN="SEU_TOKEN"
TELEGRAM_CHAT_ID="SEU_CHAT_ID"
LIMITE_PERCENT=80

# Verificar uso de cada partição:
df -h | grep -vE "^Filesystem|tmpfs|udev" | while read line; do
    USO=$(echo "$line" | awk '{print $5}' | tr -d '%')
    PONTO=$(echo "$line" | awk '{print $6}')

    if [ "$USO" -gt "$LIMITE_PERCENT" ]; then
        MSG="⚠️ Disco $PONTO em $USO% no $(hostname)"
        curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" \
          -d "chat_id=$TELEGRAM_CHAT_ID" -d "text=$MSG"
    fi
done

# Checar diretórios que mais crescem:
du -sh /var/log/* 2>/dev/null | sort -rh | head -10
du -sh /var/lib/docker/containers/* 2>/dev/null | sort -rh | head -5

# Cron — verificar de hora em hora:
# 0 * * * * root /opt/scripts/monitor-disco.sh

Rotação de logs do PM2 e Node.js

Gerenciar logs de aplicações Node.js gerenciadas pelo PM2:

bash
# PM2 tem plugin de logrotate nativo:
pm2 install pm2-logrotate

# Configurar:
pm2 set pm2-logrotate:max_size 50M       # rotacionar ao atingir 50 MB
pm2 set pm2-logrotate:retain 30          # manter 30 arquivos
pm2 set pm2-logrotate:compress true      # comprimir com gzip
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD  # data no nome do arquivo
pm2 set pm2-logrotate:rotateInterval '0 0 * * *'  # diariamente à meia-noite

# Ver configuração atual:
pm2 get pm2-logrotate

# Logs do PM2 ficam em:
# ~/.pm2/logs/nome-da-app-out.log (stdout)
# ~/.pm2/logs/nome-da-app-error.log (stderr)

# Forçar rotação manual do PM2:
pm2 reloadLogs

# Linkar logs do PM2 ao logrotate do sistema:
# /etc/logrotate.d/pm2:
/root/.pm2/logs/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    postrotate
        pm2 reloadLogs 2>/dev/null || true
    endscript
}

Não quer configurar manualmente?

Implante o VPS em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Sim, o postrotate com kill -USR1 envia o sinal SIGUSR1 ao Nginx, que reabre os arquivos de log sem interromper conexões ativas. O delaycompress garante que o arquivo atual (sem extensão) não é comprimido imediatamente, dando tempo ao Nginx de fechar o arquivo antigo antes de comprimir.

daily/weekly/monthly: rotacionar por período de tempo. size 100M: rotacionar quando o arquivo atingir 100 MB, independente do tempo. Para logs de acesso do Nginx: daily com rotate 14. Para logs de erro raramente escritos: weekly. Para logs de aplicações de alto tráfego: size 100M para evitar arquivos grandes demais.

No logrotate: rotate 90 com daily garante 90 arquivos diários comprimidos. Com compress e delaycompress: cada arquivo ocupará 5-10% do espaço original. Faça a conta: 100 MB/dia de log não comprimido × 10% × 90 dias = 900 MB de espaço. Para compliance mais sério: envie para S3/MinIO com object lock (imutabilidade garantida).

sudo du -sh /var/log/* | sort -rh | head -20 mostra os maiores diretórios. sudo find /var/log -name "*.log" -exec du -sh {} + | sort -rh | head -20 para arquivos individuais. Docker: sudo du -sh /var/lib/docker/containers/* | sort -rh. Se algum arquivo está crescendo sem parar mesmo com logrotate: verifique se o serviço está recebendo o sinal de reabrir (postrotate não está funcionando).

São independentes. journald é o sistema de logging do systemd, gerencia logs de serviços systemd. logrotate gerencia arquivos .log em /var/log/. Para Docker e PM2 (não são serviços systemd puros): logrotate. Para Nginx instalado como serviço systemd: journald captura os logs E o Nginx escreve em /var/log/nginx/, configure logrotate para os arquivos do Nginx, e journald cuida dos seus próprios logs com SystemMaxUse no journald.conf.