Skip to content
Greylog Docker Setup Fortigate logging

Greylog Docker Setup Fortigate logging

Graylog Docker Compose + FortiGate Syslog

This setup runs:

  • Graylog 7.1
  • Graylog Data Node
  • MongoDB 7
  • Syslog TCP/UDP on port 5140
  • Graylog web interface on port 9000

1. Recommended VM

For a home/lab environment:

1
2
3
4
Ubuntu Server 24.04
4 vCPU
8 GB RAM
50–100 GB disk

If you intend to retain large amounts of firewall traffic logs, increase the storage accordingly.


2. Install Docker

If Docker and Docker Compose are already installed, skip this section.

1
2
3
4
sudo apt update
sudo apt install docker.io docker-compose-v2 -y

sudo systemctl enable --now docker

Optional: allow your user to run Docker without sudo:

1
sudo usermod -aG docker $USER

Log out and back in afterwards.

Check:

1
2
docker --version
docker compose version

3. Configure the Host

Graylog Data Node requires an increased virtual memory map limit.

1
2
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-graylog.conf
sudo sysctl --system

Confirm:

1
sysctl vm.max_map_count

You should see:

1
vm.max_map_count = 262144

4. Create the Graylog Directory

1
2
3
sudo mkdir -p /opt/graylog
sudo chown $USER:$USER /opt/graylog
cd /opt/graylog

5. Generate the Graylog Password Secret

Generate a random secret:

1
2
< /dev/urandom tr -dc A-Za-z0-9 | head -c 96
echo

Copy the output somewhere temporarily.

This is not your login password.


6. Generate the Admin Password Hash

Choose the password you want to use for the Graylog admin account.

Run:

1
echo -n 'YOUR_PASSWORD' | sha256sum

For example:

1
echo -n 'SuperSecretPassword' | sha256sum

Copy only the hash:

1
0123456789abcdef...

Do not put the plain-text password in the .env file.


7. Create the .env File

1
nano /opt/graylog/.env

Add:

GRAYLOG_PASSWORD_SECRET=PASTE_YOUR_96_CHARACTER_SECRET_HERE

GRAYLOG_ROOT_PASSWORD_SHA2=PASTE_YOUR_PASSWORD_HASH_HERE

GRAYLOG_HTTP_EXTERNAL_URI=http://10.10.10.50:9000/

Replace:

1
10.10.10.50

with the IP address of your Graylog Ubuntu VM.

Save with:

1
2
3
Ctrl+O
Enter
Ctrl+X

Protect the file:

1
chmod 600 /opt/graylog/.env

8. Create docker-compose.yml

1
nano /opt/graylog/docker-compose.yml

Paste:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
services:

  mongodb:
    image: mongo:7.0
    container_name: graylog-mongodb
    restart: unless-stopped

    networks:
      - graylog

    volumes:
      - mongodb_data:/data/db
      - mongodb_config:/data/configdb


  datanode:
    image: graylog/graylog-datanode:7.1
    container_name: graylog-datanode
    hostname: datanode
    restart: unless-stopped

    environment:
      GRAYLOG_DATANODE_NODE_ID_FILE: /var/lib/graylog-datanode/node-id
      GRAYLOG_DATANODE_PASSWORD_SECRET: ${GRAYLOG_PASSWORD_SECRET}
      GRAYLOG_DATANODE_MONGODB_URI: mongodb://mongodb:27017/graylog

    networks:
      - graylog

    volumes:
      - datanode_data:/var/lib/graylog-datanode

    ulimits:
      memlock:
        soft: -1
        hard: -1

      nofile:
        soft: 65536
        hard: 65536

    depends_on:
      - mongodb


  graylog:
    image: graylog/graylog:7.1
    container_name: graylog
    hostname: graylog
    restart: unless-stopped

    environment:
      GRAYLOG_NODE_ID_FILE: /usr/share/graylog/data/data/node-id
      GRAYLOG_PASSWORD_SECRET: ${GRAYLOG_PASSWORD_SECRET}
      GRAYLOG_ROOT_PASSWORD_SHA2: ${GRAYLOG_ROOT_PASSWORD_SHA2}

      GRAYLOG_MONGODB_URI: mongodb://mongodb:27017/graylog

      GRAYLOG_HTTP_BIND_ADDRESS: 0.0.0.0:9000
      GRAYLOG_HTTP_EXTERNAL_URI: ${GRAYLOG_HTTP_EXTERNAL_URI}

    depends_on:
      - mongodb
      - datanode

    networks:
      - graylog

    volumes:
      - graylog_data:/usr/share/graylog/data

    ports:
      # Graylog Web Interface
      - "9000:9000/tcp"

      # FortiGate / Generic Syslog
      - "5140:5140/tcp"
      - "5140:5140/udp"

      # Optional GELF inputs
      - "12201:12201/tcp"
      - "12201:12201/udp"


networks:

  graylog:
    driver: bridge


