Graylog — centralizacja logów z MongoDB i Elasticsearch
Opublikowano: 9 kwietnia 2026 · Kategoria: VPS / Monitoring
Gdy masz jeden serwer, logi w /var/log/ wystarczą. Gdy masz pięć, zaczynasz się gubić,
a przy dwudziestu szukanie przyczyny awarii w ssh po maszynach jest męczące. Rozwiązaniem jest
centralizacja — wszystkie logi w jednym miejscu, z wyszukiwarką, dashboardami i alertami. Graylog
to open source platforma do logów, która daje wszystko to out of the box, opierając się na trzech
komponentach: MongoDB (metadane, konfiguracja), Elasticsearch/OpenSearch (przechowywanie i wyszukiwanie
logów), Graylog server (web UI, inputs, streams, alerting).
Architektura stack
| Komponent | Rola | RAM (prod) |
|---|---|---|
| MongoDB 6+ | Konfiguracja Graylog, użytkownicy, streams, dashboards | 1 GB |
| OpenSearch 2+ | Silnik wyszukiwania i przechowywania logów (fork Elasticsearch) | 4 GB heap |
| Graylog Server | Web UI, REST API, inputs, processing pipeline | 2 GB heap |
| Nginx reverse proxy | SSL termination, autentykacja | 50 MB |
Instalacja przez Docker Compose
Najszybsza droga to Docker Compose — nie musisz walczyć z zależnościami Java i inicjalizacją
OpenSearch. Utwórz plik docker-compose.yml:
version: "3.8"
services:
mongodb:
image: mongo:6.0
volumes:
- mongodb_data:/data/db
restart: unless-stopped
opensearch:
image: opensearchproject/opensearch:2
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- DISABLE_INSTALL_DEMO_CONFIG=true
- DISABLE_SECURITY_PLUGIN=true
- "OPENSEARCH_JAVA_OPTS=-Xms4g -Xmx4g"
ulimits:
memlock: { soft: -1, hard: -1 }
volumes:
- opensearch_data:/usr/share/opensearch/data
restart: unless-stopped
graylog:
image: graylog/graylog:6.0
environment:
- GRAYLOG_PASSWORD_SECRET=zmien-to-na-mocny-sekret-16-znakow-minimum
- GRAYLOG_ROOT_PASSWORD_SHA2=sha256-hasla-admin
- GRAYLOG_HTTP_EXTERNAL_URI=https://logs.example.com/
- GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200
- GRAYLOG_MONGODB_URI=mongodb://mongodb:27017/graylog
depends_on: [mongodb, opensearch]
ports:
- "127.0.0.1:9000:9000" # Web UI
- "1514:1514/udp" # Syslog UDP
- "1514:1514" # Syslog TCP
- "12201:12201/udp" # GELF UDP
- "12201:12201" # GELF TCP
restart: unless-stopped
volumes:
mongodb_data:
opensearch_data: # Wygeneruj haslo admin echo -n "twoje-haslo-admin" | sha256sum # Wpisz wynik jako GRAYLOG_ROOT_PASSWORD_SHA2 # Uruchom stack docker compose up -d # Sprawdz logi docker compose logs -f graylog # Po 1-2 minutach web UI jest dostepny na http://127.0.0.1:9000 # Login: admin, haslo: twoje-haslo-admin
Inputs — jak wprowadzać logi do Graylog
W Graylog web UI przejdź do System -> Inputs. Wybierz typ inputa i kliknij
Launch new input. Najważniejsze typy:
- Syslog UDP/TCP (port 1514) — dla systemowych logów z rsyslog na serwerach Linux
- GELF UDP/TCP (port 12201) — natywny format Graylog, strukturalne pola, dla własnych aplikacji
- GELF HTTP (port 12202) — REST endpoint do wysyłania GELF przez HTTP POST
- Beats (port 5044) — dla Filebeat/Metricbeat z Elastic stack
- Raw/Plaintext TCP — dla niestandardowych formatów, parser w processing pipeline
Konfiguracja rsyslog na kliencie
# /etc/rsyslog.d/90-graylog.conf # Wysylaj wszystkie logi na Graylog (UDP, port 1514) *.* @logs.example.com:1514 # Dla TCP (gwarantuje dostarczenie): # *.* @@logs.example.com:1514 # Reload rsyslog sudo systemctl restart rsyslog # Weryfikacja - test log logger -t test "Hello Graylog"
GELF z aplikacji Python (graypy)
pip install graypy
# app.py
import logging
import graypy
handler = graypy.GELFUDPHandler('logs.example.com', 12201)
logger = logging.getLogger('myapp')
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info('User logged in', extra={'user_id': 42, 'ip': '203.0.113.10'})
logger.error('Payment failed', extra={'order_id': 999, 'amount': 150.00})
# W Graylog zobaczysz strukturalne pola user_id, ip, order_id jako osobne kolumny Streams — routing logów
Stream to filtr który przekierowuje wpasowane wiadomości do osobnego "kanału". Dzięki temu możesz: wydzielić logi z produkcji od developmentu, filtrować po aplikacji, budować dashboardy per zespół, ustawiać różne alerty per stream. Przykład reguły streamu "nginx errors":
sourcematch exactlywww01.example.comlevelless than or equal4(error i wyższe)facilityequalslocal0(nginx wysyła na local0)
Alerts — powiadomienia
Graylog obsługuje alerty na streams: Event Definitions pozwalają zdefiniować warunek
(np. "więcej niż 10 wiadomości z level=error w ciągu 5 minut w streamie nginx-errors"), a Notification wysyła powiadomienie przez email, Slack, webhook, PagerDuty. Przykłady reguł:
-
Alert gdy pojawi się
OutOfMemoryErrorw logach Java — natychmiastowy webhook na Slack - Alert gdy count 502/503 z nginx przekroczy 50 w ciągu minuty — email + PagerDuty
- Alert gdy failed SSH login przekroczy 20 z jednego IP w 10 minut — webhook do fail2ban/firewall
Dashboards i wyszukiwanie
Dashboardy w Graylog to panele z widgetami: wykres słupkowy wiadomości w czasie, top N source/user/URL, histogram kodów HTTP, licznik błędów. Wyszukiwanie używa Lucene Query Syntax:
# Wszystkie errory z ostatniej godziny level:3 AND timestamp:[now-1h TO now] # Errory HTTP 5xx z nginx source:www01 AND response_code:[500 TO 599] # Logi z uzytkownika admin w kilku streamach user_id:admin AND (stream:nginx OR stream:app) # Wyklucz health checki NOT request:/healthz AND level:<=4 # Regex message:/.*timeout after \d+ ms.*/
Retention i index rotation
Graylog dzieli logi na indexes (porcja danych w OpenSearch). W System -> Indices konfigurujesz rotation strategy: Size-based (np. 1 GB na index), Time-based (np. 1 index dziennie),
Message Count. Retention strategy: Delete (usuwaj najstarsze), Close (tylko zamykaj aby oszczędzić
RAM, można otworzyć). Dla 30 dni retencji i 1 index per dzień ustaw: Time-based + Delete + max
30 indexes.
Nginx reverse proxy z SSL
server {
listen 443 ssl http2;
server_name logs.example.com;
ssl_certificate /etc/letsencrypt/live/logs.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/logs.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Graylog-Server-URL https://$host/;
}
}