Why This Matters
Most breaches aren’t caught at the moment of intrusion — they’re caught weeks later, during forensics, after the damage is done. The 2013 Target breach is the textbook example: the company’s own malware-detection tooling flagged the attacker’s activity in real time, but no one acted on the alert because the signal was buried in noise and the process to escalate it didn’t exist. The result was 40 million stolen card numbers and a breach that cost the company hundreds of millions of dollars.
An Intrusion Detection and Prevention System (IDS/IPS) doesn’t just generate alerts — it gives you the visibility layer that turns "we got breached three weeks ago" into "we blocked this five seconds after it started." Suricata is the leading open-source choice for this job: it’s multi-threaded, supports IDS (detection), IPS (inline blocking), and full network security monitoring (NSM) with protocol logging, and it’s backed by the Open Information Security Foundation (OISF) with active, well-maintained rule feeds.

This guide walks through a real, working Suricata IDS setup on Linux: installing Suricata on Ubuntu, configuring it to monitor live traffic, pulling and enabling a ruleset, verifying detection actually works, and then converting it from passive IDS to active inline IPS.
Regulatory context: PCI DSS Requirement 11.4 explicitly requires network intrusion detection or prevention techniques to detect and/or prevent intrusions. NIST SP 800-94 (Guide to Intrusion Detection and Prevention Systems) is the standard reference architecture this deployment follows. If you handle cardholder data or are building toward a NIST-aligned control set, this isn’t optional tooling — it’s a documented control.
Prerequisites
Before starting, make sure you have:
- A Linux server running Ubuntu 22.04 LTS or 24.04 LTS (this guide uses Ubuntu’s official Suricata PPA; other distros use different package names/paths).
- Root or sudo access.
- At least 2 CPU cores and 4 GB RAM — Suricata is multi-threaded and will use more resources under heavy traffic.
- A known network interface name to monitor (find it with
ip a), ideally a SPAN/mirror port, a tap, or the server’s live interface if you’re protecting that host directly. - Basic familiarity with
iptablesornftablesif you intend to deploy inline IPS mode (covered in Step 11). - Outbound internet access on the server to pull rule updates.
If you haven’t already locked down the host itself, it’s worth pairing this deployment with our guides on hardening a Linux server with CIS Benchmarks and Lynis and hardening SSH on Linux servers — a hardened host reduces the attack surface Suricata has to monitor in the first place.
How to Set Up Suricata IDS on Linux: Step-by-Step Deployment
Step 1: Update the system
sudo apt update && sudo apt upgrade -y
Ensures you’re not installing Suricata on top of outdated packages that could cause dependency conflicts. Verify with apt list --upgradable — it should return nothing critical outstanding.
Step 2: Add the official OISF Suricata PPA
sudo add-apt-repository ppa:oisf/suricata-stable -y
sudo apt update
This adds the maintained stable-release repository rather than relying on Ubuntu’s often-outdated default package. Verify it was added by checking /etc/apt/sources.list.d/ for a oisf-ubuntu-suricata-stable entry.
Step 3: Install Suricata
sudo apt install suricata -y
Installs the Suricata engine plus dependencies (libpcap, libnetfilter-queue, etc.). Verify the binary is present and check the version:
suricata -V
You should see output like This is Suricata version 7.x.x. If the command isn’t found, the PPA step likely failed — re-check Step 2.
Step 4: Confirm build capabilities
suricata --build-info
This one-line check confirms which features were compiled in — specifically look for NFQUEUE support (needed for IPS mode later) and AF_PACKET support (needed for IDS mode). If either is missing, you’ll need a source build with the relevant --enable- flag, which is outside the scope of a package install.
Step 5: Identify your monitoring interface
ip a
Note the interface name (e.g., eth0, ens160). This is the interface Suricata will capture packets from. If you’re monitoring traffic for other hosts (not just the box Suricata runs on), that interface must receive mirrored/SPAN traffic from your switch or a network tap — Suricata can only see what reaches its NIC.
Step 6: Configure the capture interface
Edit the main configuration file:
sudo nano /etc/suricata/suricata.yaml
Find the af-packet section and set your interface:
af-packet:
- interface: eth0
cluster-id: 99
cluster-type: cluster_flow
defrag: yes
This tells Suricata to use high-performance AF_PACKET capture on eth0. Verify the interface name matches exactly what ip a returned — a mismatch is the single most common reason Suricata "runs but sees nothing."
Step 7: Set your HOME_NET
In the same file, locate the vars section:
vars:
address-groups:
HOME_NET: "[192.168.1.0/24]"
EXTERNAL_NET: "!$HOME_NET"
Replace the CIDR with your actual internal network range. Many Suricata rules use $HOME_NET and $EXTERNAL_NET as variables to determine direction of traffic (inbound attack vs. outbound exfiltration) — getting this wrong silently breaks a large percentage of signatures.
Step 8: Install and run suricata-update
sudo apt install suricata-update -y 2>/dev/null; sudo suricata-update
suricata-update (bundled with recent Suricata releases) fetches the Emerging Threats Open ruleset by default and compiles it into /var/lib/suricata/rules/suricata.yaml-referenced rule files. Verify success by checking:
ls -la /var/lib/suricata/rules/
You should see suricata.rules with a recent timestamp and a non-trivial file size (several MB).
Step 9: Point Suricata to the updated ruleset
Confirm your suricata.yaml references the managed rules path:
default-rule-path: /var/lib/suricata/rules
rule-files:
- suricata.rules
This is the default in most package installs, but it’s worth confirming — a stale rule-files reference pointing at an empty or old file means Suricata loads zero real signatures.
Step 10: Validate the configuration before running
sudo suricata -T -c /etc/suricata/suricata.yaml -v
This runs Suricata in test mode — it loads the config and rules, checks for syntax errors, and exits without capturing traffic. Look for the line Configuration provided was successfully loaded at the end. If you see rule parse errors instead, they’ll reference the specific line/file — fix before proceeding.
Step 11: Start Suricata as a service
sudo systemctl enable --now suricata
sudo systemctl status suricata
Enables Suricata on boot and starts it immediately. Verify the service is active (running) with no immediate crash-loop in the status output.
Step 12: Verify detection with live traffic
Generate a known-bad request using a safe test domain designed for IDS validation:
curl http://testmyids.com
Then check the fast alert log:
sudo tail -f /var/log/suricata/fast.log
You should see an alert line referencing the ET rule for testmyids.com, something like:
[] [1:2100498:7] GPL ATTACK_RESPONSE id check returned root []
If nothing appears, check /var/log/suricata/eve.json for richer JSON-formatted event data — some environments log only to eve.json depending on the outputs section of suricata.yaml.

