Centralized log management: MongoDB (metadata), OpenSearch (log storage), and Graylog (UI/API).
| Service | Role | Port |
|---|---|---|
| MongoDB | Graylog configuration and metadata | — (internal) |
| OpenSearch | Log storage and search | — (internal) |
| Graylog | Web UI, API, log ingestion | 9000 (web), 514/1514 (syslog), 12201 (GELF) |
Graylog provides a full-featured UI for searching, dashboards, and alerting out of the box. Loki is lighter but requires Grafana for visualization. Since we're already using Grafana for metrics, Graylog's independence keeps log management self-contained.
OpenSearch is the community fork after Elastic's license change. It's API-compatible and avoids licensing concerns for self-hosted deployments.
- MongoDB and OpenSearch are on an internal
graylog_netnetwork - Graylog joins both
graylog_net(backend) andmonitoring_net(for Fluent Bit and Grafana access) - Syslog ports (514, 1514) and GELF (12201) are exposed to the host
| Service | Memory | CPU | Rationale |
|---|---|---|---|
| MongoDB | 512M | 0.5 | Metadata only; low load |
| OpenSearch | 2G | 1 | Java heap is 1G; needs headroom |
| Graylog | 2G | 1 | Java heap + ingestion and query overhead |
OpenSearch memory must exceed OPENSEARCH_JAVA_OPTS heap settings. If you increase heap, increase the container limit.
Create .env from template. Required variables:
| Variable | Purpose |
|---|---|
GRAYLOG_PASSWORD_SECRET |
96-char random string for encryption |
GRAYLOG_ROOT_PASSWORD_SHA2 |
SHA256 hash of admin password |
GRAYLOG_HTTP_EXTERNAL_URI |
Public URL for web UI |
GRAYLOG_ROOT_TIMEZONE |
Timezone for UI |
OPENSEARCH_INITIAL_ADMIN_PASSWORD |
OpenSearch bootstrap password |
Generate secrets:
# Password secret (96 chars)
openssl rand -hex 48
# Admin password hash
echo -n "yourpassword" | sha256sum | cut -d' ' -f1| Path | Contents |
|---|---|
data/mongodb/ |
Graylog configuration, users, dashboards |
data/opensearch/ |
Log indices |
data/graylog/ |
Graylog state |
Backup priority: MongoDB contains configuration; OpenSearch contains logs. Back up MongoDB before upgrades.
Configure inputs in Graylog UI (System → Inputs):
| Input Type | Port | Use Case |
|---|---|---|
| GELF TCP | 12201 | Fluent Bit, Docker GELF driver |
| GELF UDP | 12201 | High-volume, loss-tolerant |
| GELF HTTP | 12201 | Scripts via log.sh, external apps |
| Syslog TCP | 514, 1514 | Network devices, legacy systems |
| Syslog UDP | 514, 1514 | Network devices |
Required inputs:
- GELF TCP on 12201 — For Fluent Bit integration
- GELF HTTP on 12201 — For script logging via
scripts/lib/log.sh
- System → Inputs → Select "GELF HTTP"
- Launch new input
- Bind:
0.0.0.0, Port:12201
Scripts can then send logs:
source /opt/docker/scripts/lib/log.sh
log_info "myapp" "Operation completed"- Requires
monitoring_netexternal network - MongoDB and OpenSearch must be healthy before Graylog starts (enforced via
depends_on)
Graylog not starting:
# Check OpenSearch health
curl http://localhost:9200/_cluster/health
# Check MongoDB
docker exec graylog-mongodb mongosh --eval "db.runCommand('ping')"OpenSearch out of memory:
- Increase container memory limit (must exceed Java heap)
- Check for runaway index growth
Logs not appearing:
- Verify input is running (System → Inputs)
- Check source is sending to correct port/protocol
- Check Graylog logs:
docker logs graylog
Configure index rotation in System → Indices:
- Index rotation strategy: time-based or size-based
- Retention: delete or close old indices
For space management, set retention to match your backup policy.