Getting Started
From an empty console to a site in blocking mode, in the order the product actually requires: the site first, then the agent that protects it.
From nothing to a protected site, in the order that will not break it. This page is the path through the other ten: install an agent, add a site, watch before blocking, read what you see, then turn protection on.
The whole route takes about an hour of work and a week of waiting — and the waiting is the part that matters. A WAF switched straight to blocking on an application nobody has observed is how a site loses customers on a Monday morning.
Before you start
- The console (EdgeGuard Central) reachable on
https://<address>:8082. - An nginx reverse proxy with the EdgeGuard module, in front of the application you want to protect.
- An administrator account on the console; if MFA is enabled, your enrolment done.
1. Create the site
Configuration → Tenants → Add Tenant: pick the group it belongs to, give it a name and its domain.


A site inherits everything from its group, which inherits from the global settings. You have not configured anything yet, and that is correct: the defaults are a working policy.
The site comes first, and the order matters. An agent has to be given at least one site when it is created — an agent that protects nothing would run and examine nothing — so there is nothing useful to create before this.
2. Register the agent
The agent is the decision engine that sits next to nginx.
- Infrastructure → Agents → Add Agent.
- Name it for the machine it runs on —
Production Agent 1, notagent2. - Tick the site you just created. At least one is required.
- Say where it runs. On an nginx we manage ourselves hands you a one-line install command with the address and a one-time password already in it.
- Create, and run that command on the machine.
- Within about half a minute the agent appears as active.


Full detail: Agents and, for an nginx you run yourself, Install EdgeGuard on a standalone nginx.
3. Turn it on in learning mode
This is the step people skip, and the one that decides whether the rest goes well.
Global Settings → General → WAF Operating Mode → Learning (detect only, no blocking) — or set it on the site alone, if the rest of the estate is already in blocking mode.
In learning mode EdgeGuard inspects everything and blocks nothing. Every decision it would have made is recorded, with its score and the rules that fired.

Leave it here for at least a few days of ordinary traffic — including whatever runs at the weekend, and the batch jobs nobody remembers. You are not waiting for the product; you are waiting for your application to show you its habits.
4. Read what it found
After a few days, four pages answer four questions:
| Question | Page |
|---|---|
| What has been happening? | Reports → Daily summary — one page per day, exportable |
| What exactly was decided, and why? | Traffic → Security Events — open any row for the rules and what they matched on |
| Which rules are costing me false positives? | Traffic → Analytics → Performance & quality, the False Positive Rate Estimate table |
| Is anything already being suppressed for me? | Protection → False Positives, lower table |
Work through the events that would have been blocked. For each one, decide: was it an attack, or was it your application?
- An attack → nothing to do; it will be blocked when you switch modes.
- Your application → fix it now, with the narrowest instrument that works: a false-positive exclusion for one rule on one field, a path rule for one endpoint, and only then anything wider.
5. Add the cheap protections
These cost nothing to get right and stop a great deal of noise:
- Bot Management — allow the crawlers you want, with reverse-DNS verification so a spoofed User-Agent gains nothing.
- Rate Limits — a low allowance on the login endpoint, a generous one elsewhere.
- IP Lists — your own monitoring addresses, if they need to bypass challenges. Use expiries.
- Response Pages — at minimum set the branding, and make sure the page shows the EdgeGuard ID. Your support desk will need it on the first day of blocking.
6. Switch to blocking
When the events for a normal week contain nothing you would be sorry to refuse:
Global Settings → General → WAF Operating Mode → Blocking, or on the one site.
Then watch the same four pages for a day. The first hours of blocking are when a missed false positive shows itself, and undoing one is a minute's work: the event that was refused carries Mark false positive and Create rule from event in its detail panel.
6a. Prove it, in both directions
A WAF that refuses everything is not passing a test, it is failing it the other
way round. So the check is a pair of questions, always: is the attack refused,
and does ordinary traffic still arrive.
The appliance ships the run:
./tools/waf-selftest.sh https://your-site.example
Ten cases against a site you are responsible for. Six attacks that must be
refused, and four that answer the other half of the question:
| SQLi in a query parameter | refused — the shape sqlmap sends |
| Error-based SQLi | refused |
| Command injection in a urlencoded body | refused |
| Command injection in a multipart body | refused — over 400 characters, to exercise the evidence store |
| Path traversal | refused |
| A clean request | arrives |
The PHP_SESSION_UPLOAD_PROGRESS field |
refused — see PHP2Shell |
| That field's name as a value | arrives |
| English prose containing "update … where" | arrives |
| Real SQL injection in that same field | refused |
The last four are two pairs, and the pairing is the point.
The field, and its name. A rule that refused any request mentioning
PHP_SESSION_UPLOAD_PROGRESS would refuse the ticket quoting it, the advisory
describing it and the engineer pasting it into a search box. If the first of
that pair is refused and the second is too, the rule has regressed from reading
parameter names to reading the request body — and the first case on its own
looks identical either way.
The prose, and the payload. In October 2026 a real support ticket was
refused as SQL injection because its text contained "update … where". The rule
responsible was called SQL Injection Attack Detected via libinjection and was
in fact a keyword pair — (select|insert|update|…).*(from|into|set|where|…) —
which half of ordinary correspondence matches. It is a genuine semantic
detector now. The guard against its return is the prose case; but prose passes
just as well against a body the engine never reads at all, so the fourth case
sends real injection in the same field. Together they say the field is
inspected and ordinary writing survives it. Separately, neither says
anything.
Reading the result
A refusal carries an EdgeGuard ID; open it in Traffic → Security
Events and check three things on the multipart case:
- param names the form field,
payload, and not the multipart envelope
it arrived in. - Matched text carries the whole field rather than stopping short of it.
The multipart case sends a payload of over 400 characters and the event
stores 557 — all of it. It is shortened on screen with a control to show the
rest, and Copy takes the whole value. A version before 2.3.9 cut this at
160 characters and the remainder was never stored at all, so what an
operator read was a fragment of the evidence with nothing saying so. - Sensitive fields are withheld. Where a value would be shown for a field
like the upload-progress one, the event reads
(value withheld: sensitive parameter)instead. The decision is on the
field's name, so a password field is never copied into an event even when a
rule fires on it.