volumes:

  mongodb_data:
  mongodb_config:
  datanode_data:
  graylog_data:

9. Start Graylog

From:

1
cd /opt/graylog

Run:

1
2
docker compose pull
docker compose up -d

Check the containers:

1
docker compose ps

You should eventually have:

1
2
3
graylog
graylog-datanode
graylog-mongodb

all running.


10. Watch the Logs

1
docker compose logs -f

Or Graylog only:

1
docker compose logs -f graylog

On the first startup, Graylog generates a temporary preflight password.

Find it with:

1
docker compose logs graylog | grep -A5 -B5 "starting Graylog for the first time"

You should see something similar to:

1
2
Initial configuration is accessible at 0.0.0.0:9000,
with username 'admin' and password 'xxxxxxxxxx'

Use this temporary password for the first configuration only.


11. Open Graylog

Browse to:

1
http://10.10.10.50:9000

Replace the IP with your Graylog VM IP.

For the initial setup:

1
2
Username: admin
Password: temporary password from docker logs

Complete the Data Node setup wizard.

After the initial provisioning is finished, log in using:

1
2
Username: admin
Password: the original password you chose in Step 6

12. Create the FortiGate Syslog Input

In Graylog go to:

1
2
System
→ Inputs

Select:

1
Syslog UDP

and click:

1
Launch new input

Configure:

1
2
3
Title: FortiGate Syslog
Bind address: 0.0.0.0
Port: 5140

Then:

1
Save / Launch Input

You should now see the input as:

1
RUNNING

TCP Alternative

You can alternatively create:

1
Syslog TCP

on:

1
5140

TCP is preferable if you want reliable delivery.

For initial testing, UDP is slightly simpler.


13. Configure FortiGate

SSH to the FortiGate or use its CLI.

UDP

1
2
3
4
5
6
7
config log syslogd setting
    set status enable
    set server "10.10.10.50"
    set port 5140
    set mode udp
    set format default
end

Replace:

1
10.10.10.50

with the Graylog server IP.

Check the configuration:

1
show log syslogd setting

14. TCP / Reliable Syslog

If you created a Syslog TCP input in Graylog instead:

1
2
3
4
5
6
7
config log syslogd setting
    set status enable
    set server "10.10.10.50"
    set port 5140
    set mode reliable
    set format default
end

I would eventually use TCP/reliable rather than UDP once everything is working.


15. Enable FortiGate Traffic Logging

The FortiGate must actually generate logs for firewall policies.

In the GUI:

1
2
3
Policy & Objects
→ Firewall Policy
→ Edit Policy

Set:

1
Log Allowed Traffic: All Sessions

Or CLI:

1
2
3
4
5
config firewall policy
    edit 1
        set logtraffic all
    next
end

Replace 1 with the required firewall policy ID.

You don’t necessarily need all enabled on every policy. High-traffic rules can generate a significant amount of log data.


16. Check Whether Graylog Is Receiving Logs

In Graylog:

1
Search

Set the time range to:

1
Last 5 minutes

You should begin seeing messages containing FortiGate fields such as:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
date=2026-09-13
time=14:30:00
type="traffic"
subtype="forward"
srcip=10.10.10.25
dstip=1.1.1.1
srcport=54321
dstport=443
action="accept"
policyid=12

17. Check Syslog at the Ubuntu Host

If nothing appears in Graylog, check whether packets are reaching the server.

For UDP:

1
sudo tcpdump -ni any udp port 5140

For TCP:

1
sudo tcpdump -ni any tcp port 5140

You should see traffic coming from the FortiGate IP.

Check Docker is listening:

1
sudo ss -tulpn | grep 5140

18. Useful Docker Commands

Container status

1
2
cd /opt/graylog
docker compose ps

View logs

1
docker compose logs -f

Graylog logs only

1
docker compose logs -f graylog

Restart everything

1
docker compose restart

Restart Graylog

1
docker compose restart graylog

Stop

1
docker compose down

Start

1
docker compose up -d

Update images

1
2
docker compose pull
docker compose up -d

19. Data Persistence

The following Docker volumes contain the persistent data:

1
2
3
4
mongodb_data
mongodb_config
datanode_data
graylog_data

Check them with:

1
docker volume ls

Do not run:

1
docker compose down -v

unless you deliberately want to delete all Graylog data.


20. Recommended Layout

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
                    ┌───────────────────────┐
                    │      Graylog VM       │
                    │                       │
FortiGate ─Syslog──►│ TCP/UDP 5140          │
                    │                       │
                    │ Graylog :9000         │
                    │ Data Node             │
                    │ MongoDB               │
                    └──────────┬────────────┘
                         Web Browser

You can later send logs from additional devices into exactly the same server:

1
2
3
4
5
6
FortiGate ──┐
pfSense ────┤
Proxmox ────┤
Ubuntu ─────┼──► Graylog
Pi-hole ────┤
Switches ───┘

For different device types, create separate Graylog inputs or streams so the logs can easily be filtered and searched.