Graylog no Docker

Saudações.

Esse tutorial é um guia rápido de instalação e ativação inicial do Graylog, um sistema de armazenamento de logs e observabilidade gratuito e automatizado.

Pré-requisitos (constam em outros artigos aqui do blog):

  • Instalação do Linux (Debian ou Alpine);
  • Internet no servidor (sua VPS ou host);
  • Docker CE instalado;

1 – Sobre Graylog

O Graylog é uma plataforma de gerenciamento centralizado de logs (SIEM/Log Management) de código aberto, desenvolvida pela Graylog, Inc.

Sua principal função é coletar, indexar, analisar e visualizar grandes volumes de dados de log provenientes de diversas fontes: servidores, aplicações, dispositivos de rede, contêineres, nuvem e muito mais.

1.1 – Recursos

A edição Graylog Open é totalmente gratuita e inclui um conjunto robusto de funcionalidades:

  • Coleta e Ingestão:
    • Suporte nativo aos protocolos GELF (Graylog Extended Log Format), Syslog (UDP/TCP), Beats, CEF, JSON e Raw/Plaintext;
    • Inputs configuráveis via interface web ou API: TCP, UDP, HTTP, Kafka, AMQP, AWS S3, AWS CloudWatch;
    • Agentes de coleta compatíveis: Filebeat, Fluentd, Logstash, NXLog, rsyslog, syslog-ng, Telegraf;
  • Processamento e Enriquecimento:
    • Pipelines de processamento com linguagem de regras própria (Pipeline Rules Language);
    • Extratores de campos (Regex, JSON, CSV, Grok, Key-Value);
    • Lookup Tables para enriquecimento de dados (GeoIP, DNS reverso, listas customizadas);
    • Streams para roteamento dinâmico de mensagens;
  • Busca e Análise:
    • Busca em tempo real com linguagem similar ao Lucene;
    • Histórico de buscas e buscas salvas;
    • Estatísticas, contagens e agrupamentos;
    • Correlação de eventos em janelas de tempo;
  • Dashboards e Visualizações:
    • Criador de dashboards interativos com widgets (gráficos de linha, barras, pizza, mapas, tabelas);
    • Compartilhamento de dashboards por URL;
    • Atualização automática em tempo real;
  • Alertas e Notificações:
    • Alertas baseados em contagem, threshold, correlação e ausência de eventos;
    • Notificações via e-mail, Slack, PagerDuty, HTTP webhook;
    • Agendamento e supressão de alertas;
  • Segurança e Controle de Acesso:
    • Gerenciamento de usuários e papéis (RBAC básico);
    • Autenticação LDAP/Active Directory;
    • Retenção e arquivamento de logs por stream;
  • API e Integrações:
    • API REST completa documentada via Swagger;
    • Suporte a plugins e content packs da comunidade;
    • Exportação de dados via API;

1.2 – Vantagens

O Graylog ganha espaço na maioria das empresas por alguns diferenciais:

  • Custo-benefício: Não há custo de licença por volume de dados ingeridos (ao contrário de Splunk e Datadog), tornando-o ideal para organizações com grandes volumes de log;
  • Interface web intuitiva: O painel de controle do Graylog é amplamente reconhecido como mais amigável do que o da stack ELK pura. A criação de dashboards, alertas e pipelines é feita visualmente sem necessidade de editar arquivos YAML;
  • GELF (protocolo nativo): O protocolo GELF permite enviar logs estruturados em JSON com campos customizados, eliminando a necessidade de extratores para dados já estruturados com suporte acompressão, chunking para UDP e transporte TCP;
  • Performance de Busca: Ao utilizar OpenSearch/Elasticsearch como backend, o Graylog herda capacidade de busca full-text em bilhões de eventos com latência de milissegundos;
  • Pipelines: Permite transformar, enriquecer, rotear e descartar mensagens em tempo real, com lógica condicional sofisticada, sem necessidade de ferramentas externas como Logstash;
  • Facilidade de Implantação com Docker: Em poucos segundos o sistema estará pronto para uso em produção;
  • Custer e escala horizontal: Projetado para clusters, permitindo adicionar nós de processamento e indexação de forma incremental.

1.3 – Desvantagens

