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

castris

Verified User
Joined
Apr 16, 2021
Messages
157
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!
 
Hi
try using rewrite_conf hook to copy file to write place.
try this.

firs creat a Folder whit this command

mkdir -p /usr/local/directadmin/custombuild/custom/hooks/rewrite_conf/post

in Folder creat a file copy.sh and edit it

nano /usr/local/directadmin/custombuild/custom/hooks/rewrite_conf/post/copy.sh

in the file copy.sh paste copy the following codes
#! /bin/bash

cp /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf /etc/nginx

systemctl restart nginx

and make the file copy.sh executable
chmod +x /usr/local/directadmin/custombuild/custom/hooks/rewrite_conf/post/copy.sh

now wenn you run ./build rewrite_confs or da build rewrite_confs commands
rewrite_conf will started and befor ending it will started your cods in copy.sh
this will copy the file from /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf
to /etc/nginx and it will overwrite file and nginx will restared

you will also see in the terminal end of ./build rewrite_confs or da build rewrite_confs commands runs
Executing '/usr/local/directadmin/custombuild/custom/hooks/rewrite_confs/post/copy.sh'...
+++ cp /usr/local/directadmin/custombuild/custom/hooks/rewrite_conf/post/copy.sh /etc/nginx
+++ systemctl restart nginx

hope this helps
 
[...]

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)?
[...]
1. Well, yes. I tried to customize it and it worked as expected.
2.
Code:
da build modsecurity
could also do that, but it would take even longer, as it additionally recompiles nginx.
3. I don't think so.

As today a new version was released, I do not have 1.693 to test, but the 1.694 worked as expected.
Have you tried contacting DA support regarding this matter? That file should be customizable.
 
Thank you both for the replies!

Sorry for the delay in the response but these days have been very complex with the advances in massive attacks on Magento/Prestahop and others, which I imagine will increase with the appearance of prompt kiddies

@Hostmavi


That's essentially what we ended up doing. We have a post/verify_nginx.sh hook in update_versions/post/ that restores the custom file if it was overwritten, and also handles the full recovery scenario (disable ModSecurity → rebuild CRS → re-enable). Your suggestion of a simpler rewrite_conf/post/copy.sh is a nice lightweight alternative for the file copy part. Thanks!

@nsc


Appreciate you testing! I went ahead and also tried da build modsecurity as you suggested. Unfortunately, same result on our end — custom file ignored:

Bash:
# Clean test on DA 1.694 (we've updated since the original post)
da version
# DirectAdmin 1.694 add7b69d661933b9aa833960177b02d5c12ea924

# 1. Restore default template to active location
cp /usr/local/directadmin/custombuild/configure/nginx/conf/nginx-modsecurity.conf \
   /etc/nginx/nginx-modsecurity.conf

# 2. Verify custom file exists and differs (has SecRuleEngine On on line 2)
head -3 /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf
# Default recommended configuration
# SecRuleEngine On          ← this line is our custom addition
# SecRequestBodyAccess On

# 3. Run da build modsecurity
da build modsecurity

# 4. Check result
diff /usr/local/directadmin/custombuild/custom/nginx/conf/nginx-modsecurity.conf \
     /etc/nginx/nginx-modsecurity.conf
# 2d1
# < SecRuleEngine On
# ...
# → DIFFERENT — custom was ignored

So on our setup (also 1.694 now), none of these four commands apply the custom:

CommandCustom applied?
./build nginxNo
./build rewrite_confsNo
da build rewrite_confsNo
da build modsecurityNo

I wonder if there's something environment-specific at play. For reference, our setup is nginx standalone (not nginx+apache), Ubuntu 22.04, ModSecurity3 3.0.14. Could the custom mechanism perhaps work differently depending on the webserver mode (nginx standalone vs nginx_apache)?

I'll open a support ticket as you suggested. In the meantime, the hook-based workaround is solid enough for production.
 
Thank you both for the replies!

@Hostmavi


That's essentially what we ended up doing. We have a post/verify_nginx.sh hook in update_versions/post/ that restores the custom file if it was overwritten, and also handles the full recovery scenario (disable ModSecurity → rebuild CRS → re-enable). Your suggestion of a simpler rewrite_conf/post/copy.sh is a nice lightweight alternative for the file copy part. Thanks!

@nsc


Appreciate you testing! I also tried da build modsecurity — same result on our end, custom ignored. Since it works for you, I suspect this might be webserver-mode specific. Our servers all use webserver=nginx (standalone), not nginx_apache. Could that be the difference?

Update — support ticket​


Following nsc's advice, I opened a support ticket. Roman is already looking into it and asked for the exact custom file content and more details about the SecDefaultAction conflict. Really appreciate the quick response from the DA team.

I'll post back here once we have a resolution — might be useful for others running nginx standalone with ModSecurity.
 
Back
Top