For an nginx you manage yourself.
EdgeGuard does not need Artica. The agent runs beside any nginx, on any distribution, and pulls its policy from the same console. This page is what to put in that nginx and how to tell it is working.
It reads requests and answers allow or refuse, through a Unix socket. That is all.
It does not write, rewrite or reload your nginx configuration. On an Artica appliance the agent regenerates vhosts from Artica's own site definitions; on your nginx it does not, because that configuration is yours. From engine 3.0.62 the agent says so once at startup rather than leaving you to wonder:
Running without Artica's reverse-proxy, so nginx vhosts are not regenerated
That line is correct and expected. It is not a warning.
Run the installer on the machine that runs nginx and choose Agent:
sudo ./install.sh
It asks what the machine is, then for the central URL and the agent key you
create on the Agents page. If no engine
binary is bundled it downloads the published one and checks it against the
published sha256 before installing it.
Valkey or Redis has to be there first. The agent keeps rate-limit
counters and sessions in it and exits at startup if it cannot connect, so the
installer checks before installing anything and names the package for your
distribution. The in-memory alternative works on a single node and is wrong for
a cluster, because each node would then count on its own.
http { } — once per nginxload_module modules/ngx_http_security_module.so; # at the TOP of nginx.conf, outside http{}
http {
security_engine_socket /run/artica-edgeguard/engine.sock;
security_engine_timeout 50; # milliseconds; default 50
security_pool_size 16; # pooled connections to the engine; default 16
}
These three are main-context only. Putting them inside a server { } block is a configuration error, and it is the mistake most often made.
security_engine_socket has no default. Without it the module logs security: socket path not configured and lets every request through.
server { } you want protectedserver {
server_name www.example.com;
security_check on; # OFF unless you write this
security_tenant_id 7; # the tenant's id in the console
# Optional, with their defaults:
# security_fail_mode open; # open = serve if the engine is down
# security_cache on;
# security_body_preview_size 8k;
}
security_checkis off until you switch it on. An agent can be installed, running, green in the console and examining nothing, because no server block ever asked it to. This is the single most common reason a new install sees no events.
security_tenant_id must match the tenant's id on the Tenants page. Traffic reported under the wrong id lands in another site's statistics and is judged by another site's policy.
security_modsec_score_var $modsec_anomaly_score;
EdgeGuard's handler is registered to run after ModSecurity, so it can read the CRS anomaly score and combine it with its own. Without this directive the two engines simply decide separately.
The engine creates the socket at mode 0660 and hands it to the user nginx runs as. It has to be the right user or nginx cannot open it at all.
From engine 3.0.59 this is detected: the first of www-data, nginx, http, nobody that exists on the machine wins — www-data first, so a Debian or Ubuntu install is unchanged. That covers Debian, Ubuntu, RHEL, Rocky, Alma, Fedora, SUSE, Arch and Alpine.
If your nginx runs as something else, say so in the agent's config.json:
{ "socket_owner": "myuser", "socket_group": "myuser" }
If the handover fails, the agent reports it on its next heartbeat and the console says which user and group it tried. It is an error, not a warning, because nginx being unable to open the socket means nothing is examined at all.
On the Agents page, the NGINX MODULE column is the only one that answers this. STATUS says the agent is talking to the console; it says nothing about whether nginx is talking to the agent.
| What you see | What it means |
|---|---|
a version, e.g. 1.0.0 |
nginx is consulting the agent — it is working |
| not consulting | no request has ever reached the agent from nginx |
| a version plus no recent request | it was being consulted, and nothing for over six hours |
A green agent with not consulting means your traffic is being served without being examined. Three things cause it, in the order worth checking:
nginx -V should list it, and nginx -T should show the load_module line.security_check is not on for that server block.There is a script for this, and it is the recommended path. It reads this machine's nginx -V, fetches that exact source, replays that exact configure line, builds, checks what the result depends on, installs it, and asks nginx to load it before declaring success. It does not touch nginx.conf — at the end it prints what to add.
sudo ./install-module.sh
It stops before doing anything if the compiler or the development headers are missing, and names the packages. If nginx refuses the module it removes it again and restores whatever was there before.
The rest of this section is what the script does, for anyone who would rather do it by hand or needs to understand a failure.
A dynamic module loads only into an nginx whose module signature matches its own. That signature is built from the nginx version and from the build-time features, so the rule has no exceptions: compile against the same nginx version, with the same configure arguments. nginx -V prints both.
--with-compat?nginx -V 2>&1 | grep -o -- --with-compat
This decides which of two recipes applies, and getting it wrong produces a .so that nginx refuses with "module is not binary compatible".
--with-compat arrived in nginx 1.11.5. It normalises the signature so a module built elsewhere can load — but only when the nginx you are loading into was itself built with it. It is not something you simply add to your own build.
Distributions differ, and not in the way you would guess:
| nginx | --with-compat |
|
|---|---|---|
| Debian 9 (stretch) | 1.10.3 | no — predates the option |
| Debian 10 (buster) | 1.14.2 | no — the option exists, the package does not use it |
| Debian 12 (bookworm) | 1.22.1 | yes |
| anything else | — | check with the command above |
--with-compatThe easy case. The signature is normalised on both sides, so you need the right version and nothing else from its configure line — none of its paths, modules or compiler flags matter.
cd /path/to/nginx-source # the SAME version as nginx -V reports
./configure --with-compat --add-dynamic-module=/path/to/ngx_http_security_module
make modules
Reuse its own configure line verbatim and add ours. Nothing may be dropped: --with-debug and the --with-cc-opt string are part of the signature too, and --with-cc-opt='...' is a single argument that must stay in one piece.
One thing must be removed: the distribution's own --add-dynamic-module arguments. They point inside the build machine's tree — on Debian, paths like /build/nginx-m1Thpq/nginx-1.14.2/debian/modules/http-auth-pam — which exist nowhere else, so configure stops at the first one. Removing them is safe: the signature records build-time features and type sizes, not which modules were added.
cd /path/to/nginx-source # the SAME version as nginx -V reports
./configure <every argument from nginx -V, minus --add-dynamic-module=...> \
--add-dynamic-module=/path/to/ngx_http_security_module
make modules
cp objs/ngx_http_security_module.so /etc/nginx/modules/
nginx -t && systemctl reload nginx
"module is not binary compatible" means the signature did not match: a different nginx version, a missing configure argument, or
--with-compaton one side and not the other. It is never a problem with the module's code, and rebuilding with the exact line fromnginx -Vfixes it.
The build looks for ModSecurity and tells you which variant it made:
EdgeGuard: building WITHOUT ModSecurity (none found at /usr/local/modsecurity)
The CRS anomaly score still reaches the engine through
security_modsec_score_var if you run ModSecurity separately.
Until now it always linked libmodsecurity and referenced the ModSecurity-nginx connector, and either one stops the module loading on a machine that does not run ModSecurity — ld.so refuses the file before nginx can look at it. That is why the module would not install beside an nginx from apt or yum.
| Setting | Effect |
|---|---|
EDGEGUARD_MODSEC=0 |
never link it |
EDGEGUARD_MODSEC=1 |
require it, and fail at build time rather than at load time |
| unset | look for it, and say what was found |
MODSEC_PREFIX=/path |
where ModSecurity lives; default /usr/local/modsecurity |
A build without ModSecurity loses one shortcut — reading the anomaly score straight out of the transaction — and keeps the feature, because security_modsec_score_var reads the same number from an nginx variable.