git: 379784574f45 - main - www/bunkerweb: Enable ModSecurity when the module is available

From: Jochen Neumeister <joneum_at_FreeBSD.org>
Date: Thu, 24 Sep 2026 15:02:51 UTC
The branch main has been updated by joneum:

URL: https://cgit.FreeBSD.org/ports/commit/?id=379784574f45e219b4e85fa06e658ea8c825dc7a

commit 379784574f45e219b4e85fa06e658ea8c825dc7a
Author:     Jochen Neumeister <joneum@FreeBSD.org>
AuthorDate: 2026-09-24 15:01:56 +0000
Commit:     Jochen Neumeister <joneum@FreeBSD.org>
CommitDate: 2026-09-24 15:02:41 +0000

    www/bunkerweb: Enable ModSecurity when the module is available
    
    Render the ModSecurity directives only if
    ngx_http_modsecurity_module.so is installed, like upstream does for
    the stream module. Build www/openresty with the MODSECURITY option to
    get it.
    
    Point the remaining paths at their FreeBSD locations, error pages,
    assets and rule files were read from /usr/share/bunkerweb.
    
    Sponsored by:   Netzkommune GmbH
---
 www/bunkerweb/Makefile                             |  2 +-
 ...patch-src_common_confs_default-server-http.conf | 21 ++++--
 .../files/patch-src_common_confs_nginx.conf        | 10 ++-
 ...mon_core_antibot_confs_server-http_antibot.conf | 11 +++
 ...re_errors_confs_default-server-http_errors.conf | 13 ++--
 ...ommon_core_errors_confs_server-http_errors.conf | 31 ++++++--
 ...rc_common_core_grpc_confs_server-http_grpc.conf |  6 +-
 ...n_core_misc_confs_default-server-http_page.conf | 11 +++
 ...s_http_modsecurity-rules-global-crs.conf.modsec | 53 ++++++++++++++
 ...on_core_modsecurity_confs_http_modsecurity.conf | 12 ++--
 ...r-http_modsecurity-rules-global-crs.conf.modsec | 18 +++++
 ...confs_server-http_modsecurity-rules.conf.modsec | 84 ++++++++++++++++++++++
 ..._modsecurity_confs_server-http_modsecurity.conf | 15 ++--
 ...rc_common_core_mtls_confs_server-http_mtls.conf | 13 ++++
 ..._common_core_mtls_confs_server-stream_mtls.conf | 13 ++++
 ...verseproxy_confs_server-http_reverse-proxy.conf | 10 ++-
 ..._securitytxt_confs_server-http_securitytxt.conf | 11 +++
 ...ommon_core_ui_confs_default-server-http_ui.conf | 42 +++++++----
 .../files/patch-src_common_gen_Templator.py        | 21 +++++-
 19 files changed, 342 insertions(+), 55 deletions(-)

diff --git a/www/bunkerweb/Makefile b/www/bunkerweb/Makefile
index 34461f646613..d2dead141fc1 100644
--- a/www/bunkerweb/Makefile
+++ b/www/bunkerweb/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	bunkerweb
 DISTVERSION=	1.6.15
-PORTREVISION=	0
+PORTREVISION=	1
 CATEGORIES=	www security
 
 MAINTAINER=	joneum@FreeBSD.org
