June 10, 2026
BunkerWeb Setup and First Tour: Complete Documentation
A practical walkthrough for deploying BunkerWeb with Docker and understanding the first screens you will see after installation.
Md. Mahim Hossain
8 min read
Introduction
BunkerWeb is an open-source Web Application Firewall and reverse proxy designed to sit in front of your services, inspect incoming traffic, and block suspicious or malicious requests before they reach your applications. In this guide, you will deploy the All-In-One Docker image, reach the web interface on your LAN IP, complete the setup wizard, and take a first tour through the dashboard, instances, services, and reports screens.
Prerequisites
Before proceeding, make sure the following basics are in place:
- A Linux host with Docker installed and running.
- Permission to publish ports
80and443on the host. - A browser on the same network so you can open the setup wizard through the host IP.
- Basic terminal access for running Docker and checking networking with
ip a.
Practical tip: If you are only testing on a local network, you can complete the first setup using the LAN address and refine public DNS or certificate settings later.
Installation
We'll begin by creating a working directory and launching the BunkerWeb Docker container.
Step 1: Creating the Working Directory & Running Docker
Open your terminal and execute the following commands to create a directory and run the container in detached mode.
mkdir BunkerWeb
cd BunkerWeb/
docker run -d \
--name bunkerweb-aio \
-v bw-storage:/data \
-p 80:8080/tcp \
-p 443:8443/tcp \
-p 443:8443/udp \
bunkerit/bunkerweb-all-in-one:1.6.11mkdir BunkerWeb
cd BunkerWeb/
docker run -d \
--name bunkerweb-aio \
-v bw-storage:/data \
-p 80:8080/tcp \
-p 443:8443/tcp \
-p 443:8443/udp \
bunkerit/bunkerweb-all-in-one:1.6.11
What this command does: it starts the BunkerWeb all-in-one container in the background, stores persistent data in the
bw-storagevolume, maps HTTP traffic from host port80to the container's internal port8080, and maps HTTPS traffic from host port443to internal port8443for both TCP and UDP.
Network Verification
To access the web interface, you need the IP address of your host machine. Run ip a and identify the active network interface. In the screenshot, the wireless interface wlo1 is up and shows the host IP address 192.168.0.209.
Note: The UI will be reachable at the host IP shown in your network configuration. For this guide, we use
192.168.0.209.
Initial Setup Wizard
Open http://192.168.0.209 in your browser to begin the setup process. If name resolution and TLS are not configured yet, starting with plain HTTP on the LAN IP is the fastest way to reach the initial wizard.
Step 1: Admin User
The first step requires creating an administrator account. Ensure you use a strong password meeting the specified criteria.
Step 2: UI Settings
This screen controls core web UI behavior. You can define the server name, decide whether to request Let's Encrypt certificates automatically, choose the challenge type, and tune certificate-related settings such as DNS provider and propagation delay. For a quick lab deployment, you can keep things simple and return later once DNS is fully in place.
Step 3: Upgrade to PRO
BunkerWeb also offers a PRO tier. This step is optional: if you already have a license, you can enter it here; otherwise, continue with the free plan and finish the deployment first. The important point is that the wizard does not block initial setup if you skip the upgrade.
Step 4: Overview
The final review screen summarizes the values entered during the wizard, including the admin username and the URL that will be used for the BunkerWeb UI. This is the right place to confirm there are no typos before clicking the final setup button.
Touring the Interface
After the wizard finishes, BunkerWeb presents the standard login form. Use the administrator credentials created in step one to sign in.
Security reminder: avoid reusing a weak lab password in production. If this instance will be exposed outside your private network, rotate credentials and confirm HTTPS is configured correctly before broad access is allowed.
Dashboard
The dashboard is the operational landing page. It summarizes plan information, memory consumption, instance count, service count, plugin count, total requests, and blocked requests. It is the fastest place to confirm that the container is alive and that BunkerWeb is already collecting traffic and security data.
Instances
The Instances page lists the BunkerWeb nodes currently registered in the platform. In a small single-node setup, this is where you verify that the local instance is present, marked healthy, and regularly seen by the UI.
Services
The Services page is where you define and manage protected applications. Each row represents a service exposed through BunkerWeb, including its type, security mode, selected template, and current state.
Reports
The Reports page gives you visibility into incoming requests and security events. This is the best place to inspect suspicious URLs, review source IP addresses, and confirm whether BunkerWeb is blocking payloads as expected.
Security and Operational Notes
- Use a strong administrator password and store it securely.
- Prefer a unique server name that matches your DNS plan before enabling public certificates.
- Keep Docker images updated so you receive security fixes and platform improvements.
- Review the Reports page regularly after publishing a service to understand normal versus suspicious traffic.
- Start with a minimal test service, validate routing and certificates, then add more applications gradually.
Recommended first validation: after login, check that the instance is healthy, confirm the service appears online, and review the reports page for the first requests reaching the platform.
Attack Perform
SQL Injection Attack
# Test command sent by attacker
curl -k -v "https://192.168.0.209/?id=1'%20OR%20'1'='1"# Test command sent by attacker
curl -k -v "https://192.168.0.209/?id=1'%20OR%20'1'='1"Step-by-step process with comments:
# ============================================
# 1. REQUEST RECEIVED BY BUNKERWEB (NGINX)
# ============================================
# Client sends: GET /?id=1' OR '1'='1
# Source IP: 192.168.0.209 (local test)
# ============================================
# 2. NGINX CONFIGURATION LOADS MODSECURITY
# ============================================
# /etc/nginx/sites-enabled/bunkerweb.conf
server {
listen 8443 ssl http2;
# ModSecurity module is enabled
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
}
# ============================================
# 3. MODSECURITY PROCESSES THE REQUEST
# ============================================
# /etc/modsec/main.conf includes OWASP CRS
Include /etc/modsec/crs/crs-setup.conf
Include /etc/modsec/crs/rules/*.conf
# ============================================
# 4. OWASP CRS RULE MATCHES SQL INJECTION
# ============================================
# Rule ID: 942100 - SQL Injection Attack Detected
# File: /etc/modsec/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
SecRule ARGS|ARGS_NAMES|REQUEST_HEADERS|XML:/* \
"@detectSQLi" \
"id:942100,\
phase:2,\
block,\
t:none,\
msg:'SQL Injection Attack Detected',\
logdata:'Matched Data: %{TX.0}',\
severity:'CRITICAL',\
setvar:'tx.sql_injection_score=+1',\
chain"
# Pattern matched: ' OR '1'='1
# This triggers the blocking action
# ============================================
# 5. BLOCKING ACTION EXECUTED
# ============================================
# ModSecurity denies the request
# Sets HTTP response to 403 Forbidden
# Adds security headers
location / {
# Request denied before reaching backend
return 403;
}
# ============================================
# 6. RESPONSE SENT BACK TO ATTACKER
# ============================================
# HTTP Response Headers:
< HTTP/2 403 Forbidden
< date: Wed, 10 Jun 2026 04:05:10 GMT
< content-type: text/html
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< strict-transport-security: max-age=63072000# ============================================
# 1. REQUEST RECEIVED BY BUNKERWEB (NGINX)
# ============================================
# Client sends: GET /?id=1' OR '1'='1
# Source IP: 192.168.0.209 (local test)
# ============================================
# 2. NGINX CONFIGURATION LOADS MODSECURITY
# ============================================
# /etc/nginx/sites-enabled/bunkerweb.conf
server {
listen 8443 ssl http2;
# ModSecurity module is enabled
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
}
# ============================================
# 3. MODSECURITY PROCESSES THE REQUEST
# ============================================
# /etc/modsec/main.conf includes OWASP CRS
Include /etc/modsec/crs/crs-setup.conf
Include /etc/modsec/crs/rules/*.conf
# ============================================
# 4. OWASP CRS RULE MATCHES SQL INJECTION
# ============================================
# Rule ID: 942100 - SQL Injection Attack Detected
# File: /etc/modsec/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
SecRule ARGS|ARGS_NAMES|REQUEST_HEADERS|XML:/* \
"@detectSQLi" \
"id:942100,\
phase:2,\
block,\
t:none,\
msg:'SQL Injection Attack Detected',\
logdata:'Matched Data: %{TX.0}',\
severity:'CRITICAL',\
setvar:'tx.sql_injection_score=+1',\
chain"
# Pattern matched: ' OR '1'='1
# This triggers the blocking action
# ============================================
# 5. BLOCKING ACTION EXECUTED
# ============================================
# ModSecurity denies the request
# Sets HTTP response to 403 Forbidden
# Adds security headers
location / {
# Request denied before reaching backend
return 403;
}
# ============================================
# 6. RESPONSE SENT BACK TO ATTACKER
# ============================================
# HTTP Response Headers:
< HTTP/2 403 Forbidden
< date: Wed, 10 Jun 2026 04:05:10 GMT
< content-type: text/html
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< strict-transport-security: max-age=63072000XSS (Cross-Site Scripting)
# Test command
curl -k -v "https://192.168.0.209/?search=<script>alert('xss')</script>"# Test command
curl -k -v "https://192.168.0.209/?search=<script>alert('xss')</script>"Process with comments:
# ============================================
# 1. MALICIOUS PAYLOAD DETECTED
# ============================================
# Payload: <script>alert('xss')</script>
# Argument: search
# ============================================
# 2. OWASP CRS XSS RULE MATCHES
# ============================================
# Rule ID: 941100 - XSS Attack Detected
# File: /etc/modsec/crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/ \
"@rx <script.*>.*</script>" \
"id:941100,\
phase:2,\
deny,\
status:403,\
msg:'XSS Attack Detected',\
logdata:'Matched Data: %{TX.0}',\
severity:'CRITICAL'"
# Pattern <script> detected → immediate DENY
# ============================================
# 3. RESPONSE: 403 FORBIDDEN
# ============================================
< HTTP/2 403 Forbidden
< content-security-policy: object-src 'none'# ============================================
# 1. MALICIOUS PAYLOAD DETECTED
# ============================================
# Payload: <script>alert('xss')</script>
# Argument: search
# ============================================
# 2. OWASP CRS XSS RULE MATCHES
# ============================================
# Rule ID: 941100 - XSS Attack Detected
# File: /etc/modsec/crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
SecRule ARGS|ARGS_NAMES|REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/ \
"@rx <script.*>.*</script>" \
"id:941100,\
phase:2,\
deny,\
status:403,\
msg:'XSS Attack Detected',\
logdata:'Matched Data: %{TX.0}',\
severity:'CRITICAL'"
# Pattern <script> detected → immediate DENY
# ============================================
# 3. RESPONSE: 403 FORBIDDEN
# ============================================
< HTTP/2 403 Forbidden
< content-security-policy: object-src 'none'Path Traversal Blocking Process
# Test command
curl -k -v "https://192.168.0.209/../../etc/passwd"# Test command
curl -k -v "https://192.168.0.209/../../etc/passwd"Process with comments:
# ============================================
# 1. PATH TRAVERSAL PATTERN DETECTED
# ============================================
# Request URI: /../../etc/passwd
# Contains directory traversal sequence: ../
# ============================================
# 2. OWASP CRS PATH TRAVERSAL RULE
# ============================================
# Rule ID: 930120 - OS File Access Attempt
# File: /etc/modsec/crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
SecRule REQUEST_URI \
"@rx \.\./|\.\.\\\\|/etc/passwd|/win\.ini" \
"id:930120,\
phase:1,\
deny,\
status:404,\
msg:'OS File Access Attempt',\
severity:'CRITICAL'"
# Matched: /etc/passwd and ../
# Action: deny with status 404 (hides existence)
# ============================================
# 3. 404 RESPONSE (NOT FOUND)
# ============================================
# Server returns 404 instead of 403
# This is a security measure - doesn't reveal if file exists
< HTTP/2 404 Not Found
< cache-control: no-cache, no-store, must-revalidate# ============================================
# 1. PATH TRAVERSAL PATTERN DETECTED
# ============================================
# Request URI: /../../etc/passwd
# Contains directory traversal sequence: ../
# ============================================
# 2. OWASP CRS PATH TRAVERSAL RULE
# ============================================
# Rule ID: 930120 - OS File Access Attempt
# File: /etc/modsec/crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
SecRule REQUEST_URI \
"@rx \.\./|\.\.\\\\|/etc/passwd|/win\.ini" \
"id:930120,\
phase:1,\
deny,\
status:404,\
msg:'OS File Access Attempt',\
severity:'CRITICAL'"
# Matched: /etc/passwd and ../
# Action: deny with status 404 (hides existence)
# ============================================
# 3. 404 RESPONSE (NOT FOUND)
# ============================================
# Server returns 404 instead of 403
# This is a security measure - doesn't reveal if file exists
< HTTP/2 404 Not Found
< cache-control: no-cache, no-store, must-revalidateComplete Request Flow Diagram With Comments
# ============================================================================
# FULL ATTACK BLOCKING PIPELINE
# ============================================================================
[CLIENT]
│
│ 1. HTTP Request with malicious payload
│ GET /?id=1'+OR+'1'='1
▼
[NGINX]
│
│ 2. Receives request on port 443 (HTTPS)
│ TLS termination handled
▼
[MODSECURITY ENGINE]
│
│ 3. Phase 1: Request Headers Inspection
│ - Check method, URI, headers
│ - No anomaly detected
▼
[MODSECURITY PHASE 2]
│
│ 4. Request Body & Arguments Inspection
│ - Parse ARGS: id=1'+OR+'1'='1
│ - Run through 200+ CRS rules
│
├─▶ Rule 942100: "@detectSQLi" → MATCH!
│
│ Action: deny, status:403, severity:CRITICAL
│
▼
[DECISION: BLOCK]
│
│ 5. ModSecurity sets:
│ - deny_status = 403
│ - error_message = "SQL Injection Attack Detected"
│
▼
[NGINX RESPONSE GENERATION]
│
│ 6. Returns 403 Forbidden with:
│ - Security headers (X-Frame-Options, CSP, etc.)
│ - HTML error page
│
▼
[CLIENT RECEIVES]
│
│ 7. HTTP/2 403 Forbidden
│ <html>403 Forbidden</html>
│
▼
[LOGGING]
│
│ 8. Attack logged to:
│ - /var/log/nginx/error.log
│ - /var/log/modsec/audit.log
│
└─▶ docker logs bunkerweb-aio (shows block entry)# ============================================================================
# FULL ATTACK BLOCKING PIPELINE
# ============================================================================
[CLIENT]
│
│ 1. HTTP Request with malicious payload
│ GET /?id=1'+OR+'1'='1
▼
[NGINX]
│
│ 2. Receives request on port 443 (HTTPS)
│ TLS termination handled
▼
[MODSECURITY ENGINE]
│
│ 3. Phase 1: Request Headers Inspection
│ - Check method, URI, headers
│ - No anomaly detected
▼
[MODSECURITY PHASE 2]
│
│ 4. Request Body & Arguments Inspection
│ - Parse ARGS: id=1'+OR+'1'='1
│ - Run through 200+ CRS rules
│
├─▶ Rule 942100: "@detectSQLi" → MATCH!
│
│ Action: deny, status:403, severity:CRITICAL
│
▼
[DECISION: BLOCK]
│
│ 5. ModSecurity sets:
│ - deny_status = 403
│ - error_message = "SQL Injection Attack Detected"
│
▼
[NGINX RESPONSE GENERATION]
│
│ 6. Returns 403 Forbidden with:
│ - Security headers (X-Frame-Options, CSP, etc.)
│ - HTML error page
│
▼
[CLIENT RECEIVES]
│
│ 7. HTTP/2 403 Forbidden
│ <html>403 Forbidden</html>
│
▼
[LOGGING]
│
│ 8. Attack logged to:
│ - /var/log/nginx/error.log
│ - /var/log/modsec/audit.log
│
└─▶ docker logs bunkerweb-aio (shows block entry)ModSecurity Audit Log Entry (Example)
# Location: /var/log/modsec/audit.log
# This is what gets recorded when an attack is blocked
--14a53e2c-A--
[10/Jun/2026:04:05:10 +0000] 192.168.0.209 443 192.168.0.209
GET /?id=1'%20OR%20'1'='1 HTTP/2.0
User-Agent: curl/8.18.0
--14a53e2c-B--
GET /?id=1'%20OR%20'1'='1 HTTP/2.0
Host: 192.168.0.209
--14a53e2c-C--
id=1' OR '1'='1
--14a53e2c-D--
# ModSecurity Intervention Details
Apache-Error: File: /etc/modsec/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Apache-Error: Line: 85
Apache-Error: RuleId: 942100
Apache-Error: Msg: SQL Injection Attack Detected
--14a53e2c-E--
HTTP/2.0 403 Forbidden
Content-Length: 146
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block# Location: /var/log/modsec/audit.log
# This is what gets recorded when an attack is blocked
--14a53e2c-A--
[10/Jun/2026:04:05:10 +0000] 192.168.0.209 443 192.168.0.209
GET /?id=1'%20OR%20'1'='1 HTTP/2.0
User-Agent: curl/8.18.0
--14a53e2c-B--
GET /?id=1'%20OR%20'1'='1 HTTP/2.0
Host: 192.168.0.209
--14a53e2c-C--
id=1' OR '1'='1
--14a53e2c-D--
# ModSecurity Intervention Details
Apache-Error: File: /etc/modsec/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Apache-Error: Line: 85
Apache-Error: RuleId: 942100
Apache-Error: Msg: SQL Injection Attack Detected
--14a53e2c-E--
HTTP/2.0 403 Forbidden
Content-Length: 146
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Troubleshooting
Common Issues:
Image Pull Issues: Ensure your Docker daemon has internet access if you see "Unable to find image locally".
Port Exposure: Verify ports 80 and 443 aren't already in use by other services like Apache or Nginx on your host.
Local IP Access: If the web UI isn't loading, re-check your IP address using
ip aand ensure firewall rules allow incoming traffic on ports 80 and 443.
Conclusion
You now have a working BunkerWeb installation, have completed the four-step wizard, and have seen the key pages that matter most on day one: dashboard, instances, services, and reports. From here, the natural next step is to publish a real service behind BunkerWeb, enable the appropriate TLS and security settings, and monitor the platform as traffic begins to flow.