Practically every Suricata guide ends with installing Elasticsearch, Logstash and Kibana. For a single VPS that is bad advice: the stack will ask for four gigabytes of memory and constant attention, when all you wanted was to see what the IDS caught over the past day. Suricata works perfectly well without them — but it has one property that makes people install it and remove it a week later.

The mine in the default settings

Out of the box Suricata writes more than thirty event types to eve.json: not only alerts but every DNS query, every TLS handshake, every HTTP transaction, ARP, DHCP, flow after flow. Plus a separate stats.log every eight seconds. Suricata does not set up log rotation while doing so — that is the administrator's job, and nowhere is it written in large letters.

A figure from a real server: 15 gigabytes in two days — nine in eve.json and almost six in stats.log. About five days remained before the disk was full. There was not much traffic on that server either; on a busy node it would have been a matter of hours.

Check yours right now:

sudo du -sh /var/log/suricata/*

Keep only what you read

If you look at alerts rather than doing network forensics, exactly one event type is needed from eve-log. In /etc/suricata/suricata.yaml find the outputs block and, under types for eve-log, leave alert and comment the rest out. Switch off the statistics output in the same place:

  - stats:
      enabled: no

After editing, the configuration check is mandatory — before restarting the service:

sudo suricata -T -c /etc/suricata/suricata.yaml -v

Order matters: the test will not pass if the rules have not been loaded yet. First suricata-update, then the config check, then start.

Rotation that actually works

The file /etc/logrotate.d/suricata:

/var/log/suricata/*.log /var/log/suricata/*.json {
    daily
    rotate 7
    maxsize 200M
    missingok
    compress
    delaycompress
    create 0664 suricata suricata
    su suricata suricata
    postrotate
        systemctl kill -s HUP suricata
    endscript
}

Two lines here are not obvious and both are critical.

su suricata suricata — without it logrotate silently skips every file. The directory /var/log/suricata belongs to the group suricata rather than root, and logrotate considers such a setup unsafe. There will be no error in the mail and none in the log; you will simply be sure rotation exists until the disk runs out. The only way to catch it in advance is a dry run:

sudo logrotate -d /etc/logrotate.d/suricata

create 0664 suricata suricata — the permissions on the new file. With the defaults (0640), any panel or script reading the logs as a non-root user will see nothing after the very first rotation.

What to configure besides the logs

HOME_NET. This describes what Suricata considers its own. The default value lists all the private ranges, while a VPS has a public address — so some rules do not fire, or fire the wrong way round. State your own network explicitly.

Rules. The Emerging Threats Open set is pulled in by suricata-update, which belongs in cron once a day. Individual noisy signatures are disabled by identifier in /etc/suricata/disable.conf — do not be afraid to use it: the set is meant for a corporate network, and on an ordinary web server a dozen rules will fire constantly and for no reason.

Mode. By default Suricata listens to a copy of the traffic and only warns (IDS). Blocking mode (IPS, via nfqueue) on a single server is a risk mostly to yourself: one false positive and you have locked yourself out. Start by watching, and spend a month seeing what gets caught.

How to read it without Kibana

Short alerts live in /var/log/suricata/fast.log — one line per event, readable by eye:

sudo tail -50 /var/log/suricata/fast.log

The detail is in eve.json, one JSON object per line. Everything Kibana is usually installed for comes down to a single command:

sudo jq -r 'select(.event_type=="alert") | .alert.signature' \
    /var/log/suricata/eve.json | sort | uniq -c | sort -rn | head -20

That is the twenty most frequent signatures. Over a week such a list answers honestly what is going on with the server, and it also shows which rules it is time to switch off.

Why bother when Fail2ban is already there

They are different by nature. Fail2ban reads application logs and reacts to failed logins — that is, to what already reached a service. Suricata looks at the traffic itself and sees what will never be in a log: port scanning, exploit attempts matching known signatures, connections to command servers from inside your machine. The last one is particularly valuable: an outbound connection to somebody else's command and control is the earliest sign that something on the server is already running that you did not start.

Keeping both is fine, they do not conflict. The only question is whether anyone reads their output more often than once a quarter. What the same alerts look like on one page, split by category and source, is on the demo below.