BunkerWeb is an open-source, NGINX-based reverse proxy with a built-in WAF (ModSecurity + OWASP CRS, bot/anti-bruteforce protection, Let's Encrypt automation, etc.). This guide uses the Docker Compose deployment method, which is the most portable and easiest to maintain.
Target: Ubuntu 24.04 LTS, sudo/root SSH access.
1. Prerequisites
- A RamNode VPS with at least 1-2 vCPU / 2GB RAM
- Docker & Docker Compose plugin
- Ports
80/443free for BunkerWeb to bind to (don't run another web server directly on these ports) - DNS for the site(s) you want to protect pointed at this VPS
2. Install Docker
curl -fsSL https://get.docker.com | sudo sh
sudo systemctl enable --now dockerConfirm the Compose plugin is available:
docker compose version3. Create a project directory
mkdir -p ~/bunkerweb && cd ~/bunkerweb4. Create the docker-compose.yml
BunkerWeb's stack has three main components: bunkerweb (the proxy itself), bw-scheduler (applies config changes), and bw-ui (web admin interface) plus a database.
nano docker-compose.ymlPaste (adjust BUNKERWEB_VERSION to the current stable release, and pick strong secrets):
x-bw-env: &bw-env
API_WHITELIST_IP: "127.0.0.1 10.20.30.0/24" # internal Docker network range used by the scheduler/UI
services:
bunkerweb:
image: bunkerity/bunkerweb:1.6
ports:
- "80:8080/tcp"
- "443:8443/tcp"
- "443:8443/udp" # for HTTP/3 / QUIC
environment:
<<: *bw-env
restart: unless-stopped
networks:
- bw-universe
- bw-services
bw-scheduler:
image: bunkerity/bunkerweb-scheduler:1.6
depends_on:
- bunkerweb
environment:
<<: *bw-env
DATABASE_URI: "mariadb+pymysql://bunkerweb:${DB_PASSWORD}@bw-db:3306/db"
BUNKERWEB_INSTANCES: "bunkerweb"
SERVER_NAME: ""
MULTISITE: "yes"
UI_HOST: "http://bw-ui:7000"
volumes:
- bw-data:/data
restart: unless-stopped
networks:
- bw-universe
bw-ui:
image: bunkerity/bunkerweb-ui:1.6
depends_on:
- bw-scheduler
environment:
<<: *bw-env
DATABASE_URI: "mariadb+pymysql://bunkerweb:${DB_PASSWORD}@bw-db:3306/db"
ADMIN_USERNAME: "admin"
ADMIN_PASSWORD: "${UI_ADMIN_PASSWORD}"
restart: unless-stopped
networks:
- bw-universe
bw-db:
image: mariadb:11
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: "db"
MYSQL_USER: "bunkerweb"
MYSQL_PASSWORD: "${DB_PASSWORD}"
volumes:
- bw-db-data:/var/lib/mysql
restart: unless-stopped
networks:
- bw-universe
volumes:
bw-data:
bw-db-data:
networks:
bw-universe:
name: bw-universe
bw-services:
name: bw-servicesCheck the BunkerWeb docs for the current recommended compose file for the version you're deploying — the exact service list/env vars shift slightly between releases.
5. Create a .env file for secrets
nano .envDB_PASSWORD=change_this_to_a_strong_password
UI_ADMIN_PASSWORD=change_this_too6. Open the firewall
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udpThe bw-ui admin interface is not exposed externally by default in this layout — you'll reach it through a protected site entry (step 8) rather than a raw port, which is the safer setup.
7. Start the stack
docker compose up -d
docker compose psGive it a minute — the scheduler needs to initialize the database and generate the first NGINX config.
8. Expose the admin UI as a protected site
Rather than opening a separate port, the standard approach is to add the UI itself as a BunkerWeb-protected site so it gets HTTPS + WAF coverage. In practice:
- Point a subdomain (e.g.
bunkerweb-ui.example.com) at your VPS IP - Temporarily set
SERVER_NAMEand site-specific env vars forbw-ui's domain in the scheduler config (or via the UI's setup wizard on first run, depending on version — recent BunkerWeb releases include a first-run setup wizard reachable directly once the UI container is up) - Follow the in-UI wizard to finish bootstrapping, set the admin account, and enable Let's Encrypt for that domain
Refer to the "Quickstart guide" in the official docs for the exact current flow, since the UI onboarding has changed across versions.
9. Add your first protected application
Once logged into the UI:
- Services > New Service
- Enter the domain name (e.g.
app.example.com) - Set
REVERSE_PROXY_HOSTto your backend, e.g.http://127.0.0.1:8080or another container/IP - Enable
AUTO_LETS_ENCRYPTif you want automatic HTTPS certs for the domain - Save — the scheduler pushes the new config to the
bunkerwebproxy container automatically
10. Tune protections
Under each service's settings you can toggle:
- ModSecurity + OWASP Core Rule Set
- Antibot challenges (CAPTCHA, JS challenge, etc.)
- Rate limiting
- Country/IP allow-deny lists
- Bad bot / scanner blocking
11. Updating BunkerWeb
cd ~/bunkerweb
docker compose pull
docker compose up -dCheck the release notes before bumping major versions — schema/env var changes do happen between minor version lines.
12. Backup
Back up:
~/bunkerweb/docker-compose.ymland.env- The
bw-dataandbw-db-dataDocker volumes (docker volume inspectto find their mount points, or usedocker run --rm -v bw-db-data:/data ... tarto snapshot them)
