custom/nginx/conf/nginx-modsecurity.conf not applied by any build command — is this expected?

castris

Verified User
Joined
Apr 16, 2021
Messages
154
Location
Arcenillas
Hi everyone,

I manage a small fleet of DirectAdmin servers (6 servers, all nginx + ModSecurity 3.0.14 + OWASP CRS 4.22.0) and I'd really appreciate some guidance from the community or DA team on something I've run into. I'm not sure if I'm doing something wrong or if this is a gap in how CustomBuild handles this particular file.

Context — why we need to customize nginx-modsecurity.conf​


We take ModSecurity management seriously. Rather than just blanket-disabling rules when users report issues, we carefully craft targeted exclusions (per-domain, per-path, per-parameter) in 01_REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf. This allows us to keep the OWASP CRS protection intact for the vast majority of traffic while only relaxing specific rules where legitimate application behavior triggers false positives.

The problem is that we've had 3 incidents in 12 days where build update_versions left nginx completely down, taking all hosted websites offline. The root cause in each case involved ModSecurity/CRS configuration conflicts during the update process. One recurring issue is the SecDefaultAction directive: in certain scenarios after an update, the generated nginx-modsecurity.conf can contain a SecDefaultAction for phase:2 that conflicts with the one already defined in crs-setup.conf.main, causing:

Code:
nginx: [emerg] "modsecurity_rules_file" directive Rules error.
SecDefaultActions can only be placed once per phase and configuration context.
Phase 2 was informed already.

Our hardening plan​


To prevent this, we designed a simple hardening approach:

  1. Create a custom nginx-modsecurity.conf that explicitly includes SecRuleEngine On but omits SecDefaultAction (since CRS already defines it) — following the standard configure/custom/ pattern documented in the DA docs
  2. Add a post-update_versions hook for automatic detection and recovery
  3. Add a cron-based health check as an independent safety net

For step 1, we followed the ModSecurity documentation and the customize-everything guide:

Bash:
mkdir -p /usr/local/directadmin/custombuild/custom/nginx/conf/
cp /usr/local/directadmin/custombuild/configure/nginx/conf/nginx-modsecurity.conf \
   /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf
# Edit: added SecRuleEngine On, removed SecDefaultAction, added explanatory comments

The problem — custom file is never applied​


After creating the custom file, we tested every build command we could think of:

CommandResult
./build nginxRecompiled nginx, ran rewrite, but /etc/nginx/nginx-modsecurity.conf still matches configure/ template — custom ignored
./build rewrite_confsCompleted successfully — custom ignored
da build rewrite_confsCompleted successfully — custom ignored

In all three cases, the active file at /etc/nginx/nginx-modsecurity.conf remains identical to the default template at configure/nginx/conf/nginx-modsecurity.conf. Our custom file at custom/nginx/conf/nginx-modsecurity.conf is completely ignored.

We verified this with a clean test:

  1. Placed our custom file with a visible difference (SecRuleEngine On added on line 2, which the default template doesn't have)
  2. Restored the active file to match the default template
  3. Ran da build rewrite_confs
  4. Compared: active file = default template, custom file ignored

Environment​


  • DirectAdmin: 1.693
  • CustomBuild: current (as of 2026-02-17)
  • nginx: 1.29.4
  • ModSecurity: 3.0.14 (libmodsecurity3)
  • modsecurity3_nginx: 1.0.4
  • OWASP CRS: 4.22.0
  • OS: Ubuntu 22.04.5 LTS
  • Webserver mode: nginx (standalone, not nginx+apache)

Workaround​


For now we're manually copying the custom file to /etc/nginx/nginx-modsecurity.conf and we've added a post-update_versions hook that automatically restores it if a build overwrites it. This works, but it defeats the purpose of the custom mechanism.

Questions​


  1. Is custom/nginx/conf/nginx-modsecurity.conf supposed to be picked up by da build rewrite_confs? The docs suggest it should, but it doesn't seem to work in practice.
  2. Is there a different build command that handles this specific file? We've tried build nginx, build rewrite_confs, and da build rewrite_confs.
  3. Is this file perhaps regenerated by DirectAdmin's internal rewrite logic (bypassing the custom/ mechanism entirely)?

We'd love to use the standard CustomBuild mechanism instead of our manual workaround. Any pointers from the community or the DA team would be greatly appreciated.

Thanks in advance!
 
Back
Top