Com grandes poderes vem algumas desvantagens:

  • Dependência de Múltiplos Componentes: Manter Graylog + OpenSearch + MongoDB em sincronia exige conhecimento de três tecnologias distintas pois falhas em qualquer um dos três componentes comprometem o sistema;
  • Alto Consumo de Memória do OpenSearch: O OpenSearch/Elasticsearch é notoriamente faminto por RAM, em ambientes pequenos a alocação de heap do OpenSearch pode competir com os demais serviços do servidor;
  • Recursos Avançados Bloqueados: Funcionalidades como Illuminate (content packs avançados), Anomaly Detection baseada em IA/ML, Audit Log completo, SOAR integrado e suporte corporativo estão reservados às edições pagas (Operations e Security);
  • Limitações do RBAC na Versão Open: O controle de acesso granular por stream, campo ou dado sensível (mascaramento de PII) é limitado na versão gratuita. Ambientes com múltiplas equipes e requisitos rígidos de segmentação podem precisar da versão paga;
  • Complexidade Operacional em Escala: Dimensionar corretamente o cluster de OpenSearch, gerenciar índices, políticas de retenção (ILM) e shard allocation exige experiência, erros de configuração resultam em degradação severa de performance.

1.4 – Sistemas concorrentes

O Graylog não domina sozinho e em grandes empresas ele perde lugar para alguns sistemas e em pequenas empresas para outros, principais alternativas:

SoluçãoModeloPontos FortesPontos Fracos
Elastic Stack (ELK/EFK)Open Core + PagoEcossistema vasto, Kibana poderoso, integração nativaCurva de aprendizado alta, sem interface de gestão simplificada
SplunkProprietárioRecursos analíticos avançados, SIEM nativo, MLCusto altíssimo por GB ingerido
DatadogSaaS/PagoObservabilidade full-stack, APM integradoCusto proporcional ao volume
Loki + GrafanaOpen SourceLevíssimo, não indexa conteúdo, custo baixoBusca limitada (sem full-text), adequado apenas para logs de app
OpenSearch + DashboardsOpen SourceFuncional sem Graylog, ativo da AWSInterface menos amigável para ops de log
WazuhOpen SourceSIEM + XDR + compliance nativoFoco em segurança, menos flexível para log geral
Fluentd + InfluxDBOpen SourceLeve, excelente para métricasNão é solução completa de log management
SeqFreemiumExcelente para .NET, interface muito limpaPouco suporte a fontes heterogêneas

2 – Ajustes no sistema

O Graylog requer alguns ajustes no sistema para evitar problemas de performance e inconsistências. Esses ajustes são opcionais mas altamente recomendados.

Você deve, previamente:

  • Data/hora do servidor finamente sincronizada com NTP/NTS
  • Manter a coerência entre o IP do servidor e o nome de DNS (real ou fictício) no arquivo /etc/hosts
  • Possuir um DNS funcionando bem e rápido, configure o IP em /etc/resolv.conf

Esses ajustes mudam o comportamento padrão do Kernel Linux.

Bash
# Aumentar limite de mmap para OpenSearch (obrigatório)
echo "vm.max_map_count=262144" > /etc/sysctl.d/041-vm-max-map-count.conf

# Aplicar imediatamente
sysctl -w vm.max_map_count=262144;

3 – Preparativos

Antes de rodar os softwares, vamos aos requisitos vitais.

3.1 – Portas de ingestão de dados

O container final do Graylog precisa receber tráfego das portas de inbox dos protocolos que ele suporta, mesmo se você não for usa. Não adianta configurar a porta dentro do Graylog se o Docker não entregar o tráfego para o container.

PortaProtocolo L4Protocolo de inbox
514TCP e UDPSyslog (Porta RFC)
1514TCP e UDPSyslog (Porta alternativa)
2055UDPNetflow
5044TCPBeats (Filebeat, Metricbeat)
5140TCP e UDPSyslog (Porta alternativa)
5555TCPRAW TCP
8999TCPData Node REST API (apenas localhost)
9000TCPInterface web e REST API do Graylog
9200TCPOpenSearch REST API (apenas localhost)
12201TCP e UDPGELF (Graylog Extended Log Format)
13301TCPGraylog Forwarder (dados)
13302TCPGraylog Forwarder (config)

3.2 – Pasta de volume

Todos os dados acumulados pelo MongoDB, DataNode e Graylog devem ficar em local específico e explicito para backups e recuperações futuras.

Vou me basear no caminho: /storage/graylog/

Bash
# Diretorio principal do volume
DATADIR=/storage/graylog;

