Setup Graylog as central syslog server
10 Dec 2020I was searching for information about running a local syslog server in my network when I stumbled on Graylog. I’m currently running an ElastiFlow server with dashboards for my netflow and haproxy syslog info. But this way my haproxy server stores all logs it self and using filebeat to send it to my ELK stack. I would like to use a central syslog server to store the log files. Using a central syslog server I can easily set up more servers to log to that server.
Using Docker
I decided to run all of it in Docker containers even though I have a dedicated VM for it. I like the isolation a docker container have and i can keep all the config and data in one folder (with some sub folders). Another thing is that they are not depending on my Host, I can store my docker-compose.yml file on a network disk or git-repo and then just install whatever Linux distro I like at the moment and then just start my service(s).
Installing Docker
Well I have already written a small guide on how to Install Docker and docker-compose on Debian 10 so I will not cover that part here again.
Docker compose
I like to write docker-compose files for my services/servers and Graylog already have one, so why complicate stuff lets start with theirs: (you can find it over at their site)
version: '3'
services:
# MongoDB: https://hub.docker.com/_/mongo/
mongo:
image: mongo:4.2
networks:
- graylog
# Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/6.x/docker.html
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.0
environment:
- http.host=0.0.0.0
- transport.host=localhost
- network.host=0.0.0.0
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
deploy:
resources:
limits:
memory: 1g
networks:
- graylog
# Graylog: https://hub.docker.com/r/graylog/graylog/
graylog:
image: graylog/graylog:4.2
environment:
# CHANGE ME (must be at least 16 characters)!
- GRAYLOG_PASSWORD_SECRET=somepasswordpepper
# Password: admin
- GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
# This can be set to an url/domain name if you have a local DNS
- GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/
networks:
- graylog
restart: always
depends_on:
- mongo
- elasticsearch
ports:
# Graylog web interface and REST API
- 9000:9000
# Syslog TCP
- 1514:1514
# Syslog UDP
- 1514:1514/udp
# GELF TCP
- 12201:12201
# GELF UDP
- 12201:12201/udp
networks:
graylog:
driver: bridge
Set server timezone
elasticsearch:
...
environment:
# Set server timezone
- TZ=Europe/Stockholm
- GRAYLOG_TIMEZONE=Europe/Stockholm
Add persistent storage volume for services
Now lets change the docker-compose.yml to use persistent storage. I usually store my server data under /srv including my docker-compose.yml. This way I can move the content of /srv to anothe Linux server and just run docker-compose up -d in /srv folder and it will start my services.
mongo_db:
...
volumes:
- /srv/mongodb:/data/db
elasticsearch:
...
volumes:
- /srv/elasticsearch:/usr/share/elasticsearch/data
graylog:
...
volumes:
- /srv/graylog:/usr/share/graylog/data
Don’t forget to create all folders.
sudo mkdir -p /srv/{mongodb,elasticsearch,graylog}
Local config files
I like to configure my services using local files if possible. This way my docker-compose.yml isn’t cluttered with loads of environment variables.
So lets download and prep the default config files.
mkdir -p /srv/graylog/config
cd /srv/graylog/config
wget https://raw.githubusercontent.com/Graylog2/graylog-docker/4.0/config/graylog.conf
wget https://raw.githubusercontent.com/Graylog2/graylog-docker/4.0/config/log4j2.xml
Change permissions
Graylog is running with UID 1100, I don’t know about GID but I do change both UID and GID to 1100
sudo chown 1100:1100 -R /srv/graylog
Change Graylog admin password
Well the most important thing to change is your own password, that is the root_password_sha2
parameter in the config file.
To change the password you need a sha256 hash of your wanted password, this can be retrieved by piping your password to sha256sum in Linux
echo -n "superhardpassword" | sha256sum
85dee518689f3693440b4ae448d75b5beae363655f6a21e1dcdb164d266984bf -
Well not entirely true, you get the sha256 hash, spaces and a dash. You only want the contigious part up until the first space. If you want to script this, the ending parts can be removed using cut
like this
echo -n "superhardpassword" | sha256sum | cut -d" " -f1
85dee518689f3693440b4ae448d75b5beae363655f6a21e1dcdb164d266984bf
so the final string in the graylog.conf would be this
root_password_sha2 = 85dee518689f3693440b4ae448d75b5beae363655f6a21e1dcdb164d266984bf
Don’t forget to change password_secret
to some long random string, the comment in the default graylog.conf
recomends at least 64 characters.
I made a script for this:
#!/bin/bash
# graylog_passwd.sh
CONF=/srv/graylog/config/graylog.conf
echo -n "Enter a new password: "
PWD=$(head -1 </dev/stdin | tr -d '\n' | sha256sum | cut -d" " -f1)
echo "root_password_sha2 = $PWD"
sed -i "s/root_password_sha2 = .*/root_password_sha2 = $PWD/" $CONF
SALT=$(tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 64 ; echo)
echo "password_secret = $SALT"
sed -i "s/password_secret = .*/password_secret = $SALT/" $CONF
Graylog and Elasticsearch error
When I finally started my Graylog services I got errors about Graylog not being able to find Elasticsearch server. I finally solved this by exposing elasticsearch ports and instruct graylog to use my server IP and to use elasticsearch version 7.
graylog:
...
environment:
...
- GRAYLOG_ELASTICSEARCH_HOSTS=http://192.168.1.20:9200
- GRAYLOG_ELASTICSEARCH_VERSION=7
I could have put this configuration in the graylog.conf, but I decided to add this configuration to the docker-compose file. This will keep my networking settings in one place and the graylog specific configuration in another.
Everything you can configure in graylog.conf you can configure using GRAYLOG_* envrionment variable. Just remember the environment variable is all upper case and the settings variable in graylog.conf is lower case.
Syslog UDP input
Some quick notes to setup Syslog UDP input, this is needed to receive Syslog messages.
First you go to System -> Inputs At the inputs configuration screen you choose an input from the drop-down list and then press Launch new input This will bring up the Syslog UDP configuration dialog Give the input a name and the port where the docker container is listening by default 1514.
And then we need a final change to the docker-compose.yml
graylog:
...
ports:
...
# Syslog TCP
- 514:1514
# Syslog UDP
- 514:1514/udp
I changed both TCP and UDP ports, this way the none root Graylog service can listen on 1514 port and Docker will make the actual server listen to the default Syslog port 514.
Testing Syslog
A simple way to test the syslog is to send a message, this can be done using logger
on a Linux machine
logger -n 192.168.0.20 "My message"
This will send a syslog message to the server with IP 192.168.0.20, if you don’t use the standard syslog port you can specify what port using the -P <port>
parameter like this
logger -n 192.168.0.20 -P 1514 "MyMessage"
Troubleshooting
If you want to troubleshoot the Syslog input you can temporarly stop the input and create a new RAW input that will listen on the port 1514. This way you will receive the unprocessed messages in Graylog. Just remember to disable or remove the RAW input when you enables the Syslog input again.
The final docker-compose.yml
version: '3'
services:
# MongoDB: https://hub.docker.com/_/mongo/
mongo:
image: mongo:4.2
container_name: mongodb
volumes:
- /srv/mongodb:/data/db
networks:
- graylog
# Elasticsearch: https://www.elastic.co/guide/en/elasticsearch/reference/6.x$
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.0
container_name: elasticsearch
environment:
- http.host=0.0.0.0
- transport.host=localhost
- network.host=0.0.0.0
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- /srv/elasticsearch:/usr/share/elastisearch/data
ulimits:
memlock:
soft: -1
hard: -1
deploy:
resources:
limits:
memory: 1g
ports:
- 9200:9200
networks:
- graylog
# Graylog: https://hub.docker.com/r/graylog/graylog/
graylog:
image: graylog/graylog:4.2
container_name: graylog
environment:
# Set server timezone
- TZ=Europe/Stockholm
- GRAYLOG_TIMEZONE=Europe/Stockholm
- GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.0.20:9000/
- GRAYLOG_ELASTICSEARCH_HOSTS=http://192.168.0.20:9200
- GRAYLOG_ELASTICSEARCH_VERSION=7
volumes:
- /srv/graylog/graylog:/usr/share/graylog/data
networks:
- graylog
restart: always
depends_on:
- mongo
- elasticsearch
ports:
# Graylog web interface and REST API
- 9000:9000
# Syslog TCP
- 514:1514
# Syslog UDP
- 514:1514/udp
# GELF TCP
- 12201:12201
networks:
graylog: