Skip to content

Pi-hole Template#24

Open
palmcoasty wants to merge 10 commits into
bunkerity:mainfrom
palmcoasty:pi-hole
Open

Pi-hole Template#24
palmcoasty wants to merge 10 commits into
bunkerity:mainfrom
palmcoasty:pi-hole

Conversation

@palmcoasty
Copy link
Copy Markdown

Summary

Testing

  • jq . templates/<template-name>/template.json
  • Validated template or docs using the listed commands
  • Other (add details below)
Validation details

Checklist

  • I installed the pre-commit hooks and ran pre-commit run --all-files.
  • I described the service or scenario this change targets.
  • template.json references only files shipped in the same template directory.
  • Template docs note how to import it (plugin bundle and/or web UI upload).
  • I updated configs, screenshots, or notes impacted by this change.
  • I linked related issues or discussions and added context for reviewers.

@palmcoasty
Copy link
Copy Markdown
Author

palmcoasty commented Mar 31, 2026

@YouKyi Could you check my template generator, i started using him for this template but i am not sure if the format is correct and how to setup the template to require to upload configs: https://github.com/palmcoasty/bunkerweb-conf-formatter Some feedback would be great and ease future template pull requests.

@TheophileDiot
Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

Pi-hole Template Addition

Template Structure & Files

Template correctly placed at templates/pi-hole/ with three files:

  • template.json (1,154 bytes) — JSON configuration schema
  • readme.md (1,298 bytes) — deployment documentation (note: lowercase filename differs from other templates' README.md)
  • configs/modsec/pihole-exclusions.conf — ModSecurity exclusions
  • configs/server-http/pihole.conf — Nginx reverse proxy configuration

All referenced configuration files exist and are properly integrated.

template.json Schema

Defines id: "pihole" with 27 settings. Key operational parameters:

  • ModSecurity: MODSECURITY_SEC_RULE_ENGINE=DetectionOnly (alerting only, not blocking)
  • Rate Limiting: LIMIT_REQ_RATE=20r/s, HTTP/2 & HTTP/3 limits at 50 connections, bad behaviour threshold 20 requests / 3600s ban
  • TLS: AUTO_LETS_ENCRYPT=yes with example email placeholder
  • Reverse Proxy: Single upstream http://pihole-server-ip:80/, keepalive enabled, 30s connect timeout
  • Real IP: Configured for Cloudflare (CF-Connecting-IP header, ranges 172.65.0.0/16 172.64.0.0/13 104.16.0.0/13)
  • Headers: Removes Server, Expect-CT, X-Powered-By, X-AspNet-Version, X-AspNetMvc-Version, Public-Key-Pins, X-Frame-Options
  • Draft Status: IS_DRAFT=no

ModSecurity Configuration — CRS Rule Relaxation

⚠️ SECURITY IMPACT: pihole-exclusions.conf broadly disables multiple CRS rule categories:

For /api/ path:

  • Removes rules tagged attack-lfi (Local File Inclusion)
  • Removes rules tagged attack-rce (Remote Code Execution)
  • Removes rules tagged attack-injection (SQL/command injection)
  • Removes CRS rule ID 920420 (HTTP method enforcement)

For /admin/ path:

  • Removes rules tagged attack-lfi
  • Removes rules tagged attack-xss (Cross-Site Scripting)

This represents a significant WAF relaxation on the administrative and API interfaces. No false-positive mitigation rationale is documented in the PR description or readme.

Nginx Configuration

pihole.conf defines two location blocks (/admin/, /api/) with:

  • Correct proxy pass to backend
  • Header forwarding (Host, X-Forwarded-For)
  • X-Frame-Options handling (remove upstream, set to SAMEORIGIN on response)
  • 90-second read timeout
  • Configuration is syntactically sound

Documentation

readme.md warns users that serving Pi-hole at root domain "adds extra attack surface" and "is not advised". Instructs users to use raw .env config instead of template.json due to Pi-hole's hardcoded /admin/ redirect. Documentation is clear but highlights a fundamental limitation of the template approach.

Repository Documentation Updates

NOT UPDATED:

  • CHANGELOG.md## Unreleased section remains unmodified; Pi-hole template addition not documented
  • TEMPLATE_CATALOG.md — Pi-hole template not added to production template listing (contains 8 templates: WordPress, Nextcloud, Jellyfin, Tomcat, Drupal, NetBird, Xen Orchestra; missing Pi-hole)

Naming inconsistency: Template uses readme.md (lowercase) whereas all other templates use README.md (uppercase).

CI/Pre-commit Hooks

No .github/workflows/ or .pre-commit-config.yaml changes. Standard hooks (Prettier, Codespell, Gitleaks) will run on JSON and markdown files.

Summary

Pi-hole template is structurally complete and configuration files are syntactically valid, but submission is incomplete: CHANGELOG and TEMPLATE_CATALOG require updates, and significant CRS rule disabling (LFI, RCE, injection, XSS categories) lacks justification or false-positive documentation. The ModSecurity relaxation for /api/ and /admin/ should be reviewed against known Pi-hole attack patterns before acceptance.

Walkthrough

A new Pi-hole integration template for BunkerWeb is introduced, encompassing ModSecurity exclusion rules, Nginx reverse proxy configuration, template definition, and usage documentation. Four new files establish the complete deployment template.

Changes

Cohort / File(s) Summary
ModSecurity and Nginx Configuration
templates/pi-hole/configs/modsec/pihole-exclusions.conf, templates/pi-hole/configs/server-http/pihole.conf
ModSecurity ruleset adds six SecRule directives to suppress rules by tag and ID for /api/ and /admin/ paths. Nginx configuration introduces two location blocks proxying requests to the upstream Pi-hole server with header forwarding, X-Frame-Options hardening (SAMEORIGIN), and 90-second read timeout.
Template and Documentation
templates/pi-hole/template.json, templates/pi-hole/readme.md
JSON template defines Pi-hole configuration with id: "pihole" and preconfigures reverse proxy, security, TLS, and operational settings. Markdown readme documents deployment considerations, notes the increased attack surface, and provides concrete environment variable configuration examples.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🥧 A Pi-hole takes the stage so round,
With rules to keep the bad guys bound,
Through Nginx ports and SSL's glow,
BunkerWeb lets safe requests flow. 🔒

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description template is present but contains only placeholder sections with no substantive content describing the actual changes, testing performed, or checklist completion status. Complete the summary section with concrete details about the template, document testing results, and explicitly mark completed checklist items to clarify what validation work has been performed.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title "Pi-hole Template" is directly related to the changeset, which adds a complete Pi-hole template with configuration files and documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@templates/pi-hole/configs/modsec/pihole-exclusions.conf`:
- Around line 1-6: Add this new template to the templates list in template.json
(configs array) and update pihole-exclusions.conf: replace low-numbered rule IDs
(1001–1006) with unique 9,000,000+ IDs, change each ctl:ruleRemoveByTag=... to
ctl:ruleRemoveById=<specific-rule-id> referencing the exact ModSecurity rule IDs
you intend to disable for those paths (use the SecRule lines as anchors), add a
one-line inline comment after each SecRule describing the specific legitimate
traffic being unblocked, and add a top-of-file header comment naming the
template and the Pi‑Hole version it was validated against. Ensure SecRule
entries (the lines beginning with SecRule REQUEST_FILENAME "@beginsWith /api/"
and "/admin/") use the new 9M+ IDs and ctl:ruleRemoveById usage to avoid
removing entire attack families.
- Around line 1-6: The SecRule entries in pihole-exclusions.conf use IDs
1001-1006 which are below the required user/custom range and the file lacks
top-of-file metadata and is not referenced from the template.json configs array;
update each SecRule id to a value >= 9000000 (e.g., 9000000–9000005 or another
block reserved for this template), add a top-of-file comment with the template
name and the Pi-hole version this template was validated against (and any
minimal required metadata such as author or description if your project expects
it), and add "pihole-exclusions.conf" to the owning template.json's configs
array so the file is not orphaned.

In `@templates/pi-hole/configs/server-http/pihole.conf`:
- Line 1: Add a top-of-file comment to the Pi-hole Nginx template indicating
this snippet is for Pi-hole and the specific Pi-hole version it was validated
against (e.g., "Pi-hole template snippet — validated against Pi-hole vX.Y.Z"),
placing it above the existing "location /admin/" line so reviewers can quickly
identify the template and version.
- Around line 5-6: Replace the ineffective response header configuration by
keeping proxy_hide_header X-Frame-Options and replacing proxy_set_header
X-Frame-Options "SAMEORIGIN" with add_header X-Frame-Options "SAMEORIGIN"
always; update both occurrences (lines using proxy_hide_header and
proxy_set_header) so clients actually receive the header. Add a top-of-file
comment in pihole.conf that states the template purpose and the Pi-hole version
this was validated against. Finally, register this file path in the configs
array inside template.json so the template is included in the build/deployment.

In `@templates/pi-hole/readme.md`:
- Line 5: Update the README sentence to clearly explain when to use the provided
template.json versus the raw config: state that the supported/default path is to
use template.json for guided import via the repository's import workflow, and
only use the raw config when the user's DNS setup requires a root-domain entry
that the guided importer cannot represent (the specific "root-domain
exception"); mention the exact condition that triggers the exception and point
readers to the guided import workflow and the raw-config fallback so they know
which path to follow.
- Line 3: Fix the typo "its self" to "itself" and tighten the redirect sentence
for clarity: update the sentence that mentions "/admin/" so it reads succinctly
in British English (e.g. "Pi-hole will always redirect to /admin/ — this
behaviour is inherent to Pi-hole and cannot be changed without modifying Pi-hole
itself."). Ensure the preceding note about serving Pi-hole at the root remains
(warn about extra attack surface) and apply British spelling/concise phrasing.

In `@templates/pi-hole/template.json`:
- Around line 1-30: The template.json for the "pihole" template is missing a
configs array that declares the shipped files; add a top-level "configs" array
in templates/pi-hole/template.json listing "configs/server-http/pihole.conf" and
"configs/modsec/pihole-exclusions.conf" so every file referenced by the template
is declared (ensure the array key is "configs" and use the exact relative paths
used in the repo to match the existing files).
- Around line 1-30: The JSON is missing the root closing brace and must include
an immutable id matching the template directory name and a configs array listing
required config paths; fix template.json by (1) changing the "id" value from
"pihole" to "pi-hole" (lowercase-kebab-case), (2) adding a top-level "configs":
[ "configs/modsec/pihole-exclusions.conf", "configs/server-http/pihole.conf" ]
entry, and (3) appending the missing closing curly brace for the root object
after the existing "settings" block so the file is valid JSON.
- Line 2: The template's immutable id value in template.json is incorrect:
change the "id" field value from "pihole" to the lowercase-kebab-case directory
name "pi-hole" so the id matches the template directory and follows the
project's immutable id convention (update the "id" property in template.json
accordingly).
- Line 20: The default template currently sets MODSECURITY_SEC_RULE_ENGINE to
"DetectionOnly", which weakens enforcement; update the template.json entry for
MODSECURITY_SEC_RULE_ENGINE to an enforcing value (e.g., "On" or "Enabled") so
ModSecurity is active by default, and ensure no other template keys disable
ModSecurity or the CRS (refer to MODSECURITY_SEC_RULE_ENGINE in the file to
locate and replace the value).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4873a3b0-8f80-4c3d-8079-a516658214a5

📥 Commits

Reviewing files that changed from the base of the PR and between ab602a3 and 3f7a389.

📒 Files selected for processing (4)
  • templates/pi-hole/configs/modsec/pihole-exclusions.conf
  • templates/pi-hole/configs/server-http/pihole.conf
  • templates/pi-hole/readme.md
  • templates/pi-hole/template.json
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Documentation should be concise, accurate, and written in British English:

  • Keep a sensible heading hierarchy and prefer concrete instructions over narrative.
  • Commands go in backticks or fenced code blocks; keep lines under roughly 100 characters.
  • Check that referenced paths, settings, workflows, and external links still match the current repository.
  • When a PR changes behaviour, defaults, or packaging, require the matching doc update in the same PR.

Files:

  • templates/pi-hole/readme.md
templates/**/configs/**/*.conf

⚙️ CodeRabbit configuration file

templates/**/configs/**/*.conf: These are NGINX and ModSecurity snippets loaded by BunkerWeb at runtime. They must be safe and minimal:

  • ModSecurity / CRS tuning files (*_false_positives.conf): prefer targeted ctl:ruleRemoveTargetById= / ctl:ruleRemoveById= over SecRuleRemoveById with broad ranges. Every exclusion must have a short comment explaining the specific legitimate traffic it unblocks (endpoint, parameter, rule ID, reason). Do not disable whole paranoia levels or broad rule families.
  • Rule IDs authored here must live in the user range (>= 9,000,000 for SecAction markers used by CRS plugins, or the custom range documented by the upstream CRS plugin being enabled).
  • Do not set SecRuleEngine Off or SecRequestBodyAccess Off in a template config.
  • NGINX fragments: avoid if inside location where a prefix match would do; never proxy_pass to an upstream constructed from a request variable (SSRF); do not strip security headers added by BunkerWeb core; do not lower TLS/SSL protocol or cipher strength.
  • Every file referenced here must also be listed in the owning template.json configs array, and vice versa. Flag orphans in either direction.
  • Add a short top-of-file comment describing the template the snippet belongs to and the upstream service version it was validated against.

Files:

  • templates/pi-hole/configs/server-http/pihole.conf
  • templates/pi-hole/configs/modsec/pihole-exclusions.conf
templates/**/template.json

⚙️ CodeRabbit configuration file

templates/**/template.json: template.json is the BunkerWeb template definition consumed by the configurator and the guided-import UI. Apply these rules:

  • Required top-level fields: id (lowercase-kebab-case, matching the template directory name, treated as immutable once published), name (concise user-facing label). Optional: settings (object of BunkerWeb multisite settings), configs (array of relative paths), steps (ordered guided-import workflow).
  • Two-space indentation, double-quoted keys and strings, no trailing commas. The file must parse with jq . templates/<name>/template.json.
  • Setting keys must match BunkerWeb multisite setting names exactly (e.g. SERVER_NAME, USE_REVERSE_PROXY, REVERSE_PROXY_HOST, MODSECURITY_CRS_PLUGINS, USE_LIMIT_REQ, LIMIT_REQ_RATE, WHITELIST_RDNS). Flag typos, unknown keys, and values that violate documented types or ranges.
  • Every path referenced from configs (top-level or inside a step) must resolve to a file that exists under the template directory. Flag missing files, paths that escape the template directory, or duplicate entries. Templates must be self-contained: never reference files outside their own templates/<name>/ directory.
  • Each steps[].settings entry must refer to a key that also exists in the top-level settings object — the UI surfaces the step by reading those keys. Flag orphan references.
  • Templates must stay integration-agnostic. They work identically across Docker, Kubernetes, and Linux, so never introduce environment-specific assets (Dockerfiles, docker-compose.yml, Kubernetes manifests, Helm charts, systemd units) inside templates/<name>/, and never condition settings on the host integration.
  • Templates must be app-specific, not generic hardening. BunkerWeb already ships built-in low/medium/high presets for generic defaults; a template in this repo should target a named upstream service and ship app-aware configs and guided steps. Push back on PR...

Files:

  • templates/pi-hole/template.json
🪛 LanguageTool
templates/pi-hole/readme.md

[grammar] ~3-~3: Did you mean “it’s” (contraction of “it is/has”)?
Context: ...kerweb you would need to modify pi-hole its self to achieve that. If you still wan...

(ITS_TO_IT_S)

Comment on lines +1 to +6
SecRule REQUEST_FILENAME "@beginsWith /api/" "id:1001,phase:2,pass,nolog,ctl:ruleRemoveByTag=attack-lfi"
SecRule REQUEST_FILENAME "@beginsWith /api/" "id:1002,phase:2,pass,nolog,ctl:ruleRemoveByTag=attack-rce"
SecRule REQUEST_FILENAME "@beginsWith /api/" "id:1003,phase:2,pass,nolog,ctl:ruleRemoveByTag=attack-injection"
SecRule REQUEST_FILENAME "@beginsWith /api/" "id:1004,phase:2,pass,nolog,ctl:ruleRemoveById=920420"
SecRule REQUEST_FILENAME "@beginsWith /admin/" "id:1005,phase:2,pass,nolog,ctl:ruleRemoveByTag=attack-lfi"
SecRule REQUEST_FILENAME "@beginsWith /admin/" "id:1006,phase:2,pass,nolog,ctl:ruleRemoveByTag=attack-xss"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "pihole-exclusions.conf" -o -name "template.json" | head -20

Repository: bunkerity/bunkerweb-templates

Length of output: 411


🏁 Script executed:

ls -la templates/pi-hole/ 2>/dev/null | head -20

Repository: bunkerity/bunkerweb-templates

Length of output: 367


🏁 Script executed:

git ls-files templates/pi-hole/ | head -30

Repository: bunkerity/bunkerweb-templates

Length of output: 238


🏁 Script executed:

cat -n templates/pi-hole/configs/modsec/pihole-exclusions.conf

Repository: bunkerity/bunkerweb-templates

Length of output: 749


🏁 Script executed:

cat templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1226


🏁 Script executed:

find templates -name "*.conf" -path "*/modsec/*" -type f | xargs head -5

Repository: bunkerity/bunkerweb-templates

Length of output: 1929


🏁 Script executed:

cat -n templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1436


🏁 Script executed:

grep -r "1001\|1002\|1003\|1004\|1005\|1006" templates/ --include="*.json" 2>/dev/null

Repository: bunkerity/bunkerweb-templates

Length of output: 55


🏁 Script executed:

grep -A 20 '"configs"' templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 55


🏁 Script executed:

wc -l templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 107


🏁 Script executed:

tail -20 templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 929


🏁 Script executed:

cat templates/netbird/template.json | grep -A 5 '"configs"'

Repository: bunkerity/bunkerweb-templates

Length of output: 373


🏁 Script executed:

cat templates/wordpress/template.json | grep -A 2 '"configs"'

Repository: bunkerity/bunkerweb-templates

Length of output: 219


🏁 Script executed:

cat templates/xen-orchestra/template.json | grep -A 2 '"configs"'

Repository: bunkerity/bunkerweb-templates

Length of output: 261


🏁 Script executed:

grep -r "id:[0-9]" templates/*/configs/modsec/*.conf | grep -o "id:[0-9]*" | sort -u

Repository: bunkerity/bunkerweb-templates

Length of output: 227


Add pihole-exclusions.conf to template.json configs array and use rule IDs in the 9M+ range.

This file is not declared in template.json's configs array, so it will not be loaded. Additionally, rule IDs 1001–1006 violate the documented convention that authored rule IDs must use the user range (≥ 9,000,000); see NetBird (3000000+), WordPress (9005000+), and Xen-Orchestra (9010000) for correct patterns. Adopt IDs from the 9M+ range to avoid collision and align with project standards.

Furthermore, lines 1–3 and 5–6 remove entire attack families by tag (attack-lfi, attack-rce, attack-injection, attack-xss) across /api/ and /admin/ endpoints. Replace with specific ctl:ruleRemoveById= and include a one-line inline comment explaining the legitimate traffic each exclusion unblocks. Add a top-of-file header comment stating the template name and the Pi-Hole version this was validated against.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/configs/modsec/pihole-exclusions.conf` around lines 1 - 6,
Add this new template to the templates list in template.json (configs array) and
update pihole-exclusions.conf: replace low-numbered rule IDs (1001–1006) with
unique 9,000,000+ IDs, change each ctl:ruleRemoveByTag=... to
ctl:ruleRemoveById=<specific-rule-id> referencing the exact ModSecurity rule IDs
you intend to disable for those paths (use the SecRule lines as anchors), add a
one-line inline comment after each SecRule describing the specific legitimate
traffic being unblocked, and add a top-of-file header comment naming the
template and the Pi‑Hole version it was validated against. Ensure SecRule
entries (the lines beginning with SecRule REQUEST_FILENAME "@beginsWith /api/"
and "/admin/") use the new 9M+ IDs and ctl:ruleRemoveById usage to avoid
removing entire attack families.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and read its content
cat -n templates/pi-hole/configs/modsec/pihole-exclusions.conf

Repository: bunkerity/bunkerweb-templates

Length of output: 749


🏁 Script executed:

# Check if template.json exists for pi-hole and list its configs
if [ -f templates/pi-hole/template.json ]; then
  cat templates/pi-hole/template.json | jq '.configs // empty' 2>/dev/null | head -50
fi

Repository: bunkerity/bunkerweb-templates

Length of output: 55


🏁 Script executed:

# Search for the file in case the path is different
fd -type f -name "*pihole*exclusions*"

Repository: bunkerity/bunkerweb-templates

Length of output: 243


🏁 Script executed:

# Find template.json files in templates directory
find templates -name "template.json" -type f | head -20

Repository: bunkerity/bunkerweb-templates

Length of output: 337


🏁 Script executed:

# Check the pi-hole template directory structure
ls -la templates/pi-hole/

Repository: bunkerity/bunkerweb-templates

Length of output: 367


🏁 Script executed:

# Look for the pi-hole template.json specifically
cat templates/pi-hole/template.json 2>/dev/null | jq '.configs' 2>/dev/null

Repository: bunkerity/bunkerweb-templates

Length of output: 55


🏁 Script executed:

# Read the template.json file directly
cat templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1226


🏁 Script executed:

# Also check the configs directory structure
find templates/pi-hole/configs -type f

Repository: bunkerity/bunkerweb-templates

Length of output: 178


🏁 Script executed:

# Get the full template.json content and look for configs section
cat templates/pi-hole/template.json | jq -r '.configs' 2>/dev/null || cat templates/pi-hole/template.json | grep -A 20 '"configs"'

Repository: bunkerity/bunkerweb-templates

Length of output: 55


🏁 Script executed:

# Also read the entire template.json to see full structure
wc -l templates/pi-hole/template.json && tail -100 templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1261


🏁 Script executed:

# Read the complete template.json file from start to finish
cat templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1226


🏁 Script executed:

# Get the last 10 lines of template.json to see the configs array
tail -10 templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 458


🏁 Script executed:

# Alternative: use python to parse and check if configs exists
python3 << 'EOF'
import json
with open('templates/pi-hole/template.json', 'r') as f:
    data = json.load(f)
    if 'configs' in data:
        print("configs array exists:")
        print(json.dumps(data['configs'], indent=2))
    else:
        print("No 'configs' key found in template.json")
        print("Keys present:", list(data.keys()))
EOF

Repository: bunkerity/bunkerweb-templates

Length of output: 812


🏁 Script executed:

# Read specific lines to see what's at the end
sed -n '20,30p' templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 510


🏁 Script executed:

# Check actual file size and content
hexdump -C templates/pi-hole/template.json | tail -20

Repository: bunkerity/bunkerweb-templates

Length of output: 118


🏁 Script executed:

# Check if there's anything beyond line 30
sed -n '28,$p' templates/pi-hole/template.json | cat -A

Repository: bunkerity/bunkerweb-templates

Length of output: 164


🏁 Script executed:

# Count actual lines and check file end
tail -c 100 templates/pi-hole/template.json | od -c

Repository: bunkerity/bunkerweb-templates

Length of output: 115


🏁 Script executed:

# Check if other templates have configs arrays to understand the expected structure
for template in templates/*/template.json; do
  echo "=== $template ==="
  grep -c '"configs"' "$template" 2>/dev/null || echo "No configs found"
done

Repository: bunkerity/bunkerweb-templates

Length of output: 468


🏁 Script executed:

# Look at a complete template to see the pattern
cat templates/wordpress/template.json 2>/dev/null | tail -20

Repository: bunkerity/bunkerweb-templates

Length of output: 674


Fix rule IDs to comply with user range, add required metadata, and reference file in template.json.

Lines 1-6 use IDs 1001-1006, which fall below the required user range (>= 9,000,000 for custom SecAction markers); the file lacks a top-of-file comment documenting the template name and Pi-hole version validated against; and pihole-exclusions.conf is not listed in the owning template.json configs array, creating an orphaned file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/configs/modsec/pihole-exclusions.conf` around lines 1 - 6,
The SecRule entries in pihole-exclusions.conf use IDs 1001-1006 which are below
the required user/custom range and the file lacks top-of-file metadata and is
not referenced from the template.json configs array; update each SecRule id to a
value >= 9000000 (e.g., 9000000–9000005 or another block reserved for this
template), add a top-of-file comment with the template name and the Pi-hole
version this template was validated against (and any minimal required metadata
such as author or description if your project expects it), and add
"pihole-exclusions.conf" to the owning template.json's configs array so the file
is not orphaned.

@@ -0,0 +1,17 @@
location /admin/ {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the required file header comment.

Please add a short top-of-file comment indicating this is the Pi-hole template snippet and the Pi-hole version it was validated against.

As per coding guidelines "Add a short top-of-file comment describing the template the snippet belongs to and the upstream service version it was validated against."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/configs/server-http/pihole.conf` at line 1, Add a
top-of-file comment to the Pi-hole Nginx template indicating this snippet is for
Pi-hole and the specific Pi-hole version it was validated against (e.g.,
"Pi-hole template snippet — validated against Pi-hole vX.Y.Z"), placing it above
the existing "location /admin/" line so reviewers can quickly identify the
template and version.

Comment on lines +5 to +6
proxy_hide_header X-Frame-Options;
proxy_set_header X-Frame-Options "SAMEORIGIN";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and examine the pihole.conf file
find . -path "*templates/pi-hole/configs/server-http/pihole.conf" -type f

Repository: bunkerity/bunkerweb-templates

Length of output: 124


🏁 Script executed:

# Also check if template.json exists for pi-hole
find . -path "*templates/pi-hole/template.json" -type f

Repository: bunkerity/bunkerweb-templates

Length of output: 106


🏁 Script executed:

cat -n ./templates/pi-hole/configs/server-http/pihole.conf

Repository: bunkerity/bunkerweb-templates

Length of output: 760


🏁 Script executed:

cat ./templates/pi-hole/template.json | head -100

Repository: bunkerity/bunkerweb-templates

Length of output: 1226


🏁 Script executed:

cat ./templates/pi-hole/template.json | jq '.configs // "NO_CONFIGS_KEY"'

Repository: bunkerity/bunkerweb-templates

Length of output: 134


🌐 Web query:

NGINX proxy_set_header vs add_header X-Frame-Options response header

💡 Result:

proxy_set_header sets request headers sent to the upstream server, while add_header adds response headers to the client. For the X-Frame-Options response header, use add_header in the nginx server or location block, even with proxy_pass. To set X-Frame-Options SAMEORIGIN: add_header X-Frame-Options "SAMEORIGIN" always; The 'always' parameter (since nginx 1.7.5) ensures the header is added for all response codes, including errors. If the upstream server sets X-Frame-Options and you want nginx to override it, first hide the upstream header: proxy_hide_header X-Frame-Options; add_header X-Frame-Options "SAMEORIGIN" always; proxy_set_header cannot be used for response headers like X-Frame-Options.

Citations:


🏁 Script executed:

wc -l ./templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 109


🏁 Script executed:

sed -n '1,50p' ./templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1226


🏁 Script executed:

tail -20 ./templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 929


Replace proxy_set_header with add_header to actually set the response header.

Lines 5–6 and 14–15 use proxy_hide_header X-Frame-Options followed by proxy_set_header X-Frame-Options "SAMEORIGIN". This is ineffective: proxy_set_header sets only request headers sent to the upstream, not response headers to clients. Clients receive no X-Frame-Options header, weakening clickjacking protection. Replace with:

proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "SAMEORIGIN" always;

Also add a top-of-file comment describing the template and Pi-hole version this was validated against, and register this file in the configs array of template.json.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/configs/server-http/pihole.conf` around lines 5 - 6,
Replace the ineffective response header configuration by keeping
proxy_hide_header X-Frame-Options and replacing proxy_set_header X-Frame-Options
"SAMEORIGIN" with add_header X-Frame-Options "SAMEORIGIN" always; update both
occurrences (lines using proxy_hide_header and proxy_set_header) so clients
actually receive the header. Add a top-of-file comment in pihole.conf that
states the template purpose and the Pi-hole version this was validated against.
Finally, register this file path in the configs array inside template.json so
the template is included in the build/deployment.

@@ -0,0 +1,37 @@
# Pi-hole on Root Domain with BunkerWeb

It is possible to serve Pi-hole at the root of your domain, but this adds an extra attack surface and is **not advised**. Additionally, you will always be redirected to `/admin/` — this is how Pi-hole is built and cannot be changed, by using bunkerweb you would need to modify pi-hole its self to achieve that.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix wording and grammar on the redirect explanation.

Line 3 has a typo (“its self” → “itself”) and awkward phrasing. Please tighten this sentence for clarity in British English.

As per coding guidelines "Documentation should be concise, accurate, and written in British English."

🧰 Tools
🪛 LanguageTool

[grammar] ~3-~3: Did you mean “it’s” (contraction of “it is/has”)?
Context: ...kerweb you would need to modify pi-hole its self to achieve that. If you still wan...

(ITS_TO_IT_S)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/readme.md` at line 3, Fix the typo "its self" to "itself"
and tighten the redirect sentence for clarity: update the sentence that mentions
"/admin/" so it reads succinctly in British English (e.g. "Pi-hole will always
redirect to /admin/ — this behaviour is inherent to Pi-hole and cannot be
changed without modifying Pi-hole itself."). Ensure the preceding note about
serving Pi-hole at the root remains (warn about extra attack surface) and apply
British spelling/concise phrasing.


It is possible to serve Pi-hole at the root of your domain, but this adds an extra attack surface and is **not advised**. Additionally, you will always be redirected to `/admin/` — this is how Pi-hole is built and cannot be changed, by using bunkerweb you would need to modify pi-hole its self to achieve that.

If you still want to proceed, use the raw config below instead of the template.json.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify when to use template.json vs raw config.

Line 5 instructs users to bypass template.json, which is confusing in a template PR. Please explicitly state the supported path for guided import and the specific root-domain exception requiring raw config.

As per coding guidelines "Check that referenced paths, settings, workflows ... still match the current repository."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/readme.md` at line 5, Update the README sentence to clearly
explain when to use the provided template.json versus the raw config: state that
the supported/default path is to use template.json for guided import via the
repository's import workflow, and only use the raw config when the user's DNS
setup requires a root-domain entry that the guided importer cannot represent
(the specific "root-domain exception"); mention the exact condition that
triggers the exception and point readers to the guided import workflow and the
raw-config fallback so they know which path to follow.

Comment on lines +1 to +30
{
"id": "pihole",
"name": "Pihole BunkerWeb Configuration",
"settings": {
"IS_DRAFT": "no",
"SERVER_NAME": "example.com",
"BAD_BEHAVIOR_STATUS_CODES": "400 403 404 405 429 444",
"BAD_BEHAVIOR_THRESHOLD": "20",
"BAD_BEHAVIOR_BAN_TIME": "3600",
"USE_BUNKERNET": "yes",
"USE_DNSBL": "no",
"GZIP_PROXIED": "expired no-cache no-store private auth",
"REMOVE_HEADERS": "Server Expect-CT X-Powered-By X-AspNet-Version X-AspNetMvc-Version Public-Key-Pins X-Frame-Options",
"AUTO_LETS_ENCRYPT": "yes",
"EMAIL_LETS_ENCRYPT": "registration@example.com",
"LIMIT_CONN_MAX_HTTP2": "50",
"LIMIT_CONN_MAX_HTTP3": "50",
"LIMIT_REQ_RATE": "20r/s",
"USE_METRICS": "no",
"MODSECURITY_SEC_RULE_ENGINE": "DetectionOnly",
"USE_REAL_IP": "yes",
"REAL_IP_FROM": "172.65.0.0/16 172.64.0.0/13 104.16.0.0/13",
"REAL_IP_HEADER": "CF-Connecting-IP",
"USE_REVERSE_PROXY": "yes",
"REVERSE_PROXY_HOST_1": "http://pihole-server-ip:80/",
"REVERSE_PROXY_WS_1": "yes",
"REVERSE_PROXY_KEEPALIVE_1": "yes",
"REVERSE_PROXY_HIDE_HEADERS_1": "",
"REVERSE_PROXY_CONNECT_TIMEOUT_1": "30s"
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add a configs array to declare both shipped config files.

templates/pi-hole/configs/server-http/pihole.conf and templates/pi-hole/configs/modsec/pihole-exclusions.conf exist, but no configs mapping is declared in this template definition.

As per coding guidelines "Every file referenced here must also be listed in the owning template.json configs array, and vice versa. Flag orphans in either direction."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/template.json` around lines 1 - 30, The template.json for
the "pihole" template is missing a configs array that declares the shipped
files; add a top-level "configs" array in templates/pi-hole/template.json
listing "configs/server-http/pihole.conf" and
"configs/modsec/pihole-exclusions.conf" so every file referenced by the template
is declared (ensure the array key is "configs" and use the exact relative paths
used in the repo to match the existing files).

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
jq . templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 134


🏁 Script executed:

# Read the complete template.json file
cat -n templates/pi-hole/template.json

Repository: bunkerity/bunkerweb-templates

Length of output: 1436


🏁 Script executed:

# List all files in the pi-hole template directory
find templates/pi-hole -type f -ls

Repository: bunkerity/bunkerweb-templates

Length of output: 526


🏁 Script executed:

# Check if there are config files that should be referenced
ls -la templates/pi-hole/

Repository: bunkerity/bunkerweb-templates

Length of output: 367


Fix template.json syntax and add missing id and configs fields.

The file is missing the closing brace for the root object (line 30 ends with settings close only; jq parsing fails with "Unfinished JSON term at EOF"). Additionally, the id on line 2 is "pihole" but the template directory is pi-hole — guidelines require the id to match the directory name in lowercase-kebab-case and treat it as immutable. Finally, two config files exist in the template directory (configs/modsec/pihole-exclusions.conf and configs/server-http/pihole.conf) but are not referenced in a configs array; the template must declare its configuration dependencies for the configurator to load them.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/template.json` around lines 1 - 30, The JSON is missing the
root closing brace and must include an immutable id matching the template
directory name and a configs array listing required config paths; fix
template.json by (1) changing the "id" value from "pihole" to "pi-hole"
(lowercase-kebab-case), (2) adding a top-level "configs": [
"configs/modsec/pihole-exclusions.conf", "configs/server-http/pihole.conf" ]
entry, and (3) appending the missing closing curly brace for the root object
after the existing "settings" block so the file is valid JSON.

@@ -0,0 +1,30 @@
{
"id": "pihole",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Template ID must match the directory and kebab-case form.

Line 2 uses "pihole", but the directory is pi-hole; the ID should be "pi-hole" to stay consistent and immutable.

As per coding guidelines "id (lowercase-kebab-case, matching the template directory name, treated as immutable once published)."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/template.json` at line 2, The template's immutable id value
in template.json is incorrect: change the "id" field value from "pihole" to the
lowercase-kebab-case directory name "pi-hole" so the id matches the template
directory and follows the project's immutable id convention (update the "id"
property in template.json accordingly).

"LIMIT_CONN_MAX_HTTP3": "50",
"LIMIT_REQ_RATE": "20r/s",
"USE_METRICS": "no",
"MODSECURITY_SEC_RULE_ENGINE": "DetectionOnly",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid weakening ModSecurity posture in the default template.

Line 20 sets MODSECURITY_SEC_RULE_ENGINE to DetectionOnly, which relaxes enforcement for a production template baseline.

As per coding guidelines "ModSecurity / CRS ... Do not disable ModSecurity or the CRS in a template."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/pi-hole/template.json` at line 20, The default template currently
sets MODSECURITY_SEC_RULE_ENGINE to "DetectionOnly", which weakens enforcement;
update the template.json entry for MODSECURITY_SEC_RULE_ENGINE to an enforcing
value (e.g., "On" or "Enabled") so ModSecurity is active by default, and ensure
no other template keys disable ModSecurity or the CRS (refer to
MODSECURITY_SEC_RULE_ENGINE in the file to locate and replace the value).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants