Wazuh Rule Tuning Automation Approval-Gated n8n Workflow, 81 Nodes

2026-08-13 · Neetrox

Every Wazuh operator knows the feeling. You open the alerts view and the same three rules have fired ten thousand times between them. A single scanner tripping an sshd rule. Active-response block and unblock events, back to back, all night. A certbot lock file setting off file-integrity monitoring on every renewal.

None of it is a threat. All of it is buried on top of the alerts that are.

You know the fix. Write a small exception rule, give it a safe ID, test it with logtest, make sure you didn't break something else, restart the manager. Fifteen minutes of fiddly work per rule, work that never makes it to the top of the queue. So the noise stays, and it keeps hiding the signal.

I got tired of it. But every “automatic rule tuning” idea I sketched had the same problem: I did not want a script rewriting my detection ruleset on its own judgment. Lowering a rule’s level or adding an exception is a security decision. Get it wrong and you go blind to something that matters.

So I built the thing I actually wanted: an assistant that does all the tedious work, and then stops and asks.

What it does

The Wazuh rule tuning workflow open in n8n, two long rows of connected nodes annotated with orange sticky notes

It’s one n8n workflow. Every night it:

  1. Profiles the noise. One aggregation query against the Wazuh Indexer pulls the loudest rules over the last week with the concentration behind each one. Not just “rule 5710 fired 980 times,” but “92% of it came from one source IP.” That context is what tells you whether it’s noise or an attack.

  2. Asks a local LLM for a fix. Running on Ollama, so your logs never leave your network. The model proposes one of four things: a CDB list for a set of noisy IPs or users, a child exception for a specific benign pattern, a level override for a rule that doesn’t apply to your environment or, often, “no action, that’s real activity, leave it alone.”

  3. Proves the suggestion before I ever see it. This is the part that makes it usable. Every proposal runs a gauntlet of plain code, no AI trust involved. Does the new rule ID collide with an existing one? Is it in the reserved custom range? Is the XML made only of allowed elements? Is it trying to touch a decoder, or delete a rule, or filter on the agent side? Anything that fails is dropped, with the reason logged. Then each survivor is run through the Wazuh logtest API against my real ruleset. What reaches me has already been checked twice.

  4. Sends me a report. In Discord, though you can wire it to anything. The noise, the proposals that passed, what got dropped and why, and a separate list of “dead rules” rules that used to fire and have gone silent, which usually means a broken log source, not noise. Those it reports and never touches.

On a quiet week it tells me there’s nothing worth tuning, and I close it. That’s the point.

Get the Wazuh Rule Tuner →

Video Demo

The part I actually care about

The workflow can write to my production ruleset. Everything about how it’s built is aimed at making that safe.

It ships inert. The default mode is report-only. It analyzes and proposes and writes nothing. You have to deliberately change one setting to let it touch anything.

The AI never gets the last word. Its job is to suggest. The code guard and the live logtest decide what's even valid, and I decide what actually happens.

Applying takes two human clicks. When I approve a change, the link in Discord does not apply it. It opens a confirmation page showing the exact XML that would be written, and a button. Only the button acts. This matters more than it sounds: the first version I built used a plain link, and Discord’s link-preview crawler “clicked” every approve link the moment the message posted, auto-approving five changes before I touched anything. A confirmation page with a real form fixes that completely. Crawlers and browser prefetch render pages; they don’t submit forms.

Every change is reversible. Before it writes, it backs up the current rules file. Right after, it re-runs logtest the ruleset has to still load cleanly, and two known events have to still resolve to their original rules. If either check fails, it re-uploads the backup automatically and tells me it rolled back. My ruleset ends up exactly where it started.

It never restarts the manager. A successful change writes the file and reminds me to restart Wazuh myself. Nothing goes live until I decide it does.

Why not just let it run

Because tuning is a judgment call, and judgment is exactly what you should not fully automate in a detection pipeline. The value here isn’t “AI fixes your rules.” It’s “the boring 90% is done for you, the reading, the ID-picking, the XML, the logtest so the only thing left is the 10% that needs a human: looking at one clear proposal and saying yes or no.”

That’s a trade I’ll take every night. It turns rule tuning from a task I avoid into a thirty-second decision over coffee.

What it needs

Two things, really: the Wazuh Manager API and the Wazuh Indexer, both of which every Wazuh install already has. Plus an Ollama endpoint for the proposals and a Discord webhook for the reports. No database, no Git, no SSH, no agent, no extra infrastructure. It imports as a single file and configures from one node. About twenty minutes to your first report.

If you run Wazuh

I packaged this as a product, the workflow, a setup guide, a full configuration reference, and sample output. It’s licensed for a single organization, so you can run it on your own estate or for your clients as a managed service.

If your Wazuh console is louder than it should be, and you’ve been putting off tuning because doing it safely is tedious, this is the shortcut that doesn’t cut the safety.

Get the Wazuh Rule Tuner →

← Back to blog