# Criar diretorios na base:
mkdir -p "$DATADIR";
mkdir -p "$DATADIR/mongodb";
mkdir -p "$DATADIR/datanode";
#mkdir -p "$DATADIR/config";
#mkdir -p "$DATADIR/contentpacks";
#mkdir -p "$DATADIR/journal";
#mkdir -p "$DATADIR/opensearch";

# Ajustes
chmod -R 777       "$DATADIR";
#chmod -R 750       "$DATADIR/datanode";
#chown -R 1100:1100 "$DATADIR";

# - Container de graylog roda com graylog:graylog = uid 1100
#chown -R 1100:1100 "$DATADIR";

# - Container do MongoDB roda como root
chmod -R 0755      "$DATADIR/mongodb";

# - Arquivos com segredos
touch "$DATADIR/admin-password";
touch "$DATADIR/secret";
chmod -R 0700  "$DATADIR/admin-password";
chmod -R 0700  "$DATADIR/secret";

3.3 – Senha de administração

O Graylog é implementado usando três senhas:

  • Senha temporária do Graylog: Gerada aleatoriamente e dá acesso à interface de setup do Graylog na primeira execução;
  • Senha administrativa: Precisa ser gerada como senha segura, usada para administrar o Graylog. A senha é informada ao Graylog em hash SHA2-512;
  • Secret de backend: Senha ultra segura para comunicação interna dos serviços.

Gerando senha administrativa:

Bash
# Diretorio de base
    DATADIR="/storage/graylog";

# Senha administrativa
    # - Usar um UUID randomico como senha segura
    if [ -s $DATADIR/admin-password ]; then
        echo "# Graylog: Senha definida em $DATADIR/admin-password";
    else
        echo "# Graylog: Gerando senha administrativa inicial";
        head -1 /proc/sys/kernel/random/uuid > $DATADIR/admin-password;
    fi;

    # - Senha de admin (senha final)
    ADMIN_PASS=$(head -1 $DATADIR/admin-password);
    ADMIN_HASH=$(echo -n "$ADMIN_PASS" | sha256sum | cut -d' ' -f1);
    echo "$ADMIN_HASH" > $DATADIR/admin-hash;

# Exibir
    echo "# Graylog";
    echo "# - Senha de admin....: $(head -1 $DATADIR/admin-password)";
    echo "# - Hash SHA2-512.....: $(head -1 $DATADIR/admin-hash)";
    echo;

Gerando secret de backend:

Bash
# Diretorio de base
    DATADIR="/storage/graylog";

# Secret de backend
    # - Usar um ASCII longo e randomico como secret
    if [ -s $DATADIR/secret ]; then
        echo "# Graylog: Secret definida em $DATADIR/secret";
        GRAYLOG_SECRET=$(head -1 $DATADIR/secret);
    else
        echo "# Graylog: Gerando secret de servicos";
        GRAYLOG_SECRET=$(head -c 1024 /dev/urandom | tr -dc A-Za-z0-9 | head -c 96);
        echo "$GRAYLOG_SECRET" > $DATADIR/secret;
    fi;

# Exibir
    echo "# Graylog";
    echo "# - Secret de servicos: $(head -1 $DATADIR/secret)";
    echo;

3.4 – URL de acesso

Você precisa informar por variável de ambiente qual é a URL de base para acesso ao Graylog no navegador do usuário. Escolha:

  • IP e porta 9000
    • Exemplo: http://45.255.128.2:9000
  • FQDN, nome de DNS para acesso via proxy/traefik
    • Exemplo: https://graylog.seudominio.com.br
Bash
# Diretorio de base
    DATADIR="/storage/graylog";

# URL de base para acesso administrativo
    echo "http://45.255.128.2:9000"            > $DATADIR/url;
    # echo "http://$(hostname -f):9000"         > $DATADIR/url;
    # echo "http://graylog.$(hostname -f):9000" > $DATADIR/url;
    # echo "https://graylog.$(hostname -f)"     > $DATADIR/url;

4 – Rodando Graylog no Docker

Vamos implementar passo a passo.

4.1 – Rede Docker

Padrão “network_public” que costumo usar nos meus tutoriais:

Bash
# Rede de containers
docker network create network_public \
    -d bridge \
    -o com.docker.network.bridge.name=br-net-public \
    -o com.docker.network.driver.mtu=1500 \
    -o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
    --subnet 10.249.0.0/16 \
    --gateway 10.249.255.254;

