castris
Verified User
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.
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
The problem is that we've had 3 incidents in 12 days where
To prevent this, we designed a simple hardening approach:
For step 1, we followed the ModSecurity documentation and the customize-everything guide:
After creating the custom file, we tested every build command we could think of:
In all three cases, the active file at
We verified this with a clean test:
For now we're manually copying the custom file to
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!
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:
- Create a custom
nginx-modsecurity.confthat explicitly includesSecRuleEngine Onbut omitsSecDefaultAction(since CRS already defines it) — following the standardconfigure/→custom/pattern documented in the DA docs - Add a post-update_versions hook for automatic detection and recovery
- 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:
| Command | Result |
|---|---|
./build nginx | Recompiled nginx, ran rewrite, but /etc/nginx/nginx-modsecurity.conf still matches configure/ template — custom ignored |
./build rewrite_confs | Completed successfully — custom ignored |
da build rewrite_confs | Completed 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:
- Placed our custom file with a visible difference (
SecRuleEngine Onadded on line 2, which the default template doesn't have) - Restored the active file to match the default template
- Ran
da build rewrite_confs - 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
- Is
custom/nginx/conf/nginx-modsecurity.confsupposed to be picked up byda build rewrite_confs? The docs suggest it should, but it doesn't seem to work in practice. - Is there a different build command that handles this specific file? We've tried
build nginx,build rewrite_confs, andda build rewrite_confs. - 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!