Step 13 (Optional): Convert to active IPS mode
By default, Suricata runs as a passive IDS — it logs and alerts but does not block. To actively drop malicious traffic, switch to inline NFQUEUE mode.
First, redirect traffic to the queue with iptables:
sudo iptables -I FORWARD -j NFQUEUE --queue-num 0
sudo iptables -I INPUT -j NFQUEUE --queue-num 0
This routes matched packets through Suricata before the kernel finishes processing them, giving Suricata the ability to drop packets inline.
Then update suricata.yaml to run in NFQ mode and set the default action:
nfq:
mode: accept
repeat-mark: 1
repeat-mask: 1
Restart Suricata explicitly using the NFQUEUE capture method:
sudo suricata -c /etc/suricata/suricata.yaml -q 0
Verify IPS is active by checking that a rule with drop action actually prevents the connection, not just logs it — pick or write a test rule with drop tcp any any -> any any (msg:"Test Drop Rule"; sid:9000001; rev:1;), reload rules, and confirm the matching connection is refused rather than just alerted on.
Common Pitfalls and Mistakes
Running Suricata on the wrong interface. If the interface doesn’t receive the traffic you care about (no SPAN/mirror configured), Suricata will run cleanly and detect nothing — not because it’s broken, but because it’s blind. Always confirm with tcpdump -i <interface> that traffic is actually visible before troubleshooting Suricata itself.
Leaving HOME_NET as the default placeholder. The out-of-the-box any or example CIDR in suricata.yaml causes many directional rules to behave unpredictably. Set it to your real internal range immediately after install.
Forgetting to re-run suricata-update after rule changes. Enabling/disabling rule categories (via enable-source / disable in /etc/suricata/update.yaml) has no effect until you run suricata-update again to recompile the rule set.
Deploying IPS mode without a rollback plan. Inline blocking can take down legitimate traffic if a signature misfires. Always test new rulesets in IDS (alert-only) mode first, review fast.log for false positives over a few days, then promote to IPS.
Under-provisioning CPU for a high-traffic link. Suricata’s packet capture and detection engine are CPU-intensive on busy networks. If ethtool -S <interface> or Suricata’s own stats show drops, you need more worker threads or a faster capture method (eBPF/XDP where supported).
Troubleshooting
Symptom: suricata -V returns "command not found"
The PPA wasn’t added correctly or apt update wasn’t re-run after adding it. Re-check Step 2 and confirm /etc/apt/sources.list.d/ contains the OISF entry.
Symptom: Service starts but immediately exits (systemctl status shows failed)
Run sudo suricata -T -c /etc/suricata/suricata.yaml -v to surface the exact config/rule parse error. The most common cause is a malformed YAML indentation (YAML is whitespace-sensitive) or a bad interface name.
Symptom: No alerts in fast.log despite generating test traffic
Confirm the interface is actually capturing packets with sudo tcpdump -i eth0 -c 10. If tcpdump sees nothing, the issue is network-level (no mirror/SPAN configured), not Suricata. If tcpdump sees traffic but Suricata doesn’t alert, check that the rule file is actually loaded with suricata --list-app-layer-protos and confirm rule-files points to a populated file.
Symptom: High packet drop rate under load
Check /var/log/suricata/stats.log for capture.kernel_drops. This indicates Suricata can’t keep up with the traffic volume. Increase af-packet threads (threads: auto or a specific count matching CPU cores) and consider enabling cluster-type: cluster_flow to better distribute load.
Symptom: IPS mode blocks legitimate traffic
Revert the default NFQUEUE action to accept immediately (sudo iptables -D FORWARD -j NFQUEUE --queue-num 0) to restore normal traffic flow, then review the triggering rule’s SID in fast.log, and either tune or disable it in /etc/suricata/update.yaml before re-enabling inline mode.
Conclusion
Suricata gives you a production-grade, free IDS/IPS that satisfies real compliance requirements (PCI DSS 11.4, NIST SP 800-94 alignment) without a licensing cost. The deployment path above — install, configure capture, pull rules, validate in IDS mode, then selectively promote to IPS — mirrors how security teams actually roll this out in production: detect first, tune against false positives, then block.
Next step: Once your IDS is stable and alerting accurately for a week or two, integrate eve.json output into a SIEM (Suricata natively supports JSON logging designed for this) so alerts don’t just sit in a log file — they reach someone who can act on them before the next Target-style incident becomes your incident. Pairing this with a regular internal vulnerability assessment closes the gap between detection and prevention even further.
Free Resources
- Suricata Official Documentation — authoritative configuration reference, rule syntax, and deployment guides maintained by OISF.
- Suricata GitHub Repository — source code, issue tracker, and release notes for every stable version.
- Emerging Threats Open Ruleset — the free, community-maintained signature feed used by
suricata-updatein this guide. - NIST SP 800-94: Guide to Intrusion Detection and Prevention Systems — the standards reference for IDS/IPS architecture and deployment decisions.