diff --git a/www/bunkerweb/files/patch-src_common_confs_default-server-http.conf b/www/bunkerweb/files/patch-src_common_confs_default-server-http.conf
index df549ad34660..9a3a6063a099 100644
--- a/www/bunkerweb/files/patch-src_common_confs_default-server-http.conf
+++ b/www/bunkerweb/files/patch-src_common_confs_default-server-http.conf
@@ -1,6 +1,6 @@
---- src/common/confs/default-server-http.conf.orig	2026-05-25 18:23:18 UTC
+--- src/common/confs/default-server-http.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/confs/default-server-http.conf
-@@ -45,7 +45,7 @@ server {
+@@ -45,7 +45,7 @@
  	{% endif %}
  	ssl_ecdh_curve {{ resolve_ssl_ecdh_curve(SSL_ECDH_CURVE) }};
  	{% if "TLSv1.2" in SSL_PROTOCOLS +%}
@@ -9,7 +9,7 @@
  		{% if SSL_CIPHERS_CUSTOM != "" %}
  	ssl_ciphers {{ SSL_CIPHERS_CUSTOM }};
  		{% else %}
-@@ -61,7 +61,6 @@ server {
+@@ -61,7 +61,6 @@
  	ssl_certificate /var/cache/bunkerweb/misc/default-server-cert.pem;
  	ssl_certificate_key /var/cache/bunkerweb/misc/default-server-cert.key;
  	{% if HTTP2 == "yes" %}
@@ -17,7 +17,7 @@
  	{% endif %}
  	{% set common_options = " ssl default_server" %}
  	{% if USE_PROXY_PROTOCOL == "yes" %}
-@@ -75,14 +74,10 @@ server {
+@@ -75,14 +74,10 @@
  	{% endfor %}
  
  	{% if "TLSv1.3" in SSL_PROTOCOLS and HTTP3 == "yes" and USE_PROXY_PROTOCOL == "no" %}
@@ -32,7 +32,16 @@
  	{% endif %}
  
  	ssl_client_hello_by_lua_block {
-@@ -233,10 +228,10 @@ server {
+@@ -178,7 +173,7 @@
+ 		add_header Last-Modified "";
+ 		server_tokens off;
+ 		default_type 'text/html';
+-		root /usr/share/bunkerweb/loading;
++		root /usr/local/share/bunkerweb/bw/loading;
+ 		content_by_lua_block {
+ 				local utils = require "bunkerweb.utils"
+ 				local rand = utils.rand
+@@ -236,10 +231,10 @@
  {% endif %}
  
  	# include core and plugins default-server configurations
@@ -41,7 +50,7 @@
  
  	# include custom default-server configurations
 -	include /etc/bunkerweb/configs/default-server-http/*.conf;
-+	include /usr/local/etc/bunkerweb/configs/default-server-http/*.conf;
++	include /usr/local/usr/local/etc/bunkerweb/configs/default-server-http/*.conf;
  
  	log_by_lua_block {
  
diff --git a/www/bunkerweb/files/patch-src_common_confs_nginx.conf b/www/bunkerweb/files/patch-src_common_confs_nginx.conf
index 1e2918d0edb6..f01714be4fc7 100644
--- a/www/bunkerweb/files/patch-src_common_confs_nginx.conf
+++ b/www/bunkerweb/files/patch-src_common_confs_nginx.conf
@@ -1,6 +1,6 @@
---- src/common/confs/nginx.conf.orig	2026-05-25 18:23:18 UTC
+--- src/common/confs/nginx.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/confs/nginx.conf
-@@ -1,27 +1,15 @@
+@@ -1,27 +1,19 @@
 -# /etc/nginx/nginx.conf
 +# /usr/local/etc/nginx/nginx.conf
  
@@ -23,6 +23,10 @@
 -load_module /usr/share/bunkerweb/modules/ngx_stream_lua_module.so;
 -load_module /usr/share/bunkerweb/modules/ngx_http_lua_upstream_module.so;
  
++{% if has_modsecurity +%}
++load_module /usr/local/nginx/modules/ngx_http_modsecurity_module.so;
++{% endif %}
++
  {% if os.uname().sysname == "FreeBSD" -%}
  # run workers as the dedicated BunkerWeb account
 -user nginx;
@@ -30,7 +34,7 @@
  {% endif %}
  
  # PID file
-@@ -66,22 +54,22 @@ http {
+@@ -66,22 +58,22 @@
  
  http {
  	# include base http configuration
diff --git a/www/bunkerweb/files/patch-src_common_core_antibot_confs_server-http_antibot.conf b/www/bunkerweb/files/patch-src_common_core_antibot_confs_server-http_antibot.conf
new file mode 100644
index 000000000000..1ecd0b6313c9
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_antibot_confs_server-http_antibot.conf
@@ -0,0 +1,11 @@
+--- src/common/core/antibot/confs/server-http/antibot.conf.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/antibot/confs/server-http/antibot.conf
+@@ -1,7 +1,7 @@
+ {%+ if USE_ANTIBOT != "no" -%}
+ location {{ ANTIBOT_URI }} {
+     default_type 'text/html';
+-    root /usr/share/bunkerweb/core/antibot/files;
++    root /usr/local/share/bunkerweb/common/core/antibot/files;
+     content_by_lua_block {
+         local logger   = require "bunkerweb.logger":new("ANTIBOT")
+         local helpers  = require "bunkerweb.helpers"
diff --git a/www/bunkerweb/files/patch-src_common_core_errors_confs_default-server-http_errors.conf b/www/bunkerweb/files/patch-src_common_core_errors_confs_default-server-http_errors.conf
index f1c53fab2bb3..b3521bfb2d9b 100644
--- a/www/bunkerweb/files/patch-src_common_core_errors_confs_default-server-http_errors.conf
+++ b/www/bunkerweb/files/patch-src_common_core_errors_confs_default-server-http_errors.conf
@@ -1,10 +1,15 @@
---- src/common/core/errors/confs/default-server-http/errors.conf.orig	2026-05-25 18:23:18 UTC
+--- src/common/core/errors/confs/default-server-http/errors.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/errors/confs/default-server-http/errors.conf
-@@ -8,7 +8,6 @@ location {% if intercepted_error_code == "400" %}= /{%
+@@ -8,9 +8,11 @@
  location {% if intercepted_error_code == "400" %}= /{% else %} @{% endif %}bwerror{{ intercepted_error_code }} {
      auth_basic off;
      internal;
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      default_type 'text/html';
-     root /usr/share/bunkerweb/core/errors/files;
+-    root /usr/share/bunkerweb/core/errors/files;
++    root /usr/local/share/bunkerweb/common/core/errors/files;
      content_by_lua_block {
+         local logger = require "bunkerweb.logger"
+         local cerrors = require "errors.errors"
diff --git a/www/bunkerweb/files/patch-src_common_core_errors_confs_server-http_errors.conf b/www/bunkerweb/files/patch-src_common_core_errors_confs_server-http_errors.conf
index bd77464c4a99..762d4f352134 100644
--- a/www/bunkerweb/files/patch-src_common_core_errors_confs_server-http_errors.conf
+++ b/www/bunkerweb/files/patch-src_common_core_errors_confs_server-http_errors.conf
@@ -1,18 +1,35 @@
---- src/common/core/errors/confs/server-http/errors.conf.orig	2026-05-25 18:23:18 UTC
+--- src/common/core/errors/confs/server-http/errors.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/errors/confs/server-http/errors.conf
-@@ -6,7 +6,6 @@ location = {{ page }} {
- error_page {{ code }} {{ page }};
+@@ -12,7 +12,9 @@
+ error_page {{ code }} @bwcustomerror{{ code }};
+ location @bwcustomerror{{ code }} {
+ 	root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
++	{% if has_modsecurity %}
+ 	modsecurity off;
++	{% endif %}
+ 	auth_basic off;
+ 	rewrite ^ {{ page }} break;
+ }
+@@ -21,7 +23,9 @@
+ {% endif %}
  location = {{ page }} {
  	root {% if ROOT_FOLDER == "" %}/var/www/html/{% if MULTISITE == "yes" %}{{ SERVER_NAME.split(" ")[0] }}{% endif %}{% else %}{{ ROOT_FOLDER }}{% endif %};
--	modsecurity off;
++	{% if has_modsecurity %}
+ 	modsecurity off;
++	{% endif %}
  	internal;
  	auth_basic off;
  }
-@@ -27,7 +26,6 @@ location {% if intercepted_error_code == "400" %}= /{%
+@@ -42,9 +46,11 @@
  location {% if intercepted_error_code == "400" %}= /{% else %} @{% endif %}bwerror{{ intercepted_error_code }} {
  	auth_basic off;
  	internal;
--	modsecurity off;
++	{% if has_modsecurity %}
+ 	modsecurity off;
++	{% endif %}
  	default_type 'text/html';
- 	root /usr/share/bunkerweb/core/errors/files;
+-	root /usr/share/bunkerweb/core/errors/files;
++	root /usr/local/share/bunkerweb/common/core/errors/files;
  	content_by_lua_block {
+ 		local logger = require "bunkerweb.logger"
+ 		local cerrors = require "errors.errors"
diff --git a/www/bunkerweb/files/patch-src_common_core_grpc_confs_server-http_grpc.conf b/www/bunkerweb/files/patch-src_common_core_grpc_confs_server-http_grpc.conf
index f59f15528cb6..94c8295482aa 100644
--- a/www/bunkerweb/files/patch-src_common_core_grpc_confs_server-http_grpc.conf
+++ b/www/bunkerweb/files/patch-src_common_core_grpc_confs_server-http_grpc.conf
@@ -1,10 +1,12 @@
 --- src/common/core/grpc/confs/server-http/grpc.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/grpc/confs/server-http/grpc.conf
-@@ -98,7 +98,6 @@
+@@ -98,7 +98,9 @@
  location {% if url_modifier %}{{ url_modifier }} {% endif %}"{{ quoted_url }}" {
  			{% if USE_MODSECURITY == "yes" %}
  	# ModSecurity does not reliably support gRPC traffic patterns, it is always disabled on gRPC locations.
--	modsecurity off;
++	{% if has_modsecurity %}
+ 	modsecurity off;
++	{% endif %}
  			{% endif %}
  			{% if max_client_size != "" %}
  	client_max_body_size {{ max_client_size }};
diff --git a/www/bunkerweb/files/patch-src_common_core_misc_confs_default-server-http_page.conf b/www/bunkerweb/files/patch-src_common_core_misc_confs_default-server-http_page.conf
new file mode 100644
index 000000000000..b86b875690f4
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_misc_confs_default-server-http_page.conf
@@ -0,0 +1,11 @@
+--- src/common/core/misc/confs/default-server-http/page.conf.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/misc/confs/default-server-http/page.conf
+@@ -9,7 +9,7 @@
+ 	add_header Last-Modified "";
+ 	server_tokens off;
+ 	default_type 'text/html';
+-	root /usr/share/bunkerweb/core/misc/files;
++	root /usr/local/share/bunkerweb/common/core/misc/files;
+ 	content_by_lua_block {
+ 			local utils = require "bunkerweb.utils"
+ 			local rand = utils.rand
diff --git a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity-rules-global-crs.conf.modsec b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity-rules-global-crs.conf.modsec
new file mode 100644
index 000000000000..a00cf3954216
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity-rules-global-crs.conf.modsec
@@ -0,0 +1,53 @@
+--- src/common/core/modsecurity/confs/http/modsecurity-rules-global-crs.conf.modsec.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/modsecurity/confs/http/modsecurity-rules-global-crs.conf.modsec
+@@ -102,15 +102,15 @@
+   {% if USE_MODSECURITY_CRS == "yes" -%}
+ # include OWASP CRS configurations
+     {% if effective_crs_version == "3" %}
+-include /usr/share/bunkerweb/core/modsecurity/files/crs-setup-v3.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/crs-setup-v3.conf
+     {% else %}
+-include /usr/share/bunkerweb/core/modsecurity/files/crs-setup-v4.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/crs-setup-v4.conf
+     {% endif %}
+ 
+     {% if USE_MODSECURITY_CRS_PLUGINS == "yes" and effective_crs_version != "3" -%}
+ # custom CRS plugins configurations before loading plugins
+-      {% if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before") %}
+-include /etc/bunkerweb/configs/crs-plugins-before/*.conf
++      {% if is_custom_conf("/usr/local/etc/bunkerweb/configs/crs-plugins-before") %}
++include /usr/local/etc/bunkerweb/configs/crs-plugins-before/*.conf
+       {% endif %}
+       {% if is_custom_conf("/etc/nginx/crs-plugins-before") %}
+ include /etc/nginx/crs-plugins-before/*.conf
+@@ -118,8 +118,8 @@
+     {% endif %}
+ 
+ # custom CRS configurations before loading rules (e.g. exclusions)
+-    {% if is_custom_conf("/etc/bunkerweb/configs/modsec-crs") %}
+-include /etc/bunkerweb/configs/modsec-crs/*.conf
++    {% if is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec-crs") %}
++include /usr/local/etc/bunkerweb/configs/modsec-crs/*.conf
+     {% endif %}
+     {% if is_custom_conf("/etc/nginx/modsec-crs") %}
+ include /etc/nginx/modsec-crs/*.conf
+@@ -131,15 +131,15 @@
+ 
+ # include OWASP CRS rules
+     {% if effective_crs_version == "3" %}
+-include /usr/share/bunkerweb/core/modsecurity/files/coreruleset-v3/rules/*.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/coreruleset-v3/rules/*.conf
+     {% else %}
+-include /usr/share/bunkerweb/core/modsecurity/files/coreruleset-v4/rules/*.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/coreruleset-v4/rules/*.conf
+     {% endif %}
+ 
+     {% if USE_MODSECURITY_CRS_PLUGINS == "yes" and effective_crs_version != "3" %}
+ # custom CRS plugins configurations after loading plugins
+-      {%- if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after") %}
+-include /etc/bunkerweb/configs/crs-plugins-after/*.conf
++      {%- if is_custom_conf("/usr/local/etc/bunkerweb/configs/crs-plugins-after") %}
++include /usr/local/etc/bunkerweb/configs/crs-plugins-after/*.conf
+       {%- endif %}
+       {% if is_custom_conf("/etc/nginx/crs-plugins-after") %}
+ include /etc/nginx/crs-plugins-after/*.conf
diff --git a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity.conf b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity.conf
index 6fdadea6aee9..934702f13ca9 100644
--- a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity.conf
+++ b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_http_modsecurity.conf
@@ -1,7 +1,9 @@
---- src/common/core/modsecurity/confs/http/modsecurity.conf.orig	2026-05-10 11:05:38 UTC
+--- src/common/core/modsecurity/confs/http/modsecurity.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/modsecurity/confs/http/modsecurity.conf
-@@ -1,4 +1,2 @@
- {%- if USE_MODSECURITY == "yes" and USE_MODSECURITY_GLOBAL_CRS == "yes" -%}
--modsecurity on;
--modsecurity_rules_file {{ NGINX_PREFIX }}http/modsecurity-rules-global-crs.conf.modsec;
+@@ -1,4 +1,6 @@
++{% if has_modsecurity %}
+ {%- if USE_MODSECURITY_GLOBAL_CRS == "yes" and has_service_with(all, {"SERVER_TYPE": "http", "USE_MODSECURITY": "yes"}) -%}
+ modsecurity on;
+ modsecurity_rules_file {{ NGINX_PREFIX }}http/modsecurity-rules-global-crs.conf.modsec;
  {%- endif %}
++{% endif %}
diff --git a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity-rules-global-crs.conf.modsec b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity-rules-global-crs.conf.modsec
new file mode 100644
index 000000000000..d3724e4f942c
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity-rules-global-crs.conf.modsec
@@ -0,0 +1,18 @@
+--- src/common/core/modsecurity/confs/server-http/modsecurity-rules-global-crs.conf.modsec.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/modsecurity/confs/server-http/modsecurity-rules-global-crs.conf.modsec
+@@ -80,11 +80,11 @@
+   {% endif %}
+ 
+ # custom rules after loading the CRS
+-  {% if is_custom_conf("/etc/bunkerweb/configs/modsec") %}
+-include /etc/bunkerweb/configs/modsec/*.conf
++  {% if is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec") %}
++include /usr/local/etc/bunkerweb/configs/modsec/*.conf
+   {% endif %}
+-  {% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/modsec/" + service_id) %}
+-include /etc/bunkerweb/configs/modsec/{{ service_id }}/*.conf
++  {% if MULTISITE == "yes" and is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec/" + service_id) %}
++include /usr/local/etc/bunkerweb/configs/modsec/{{ service_id }}/*.conf
+   {% endif %}
+   {% if is_custom_conf("/etc/nginx/modsec") %}
+ include /etc/nginx/modsec/*.conf
diff --git a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity-rules.conf.modsec b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity-rules.conf.modsec
new file mode 100644
index 000000000000..d52567a504e3
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity-rules.conf.modsec
@@ -0,0 +1,84 @@
+--- src/common/core/modsecurity/confs/server-http/modsecurity-rules.conf.modsec.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/modsecurity/confs/server-http/modsecurity-rules.conf.modsec
+@@ -137,18 +137,18 @@
+   {% if USE_MODSECURITY_CRS == "yes" -%}
+ # include OWASP CRS configurations
+     {% if effective_crs_version == "3" %}
+-include /usr/share/bunkerweb/core/modsecurity/files/crs-setup-v3.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/crs-setup-v3.conf
+     {% else %}
+-include /usr/share/bunkerweb/core/modsecurity/files/crs-setup-v4.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/crs-setup-v4.conf
+     {% endif %}
+ 
+     {% if USE_MODSECURITY_CRS_PLUGINS == "yes" and effective_crs_version != "3" -%}
+ # custom CRS plugins configurations before loading plugins
+-      {% if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before") %}
+-include /etc/bunkerweb/configs/crs-plugins-before/*.conf
++      {% if is_custom_conf("/usr/local/etc/bunkerweb/configs/crs-plugins-before") %}
++include /usr/local/etc/bunkerweb/configs/crs-plugins-before/*.conf
+       {% endif %}
+-      {% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/crs-plugins-before/" + service_id) %}
+-include /etc/bunkerweb/configs/crs-plugins-before/{{ service_id }}/*.conf
++      {% if MULTISITE == "yes" and is_custom_conf("/usr/local/etc/bunkerweb/configs/crs-plugins-before/" + service_id) %}
++include /usr/local/etc/bunkerweb/configs/crs-plugins-before/{{ service_id }}/*.conf
+       {% endif %}
+       {% if is_custom_conf("/etc/nginx/crs-plugins-before") %}
+ include /etc/nginx/crs-plugins-before/*.conf
+@@ -184,11 +184,11 @@
+     {% endif %}
+ 
+ # custom CRS configurations before loading rules (e.g. exclusions)
+-    {% if is_custom_conf("/etc/bunkerweb/configs/modsec-crs") %}
+-include /etc/bunkerweb/configs/modsec-crs/*.conf
++    {% if is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec-crs") %}
++include /usr/local/etc/bunkerweb/configs/modsec-crs/*.conf
+     {% endif %}
+-    {% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/modsec-crs/" + service_id) %}
+-include /etc/bunkerweb/configs/modsec-crs/{{ service_id }}/*.conf
++    {% if MULTISITE == "yes" and is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec-crs/" + service_id) %}
++include /usr/local/etc/bunkerweb/configs/modsec-crs/{{ service_id }}/*.conf
+     {% endif %}
+     {% if is_custom_conf("/etc/nginx/modsec-crs") %}
+ include /etc/nginx/modsec-crs/*.conf
+@@ -213,18 +213,18 @@
+ 
+ # include OWASP CRS rules
+     {% if effective_crs_version == "3" %}
+-include /usr/share/bunkerweb/core/modsecurity/files/coreruleset-v3/rules/*.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/coreruleset-v3/rules/*.conf
+     {% else %}
+-include /usr/share/bunkerweb/core/modsecurity/files/coreruleset-v4/rules/*.conf
++include /usr/local/share/bunkerweb/common/core/modsecurity/files/coreruleset-v4/rules/*.conf
+     {% endif %}
+ 
+     {% if USE_MODSECURITY_CRS_PLUGINS == "yes" and effective_crs_version != "3" %}
+ # custom CRS plugins configurations after loading plugins
+-      {%- if is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after") %}
+-include /etc/bunkerweb/configs/crs-plugins-after/*.conf
++      {%- if is_custom_conf("/usr/local/etc/bunkerweb/configs/crs-plugins-after") %}
++include /usr/local/etc/bunkerweb/configs/crs-plugins-after/*.conf
+       {%- endif %}
+-      {% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/crs-plugins-after/" + service_id) %}
+-include /etc/bunkerweb/configs/crs-plugins-after/{{ service_id }}/*.conf
++      {% if MULTISITE == "yes" and is_custom_conf("/usr/local/etc/bunkerweb/configs/crs-plugins-after/" + service_id) %}
++include /usr/local/etc/bunkerweb/configs/crs-plugins-after/{{ service_id }}/*.conf
+       {% endif %}
+       {% if is_custom_conf("/etc/nginx/crs-plugins-after") %}
+ include /etc/nginx/crs-plugins-after/*.conf
+@@ -256,11 +256,11 @@
+   {% endif +%}
+ 
+ # custom rules after loading the CRS
+-  {% if is_custom_conf("/etc/bunkerweb/configs/modsec") %}
+-include /etc/bunkerweb/configs/modsec/*.conf
++  {% if is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec") %}
++include /usr/local/etc/bunkerweb/configs/modsec/*.conf
+   {% endif %}
+-  {% if MULTISITE == "yes" and is_custom_conf("/etc/bunkerweb/configs/modsec/" + service_id) %}
+-include /etc/bunkerweb/configs/modsec/{{ service_id }}/*.conf
++  {% if MULTISITE == "yes" and is_custom_conf("/usr/local/etc/bunkerweb/configs/modsec/" + service_id) %}
++include /usr/local/etc/bunkerweb/configs/modsec/{{ service_id }}/*.conf
+   {% endif %}
+   {% if is_custom_conf("/etc/nginx/modsec") %}
+ include /etc/nginx/modsec/*.conf
diff --git a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity.conf b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity.conf
index 8ee9c1dc7885..c490da8ccfc3 100644
--- a/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity.conf
+++ b/www/bunkerweb/files/patch-src_common_core_modsecurity_confs_server-http_modsecurity.conf
@@ -1,13 +1,12 @@
---- src/common/core/modsecurity/confs/server-http/modsecurity.conf.orig	2026-05-10 11:05:38 UTC
+--- src/common/core/modsecurity/confs/server-http/modsecurity.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/modsecurity/confs/server-http/modsecurity.conf
-@@ -1,10 +1,6 @@
+@@ -1,3 +1,4 @@
++{% if has_modsecurity %}
  {% if USE_MODSECURITY == "yes" %}
--modsecurity on;
+ modsecurity on;
      {% if USE_MODSECURITY_GLOBAL_CRS == "yes" %}
--modsecurity_rules_file {{ NGINX_PREFIX }}server-http/modsecurity-rules-global-crs.conf.modsec;
-     {% else %}
--modsecurity_rules_file {{ NGINX_PREFIX }}server-http/modsecurity-rules.conf.modsec;
-     {% endif %}
+@@ -8,3 +9,4 @@
  {% else %}
--modsecurity off;
+ modsecurity off;
  {% endif %}
++{% endif %}
diff --git a/www/bunkerweb/files/patch-src_common_core_mtls_confs_server-http_mtls.conf b/www/bunkerweb/files/patch-src_common_core_mtls_confs_server-http_mtls.conf
new file mode 100644
index 000000000000..d7b12db1ee5e
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_mtls_confs_server-http_mtls.conf
@@ -0,0 +1,13 @@
+--- src/common/core/mtls/confs/server-http/mtls.conf.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/mtls/confs/server-http/mtls.conf
+@@ -11,8 +11,8 @@
+ 		{% endif %}
+ 	{% elif verify_mode != "optional_no_ca" %}
+ # No validated client CA bundle available yet for this server: mTLS points at a placeholder CA nothing can be validated against, so the verification directives stay in place instead of being dropped. Set MTLS_CA_CERTIFICATE or MTLS_CA_CERTIFICATE_DATA; the Scheduler validates the bundle and distributes it to every instance.
+-ssl_client_certificate /usr/share/bunkerweb/core/mtls/misc/placeholder-ca.pem;
+-ssl_trusted_certificate /usr/share/bunkerweb/core/mtls/misc/placeholder-ca.pem;
++ssl_client_certificate /usr/local/share/bunkerweb/common/core/mtls/misc/placeholder-ca.pem;
++ssl_trusted_certificate /usr/local/share/bunkerweb/common/core/mtls/misc/placeholder-ca.pem;
+ 	{% endif %}
+ 
+ ssl_verify_client {{ verify_mode }};
diff --git a/www/bunkerweb/files/patch-src_common_core_mtls_confs_server-stream_mtls.conf b/www/bunkerweb/files/patch-src_common_core_mtls_confs_server-stream_mtls.conf
new file mode 100644
index 000000000000..69036f3f884a
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_mtls_confs_server-stream_mtls.conf
@@ -0,0 +1,13 @@
+--- src/common/core/mtls/confs/server-stream/mtls.conf.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/mtls/confs/server-stream/mtls.conf
+@@ -11,8 +11,8 @@
+ 		{% endif %}
+ 	{% elif verify_mode != "optional_no_ca" %}
+ # No validated client CA bundle available yet for this stream server: mTLS points at a placeholder CA nothing can be validated against, so the verification directives stay in place instead of being dropped. Set MTLS_CA_CERTIFICATE or MTLS_CA_CERTIFICATE_DATA; the Scheduler validates the bundle and distributes it to every instance.
+-ssl_client_certificate /usr/share/bunkerweb/core/mtls/misc/placeholder-ca.pem;
+-ssl_trusted_certificate /usr/share/bunkerweb/core/mtls/misc/placeholder-ca.pem;
++ssl_client_certificate /usr/local/share/bunkerweb/common/core/mtls/misc/placeholder-ca.pem;
++ssl_trusted_certificate /usr/local/share/bunkerweb/common/core/mtls/misc/placeholder-ca.pem;
+ 	{% endif %}
+ 
+ ssl_verify_client {{ verify_mode }};
diff --git a/www/bunkerweb/files/patch-src_common_core_reverseproxy_confs_server-http_reverse-proxy.conf b/www/bunkerweb/files/patch-src_common_core_reverseproxy_confs_server-http_reverse-proxy.conf
index b610e01a9df6..42a1a6a3e7e4 100644
--- a/www/bunkerweb/files/patch-src_common_core_reverseproxy_confs_server-http_reverse-proxy.conf
+++ b/www/bunkerweb/files/patch-src_common_core_reverseproxy_confs_server-http_reverse-proxy.conf
@@ -1,16 +1,20 @@
 --- src/common/core/reverseproxy/confs/server-http/reverse-proxy.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/reverseproxy/confs/server-http/reverse-proxy.conf
-@@ -130,13 +130,11 @@
+@@ -130,13 +130,17 @@
  location {% if url_modifier %}{{ url_modifier }} {% endif %}"{{ quoted_url }}" {
  	etag off;
  			{% if USE_MODSECURITY == "yes" and modsecurity_location == "no" %}
--	modsecurity off;
++	{% if has_modsecurity %}
+ 	modsecurity off;
++	{% endif %}
  			{% endif %}
  			{% if max_client_size != "" %}
  	client_max_body_size {{ max_client_size }};
  				{% if USE_MODSECURITY == "yes" and modsecurity_location != "no" %}
  					{% set max_client_size_bytes = (max_client_size[:-1]|int * {"k": 1024, "K": 1024, "m": 1048576, "M": 1048576, "g": 1073741824, "G": 1073741824}[max_client_size[-1]]) if max_client_size[-1] in "kKmMgG" else max_client_size|int %}
--	modsecurity_rules 'SecRequestBodyLimit {{ max_client_size_bytes }}';
++	{% if has_modsecurity %}
+ 	modsecurity_rules 'SecRequestBodyLimit {{ max_client_size_bytes }}';
++	{% endif %}
  				{% endif %}
  			{% endif %}
  	set $backend{{ index }} "{{ host }}";
diff --git a/www/bunkerweb/files/patch-src_common_core_securitytxt_confs_server-http_securitytxt.conf b/www/bunkerweb/files/patch-src_common_core_securitytxt_confs_server-http_securitytxt.conf
new file mode 100644
index 000000000000..bc210d736656
--- /dev/null
+++ b/www/bunkerweb/files/patch-src_common_core_securitytxt_confs_server-http_securitytxt.conf
@@ -0,0 +1,11 @@
+--- src/common/core/securitytxt/confs/server-http/securitytxt.conf.orig	2026-09-21 08:05:39 UTC
++++ src/common/core/securitytxt/confs/server-http/securitytxt.conf
+@@ -1,7 +1,7 @@
+ {%- if USE_SECURITYTXT == "yes" and SECURITYTXT_CONTACT != "" -%}
+ location = {{ SECURITYTXT_URI }} {
+ 	default_type 'text/plain; charset=utf-8';
+-	root /usr/share/bunkerweb/core/securitytxt/files;
++	root /usr/local/share/bunkerweb/common/core/securitytxt/files;
+ 	content_by_lua_block {
+ 		local logger   = require "bunkerweb.logger":new("SECURITYTXT")
+ 		local helpers  = require "bunkerweb.helpers"
diff --git a/www/bunkerweb/files/patch-src_common_core_ui_confs_default-server-http_ui.conf b/www/bunkerweb/files/patch-src_common_core_ui_confs_default-server-http_ui.conf
index 090c0d580a9a..a9453e58bb98 100644
--- a/www/bunkerweb/files/patch-src_common_core_ui_confs_default-server-http_ui.conf
+++ b/www/bunkerweb/files/patch-src_common_core_ui_confs_default-server-http_ui.conf
@@ -1,58 +1,72 @@
 --- src/common/core/ui/confs/default-server-http/ui.conf.orig	2026-09-21 08:05:39 UTC
 +++ src/common/core/ui/confs/default-server-http/ui.conf
-@@ -35,7 +35,6 @@
+@@ -35,7 +35,9 @@
      # in http/ui.modsec-crs cannot match. Disable modsec on the UI proxy
      # locations only — other defenses (limit, badbehavior, crowdsec, allowlists)
      # still run via the BunkerWeb Lua pipeline.
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      proxy_pass $backendui;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
-@@ -53,7 +52,6 @@
+@@ -53,7 +55,9 @@
  }
  
  location = /login {
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      etag off;
      add_header Last-Modified "";
      proxy_pass $backendui;
-@@ -73,7 +71,6 @@
+@@ -73,7 +77,9 @@
  }
  
  location = /logout {
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      etag off;
      add_header Last-Modified "";
      proxy_pass $backendui;
-@@ -94,7 +91,6 @@
+@@ -94,7 +100,9 @@
  
  # Serve CSS, Fonts, Images, JavaScript and Libs without modifying the response body
  location ~ ^/setup/(css|fonts|img|js|libs|locales)(.*)$ {
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      # Capture the asset type and the remaining path
      # Example: /setup/js/app.js -> /js/app.js
      proxy_pass $backendui/$1$2;
-@@ -122,7 +118,6 @@
+@@ -122,7 +130,9 @@
  }
  
  location /setup {
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      etag off;
      add_header Last-Modified "";
      proxy_pass $backendui;
-@@ -171,7 +166,6 @@
+@@ -171,7 +181,9 @@
  }
  
  location /setup/loading {
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      etag off;
      add_header Last-Modified "";
      proxy_pass $backendui;
-@@ -220,7 +214,6 @@
+@@ -220,7 +232,9 @@
  }
  
  location /setup/check {
--    modsecurity off;
++    {% if has_modsecurity %}
+     modsecurity off;
++    {% endif %}
      etag off;
      add_header Last-Modified "";
      add_header 'Access-Control-Allow-Origin' '*' always;
diff --git a/www/bunkerweb/files/patch-src_common_gen_Templator.py b/www/bunkerweb/files/patch-src_common_gen_Templator.py
index 2020696cdb2d..86484eb742eb 100644
--- a/www/bunkerweb/files/patch-src_common_gen_Templator.py
+++ b/www/bunkerweb/files/patch-src_common_gen_Templator.py
@@ -1,6 +1,23 @@
---- src/common/gen/Templator.py.orig	2026-05-28 20:12:40 UTC
+--- src/common/gen/Templator.py.orig	2026-09-21 08:05:39 UTC
 +++ src/common/gen/Templator.py
-@@ -650,6 +650,7 @@ class Templator:
+@@ -9,7 +9,7 @@
+ from glob import glob
+ from math import ceil
+ import multiprocessing as mp
+-from os.path import basename, join, sep
++from os.path import basename, isfile, join, sep
+ from pathlib import Path
+ from random import choice
+ from ssl import PROTOCOL_TLS_SERVER, SSLContext
+@@ -441,6 +441,7 @@
+             "import": import_module,
+             "resolve_ssl_ecdh_curve": resolve_ssl_ecdh_curve,
+             "normalize_memory_size": Templator._normalize_memory_size,
++            "has_modsecurity": isfile("/usr/local/nginx/modules/ngx_http_modsecurity_module.so"),
+         }
+ 
+         self._server_env_cache: Dict[str, Environment] = {}
+@@ -721,6 +722,7 @@
          template_vars = self._base_template_vars.copy()
          template_vars["all"] = full_config
          template_vars.update(config)