If every case fails, including the clean request, the requests are being
stopped before any payload is looked at. Check the event's rule: it will be
Bad Bot, a firewall rule or geo-blocking rather than an injection rule. The
script sends a browser's headers for exactly this reason — curl/8.x announces
itself and bot detection refuses it on that alone, at which point every case
comes back 403 for a reason that has nothing to do with what it was carrying.
7. Settle in
Once it is quiet, three habits keep it that way:
- The bell. It carries what needs a person — learned rules waiting, exclusions nobody uses, agents that stopped reporting. It is deliberately not a feed of blocks.
- The daily summary. Two minutes a morning; it is the record of what was handled while you were not looking.
- A quarterly tidy. Sort exclusions by Allowed and remove the ones that have never allowed anything; check the VERSION column on Agents; look at Silent in this window in Analytics before adding any new rule.
8. When the traffic has settled: learned rules
After a fortnight of steady traffic, Protection → Learned Rules begins proposing rules built from your own application's habits — "user_id is always a whole number of 1 to 6 digits". Accepting one only measures it; it blocks nothing until you have the evidence and say so.
Full detail: Learned Rules.
The order everything is decided in
Worth knowing once, because it explains most surprises:
- Path rule action override
- IP lists — allowlist, then blocklist
- Threat intelligence
- Geo blocking
- Firewall rules
- Behavioural analysis, bot detection, browser integrity
- Rate limits
- Managed rulesets, custom rulesets and learned rules
An earlier step ends the request. So an allowlisted address is never inspected, a firewall Allow skips every detection that follows it, and a rule you expected to fire may simply never have been reached.
Where to go next
| The console, screen by screen | Dashboard Guide |
| Your own block/allow/challenge rules | Firewall Rules |
| The detection rules and how scoring works | Rules & Rulesets |
| Recording a rule that was wrong | False Positives |
| Rules learned from your traffic | Learned Rules |
| Addresses, limits, bots, paths, pages | IP Lists · Rate Limits · Bot Management · Path Rules · Response Pages |
| The fleet | Agents · Threat Intelligence |