4.2 – Container do MongoDB

O MongoDB é o storage de todos os dados coletados e processados pelo GrayLog:

Bash
# Variaveis
    NAME="graylog-mongodb";
    IMAGE="mongo:7.0";
    DATADIR="/storage/graylog";

# Rodar/renovar
    docker pull $IMAGE;
    docker stop $NAME 2>/dev/null;
    docker rm   $NAME 2>/dev/null;
    docker run -d \
        --name $NAME \
        --hostname $NAME.intranet.br \
        --restart unless-stopped \
        \
        --network network_public \
        --ip=10.249.222.101 \
        \
        -v $DATADIR/mongodb:/data \
        \
        $IMAGE;

# Analise:
    # - Logs do container
    docker logs $NAME  --tail 20;
    
    # - Teste de funcionamento
    docker exec $NAME  mongosh --eval "db.adminCommand({ping:1})";
    # Precisa retornar:
    #  { ok: 1 }

4.3 – Container do DataNode

Esse é o principal backend do Graylog:

Bash
# Variaveis
    NAME="graylog-datanode";
    IMAGE="graylog/graylog-datanode:7.0";
    DATADIR="/storage/graylog";
    INTERNAL_DIR="/var/lib/graylog-datanode";

# Secret
    GRAYLOG_SECRET=$(head -1 $DATADIR/secret);

# Rodar/renovar
    docker pull $IMAGE;
    docker stop $NAME 2>/dev/null;
    docker rm   $NAME 2>/dev/null;
    docker run -d \
        --name $NAME \
        --hostname $NAME.intranet.br \
        --restart unless-stopped \
        \
        --network network_public \
        --ip=10.249.222.102 \
        \
        --ulimit memlock=-1:-1 \
        --ulimit nofile=65536:65536 \
        \
        -e GRAYLOG_DATANODE_PASSWORD_SECRET="$GRAYLOG_SECRET" \
        -e GRAYLOG_DATANODE_MONGODB_URI="mongodb://graylog-mongodb:27017/graylog" \
        -e GRAYLOG_DATANODE_OPENSEARCH_DATA_LOCATION="$INTERNAL_DIR/opensearch" \
        \
        -p 127.0.0.1:8999:8999 \
        -p 127.0.0.1:9200:9200 \
        -p 127.0.0.1:9300:9300 \
        \
        -v $DATADIR/datanode:$INTERNAL_DIR \
        \
        $IMAGE;

4.4 – Container do Gaylog

O Graylog é um servidor de API, front-end e receptor de dados num único processo Java. Rodando:

Bash
# Variaveis
    NAME=graylog-server;
    IMAGE="graylog/graylog:7.0";
    DATADIR="/storage/graylog";

# Endereco de acesso via navegador
    GRAYLOG_URL=$(head -1 $DATADIR/url);

# Senhas
    # - Senha de admin (senha final no formato hash SHA512)
    ADMIN_PASS=$(head -1 $DATADIR/admin-password);
    ADMIN_HASH=$(head -1 $DATADIR/admin-hash);

    # - Secret
    GRAYLOG_SECRET=$(head -1 $DATADIR/secret);

# Rodar/renovar
    docker pull  $IMAGE;
    docker stop  $NAME 2>/dev/null;
    docker rm -f $NAME 2>/dev/null;
    docker run -d \
        --name $NAME \
        --hostname $NAME.intranet.br \
        --restart unless-stopped \
        \
        --network network_public \
        --ip=10.249.222.109 \
        \
        --ulimit memlock=-1:-1 \
        --ulimit nofile=65536:65536 \
        \
        -e GRAYLOG_REPORT_DISABLE_SANDBOX=true \
        -e GRAYLOG_PASSWORD_SECRET="${GRAYLOG_SECRET}" \
        -e GRAYLOG_ROOT_PASSWORD_SHA2="${ADMIN_HASH}" \
        -e GRAYLOG_HTTP_EXTERNAL_URI="${GRAYLOG_URL}/" \
        -e GRAYLOG_HTTP_PUBLISH_URI="${GRAYLOG_URL}/" \
        -e GRAYLOG_MONGODB_URI="mongodb://graylog-mongodb:27017/graylog" \
        -e GRAYLOG_DATANODE_HTTP_CONNECT_URI="http://graylog-datanode:8999" \
        -e GRAYLOG_NODE_ID_FILE=/usr/share/graylog/data/config/node-id \
        -e GRAYLOG_HTTP_BIND_ADDRESS=0.0.0.0:9000 \
        -e xGRAYLOG_ELASTICSEARCH_HOSTS=http://graylog-opensearch:9200 \
        \
        -p 2055:2055/udp \
        -p 9000:9000/tcp \
        -p 5044:5044/tcp \
        -p 5555:5555 \
        -p 5140:5140/tcp \
        -p 5140:5140/udp \
        -p 12201:12201/tcp \
        -p 12201:12201/udp \
        -p 13301:13301/tcp \
        -p 13302:13302/tcp \
        \
        -v $DATADIR:/usr/share/graylog/data \
        \
        $IMAGE;

# Acesso
    echo;
    echo "# Acesso ao Graylog";
    echo "# URL.....: $GRAYLOG_URL";
    echo "# Usuario.: admin";
    echo "# Senha...: $ADMIN_PASS";
    echo;

4.5 – Acesso temporário para setup

A primeira fase do setup é acessar o Graylog com uma senha temporária que ele gera aleatoriamente.

Detecte a senha nos logs do container graylog-server:

Bash
# Analisar logs do container do graylog
#  para capturar a senha temporaria inicial
docker logs graylog-server;

    # Initial configuration is accessible at 0.0.0.0:9000,
    #    with username 'admin' and password 'RDxDeLjEUm'.
    # Try clicking on http://admin:RDxDeLjEUm@0.0.0.0:9000
    #

# Exibir senha especifica
    docker logs graylog-server 2>&1 | tail -n 20 > /tmp/gst20.txt;
    PWL=$(egrep '.*username.*admin.*password' /tmp/gst20.txt);
    TMP=$(echo "$PWL" | sed 's#and.password#|#' | cut -f2 -d"|" | cut -f2 -d"'");
    echo;
    echo "# Usuario.........: admin";
    echo "# Senha temporaria: $TMP";
    echo;

Use o usuário admin e a senha acima (a frente da palavra “password”).

Procedimentos:

  • 1 – Clique na guia “Create new CA” e no botão “Graylog CA“;
  • 2 – Em “Configure Renewal Policy“:
    • Mude de “days” para “years” (30 years);
    • Clique em “Create policy“;
  • 3 – Em “Provision certificates“:
    • Clique no botão “Provision certificate and continue“;
  • (vai demorar 1 minuto após o passo 3)
  • 4 – Em “Configuration finished“:
    • Clique em “Resume startup”.

O container será reiniciado automaticamente para subir pronto para trabalhar.

Agora você deve acessar com o usuário admin e a “Senha de admin” definida no capítulo 3.3.

5 – Criando inputs

O Graylog está pronto mas não está aceitando dados (logs, flow, etc).

Será necessário criar os serviços de inputs para cada protocolo.

5.1 – Input para Syslog

Acesse a interface administrativa.

Vamos criar a input de syslog transportado por UDP na porta 5140 redirecionada pelo Docker para o container graylog-server.

Procedimentos:

  • 1 – Click no último menu no topo lado direito chamado “System“;
    • Clique em “inputs“;
  • 2 – No menu chamado “Select input” selecione “Syslog UDP“;
  • 3 – Clique no botão “Launch new input“;
  • 4 – Vai aparecer uma janela “Launch new Syslog UDP input“:
    • Preencha o “title” com “syslog-udp-5140“;
    • Mude a porta em “Port” de 514 para 5140;
    • Em “Time Zone” selecione “UTC-0300 America/Sao_Paulo“;
  • 5 – Click em “Launch input” para criar a input;
  • 6 – A input aparecerá na tela de inputs, clique em “Set-up input” para iniciar o serviço;
    • Vai aparecer um wizard (passo-a-passo), clique em “Next” > “Start input“.

Faça o mesmo procedimento para criar o “Syslog TCP” com nome “syslog-tcp-5140” na porta 5140/TCP com timezone America/Sao_Paulo.

5.2 – Input para Netflow

Crie a input para o protocolo “Netflow UDP” chamada “netflow-udp-2055” na porta 2055/UDP.

.

Seu GrayLog está pronto para consumir muita CPU, memória e tempo!

Tentei fugir de mim,
mas onde eu ia eu estava.
Tiririca

Terminamos por hoje!

Patrick Brandão, patrickbrandao@gmail.com