Merge pull request #436 from bunkerity/staging

WIP Ui
This commit is contained in:
Théophile Diot 2023-04-18 10:29:21 +02:00 committed by GitHub
commit 535f1a0552
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 433 additions and 182 deletions

View File

@ -3,7 +3,7 @@
## Overview
<figure markdown>
![Overview](assets/img/intro-overview.svg){ align=center }
![Overview](assets/img/intro-overview.svg){ align=center, width="800" }
<figcaption>Make your web services secure by default !</figcaption>
</figure>
@ -38,7 +38,7 @@ Learn more about the core security features in the [security tuning](security-tu
## Demo
<figure markdown>
![Overwiew](assets/img/demo.gif){ align=center }
![Demo](assets/img/demo.gif){ align=center }
<figcaption>Fooling automated tools/scanners</figcaption>
</figure>

View File

@ -12,44 +12,48 @@ When settings are considered as "multiple", it means that you can have multiple
## Global settings
| Setting | Default | Context |Multiple| Description |
|-----------------------|------------------------------------------------------------------------------------------------------------------------|---------|--------|--------------------------------------------------|
|`IS_LOADING` |`no` |global |no |Internal use : set to yes when BW is loading. |
|`NGINX_PREFIX` |`/etc/nginx/` |global |no |Where nginx will search for configurations. |
|`HTTP_PORT` |`8080` |global |no |HTTP port number which bunkerweb binds to. |
|`HTTPS_PORT` |`8443` |global |no |HTTPS port number which bunkerweb binds to. |
|`MULTISITE` |`no` |global |no |Multi site activation. |
|`SERVER_NAME` |`www.example.com` |multisite|no |List of the virtual hosts served by bunkerweb. |
|`WORKER_PROCESSES` |`auto` |global |no |Number of worker processes. |
|`WORKER_RLIMIT_NOFILE` |`2048` |global |no |Maximum number of open files for worker processes.|
|`WORKER_CONNECTIONS` |`1024` |global |no |Maximum number of connections per worker. |
|`LOG_FORMAT` |`$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"`|global |no |The format to use for access logs. |
|`LOG_LEVEL` |`notice` |global |no |The level to use for error logs. |
|`DNS_RESOLVERS` |`127.0.0.11` |global |no |DNS addresses of resolvers to use. |
|`DATASTORE_MEMORY_SIZE`|`256m` |global |no |Size of the internal datastore. |
|`USE_API` |`yes` |global |no |Activate the API to control BunkerWeb. |
|`API_HTTP_PORT` |`5000` |global |no |Listen port number for the API. |
|`API_SERVER_NAME` |`bwapi` |global |no |Server name (virtual host) for the API. |
|`API_WHITELIST_IP` |`127.0.0.0/8` |global |no |List of IP/network allowed to contact the API. |
|`AUTOCONF_MODE` |`no` |global |no |Enable Autoconf Docker integration. |
|`SWARM_MODE` |`no` |global |no |Enable Docker Swarm integration. |
|`KUBERNETES_MODE` |`no` |global |no |Enable Kubernetes integration. |
| Setting | Default | Context |Multiple| Description |
|------------------------|------------------------------------------------------------------------------------------------------------------------|---------|--------|--------------------------------------------------|
|`IS_LOADING` |`no` |global |no |Internal use : set to yes when BW is loading. |
|`NGINX_PREFIX` |`/etc/nginx/` |global |no |Where nginx will search for configurations. |
|`HTTP_PORT` |`8080` |global |no |HTTP port number which bunkerweb binds to. |
|`HTTPS_PORT` |`8443` |global |no |HTTPS port number which bunkerweb binds to. |
|`MULTISITE` |`no` |global |no |Multi site activation. |
|`SERVER_NAME` |`www.example.com` |multisite|no |List of the virtual hosts served by bunkerweb. |
|`WORKER_PROCESSES` |`auto` |global |no |Number of worker processes. |
|`WORKER_RLIMIT_NOFILE` |`2048` |global |no |Maximum number of open files for worker processes.|
|`WORKER_CONNECTIONS` |`1024` |global |no |Maximum number of connections per worker. |
|`LOG_FORMAT` |`$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"`|global |no |The format to use for access logs. |
|`LOG_LEVEL` |`notice` |global |no |The level to use for error logs. |
|`DNS_RESOLVERS` |`127.0.0.11` |global |no |DNS addresses of resolvers to use. |
|`DATASTORE_MEMORY_SIZE` |`256m` |global |no |Size of the internal datastore. |
|`USE_API` |`yes` |global |no |Activate the API to control BunkerWeb. |
|`API_HTTP_PORT` |`5000` |global |no |Listen port number for the API. |
|`API_LISTEN_IP` |`0.0.0.0` |global |no |Listen IP address for the API. |
|`API_SERVER_NAME` |`bwapi` |global |no |Server name (virtual host) for the API. |
|`API_WHITELIST_IP` |`127.0.0.0/8` |global |no |List of IP/network allowed to contact the API. |
|`AUTOCONF_MODE` |`no` |global |no |Enable Autoconf Docker integration. |
|`SWARM_MODE` |`no` |global |no |Enable Docker Swarm integration. |
|`KUBERNETES_MODE` |`no` |global |no |Enable Kubernetes integration. |
|`SERVER_TYPE` |`http` |multisite|no |Server type : http or stream. |
|`LISTEN_STREAM` |`yes` |multisite|no |Enable listening for non-ssl (passthrough). |
|`LISTEN_STREAM_PORT` |`1337` |multisite|no |Listening port for non-ssl (passthrough). |
|`LISTEN_STREAM_PORT_SSL`|`4242` |multisite|no |Listening port for ssl (passthrough). |
|`USE_UDP` |`no` |multisite|no |UDP listen instead of TCP (stream). |
## Core settings
### Antibot
| Setting | Default | Context |Multiple| Description |
|---------------------------|------------|---------|--------|---------------------------------------------------------------------------------|
|`USE_ANTIBOT` |`no` |multisite|no |Activate antibot feature. |
|`ANTIBOT_URI` |`/challenge`|multisite|no |Unused URI that clients will be redirected to to solve the challenge. |
|`ANTIBOT_SESSION_SECRET` |`random` |global |no |Secret used to encrypt sessions variables for storing data related to challenges.|
|`ANTIBOT_SESSION_NAME` |`random` |global |no |Name of the cookie used by the antibot feature. |
|`ANTIBOT_RECAPTCHA_SCORE` |`0.7` |multisite|no |Minimum score required for reCAPTCHA challenge. |
|`ANTIBOT_RECAPTCHA_SITEKEY`| |multisite|no |Sitekey for reCAPTCHA challenge. |
|`ANTIBOT_RECAPTCHA_SECRET` | |multisite|no |Secret for reCAPTCHA challenge. |
|`ANTIBOT_HCAPTCHA_SITEKEY` | |multisite|no |Sitekey for hCaptcha challenge. |
|`ANTIBOT_HCAPTCHA_SECRET` | |multisite|no |Secret for hCaptcha challenge. |
| Setting | Default | Context |Multiple| Description |
|---------------------------|------------|---------|--------|---------------------------------------------------------------------|
|`USE_ANTIBOT` |`no` |multisite|no |Activate antibot feature. |
|`ANTIBOT_URI` |`/challenge`|multisite|no |Unused URI that clients will be redirected to to solve the challenge.|
|`ANTIBOT_RECAPTCHA_SCORE` |`0.7` |multisite|no |Minimum score required for reCAPTCHA challenge. |
|`ANTIBOT_RECAPTCHA_SITEKEY`| |multisite|no |Sitekey for reCAPTCHA challenge. |
|`ANTIBOT_RECAPTCHA_SECRET` | |multisite|no |Secret for reCAPTCHA challenge. |
|`ANTIBOT_HCAPTCHA_SITEKEY` | |multisite|no |Sitekey for hCaptcha challenge. |
|`ANTIBOT_HCAPTCHA_SECRET` | |multisite|no |Secret for hCaptcha challenge. |
### Auth basic
@ -69,26 +73,26 @@ When settings are considered as "multiple", it means that you can have multiple
|`BAD_BEHAVIOR_STATUS_CODES`|`400 401 403 404 405 429 444`|multisite|no |List of HTTP status codes considered as 'bad'. |
|`BAD_BEHAVIOR_BAN_TIME` |`86400` |multisite|no |The duration time (in seconds) of a ban when the corresponding IP has reached the threshold.|
|`BAD_BEHAVIOR_THRESHOLD` |`10` |multisite|no |Maximum number of 'bad' HTTP status codes within the period of time before IP is banned. |
|`BAD_BEHAVIOR_COUNT_TIME` |`60` |multisite|no |Period of time during which we count 'bad' HTTP status codes. |
|`BAD_BEHAVIOR_COUNT_TIME` |`60` |multisite|no |Period of time (in seconds) during which we count 'bad' HTTP status codes. |
### Blacklist
| Setting | Default | Context |Multiple| Description |
|----------------------------------|------------------------------------------------------------------------------------------------------------------------------|---------|--------|------------------------------------------------------------------------------------------------|
|`USE_BLACKLIST` |`yes` |multisite|no |Activate blacklist feature. |
|`BLACKLIST_IP_URLS` |`https://www.dan.me.uk/torlist/?exit` |global |no |List of URLs, separated with spaces, containing bad IP/network to block. |
|`BLACKLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to block. |
|`BLACKLIST_IP_URLS` |`https://www.dan.me.uk/torlist/?exit` |global |no |List of URLs, separated with spaces, containing bad IP/network to block. |
|`BLACKLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS blacklist checks on global IP addresses. |
|`BLACKLIST_RDNS` |`.shodan.io .censys.io` |multisite|no |List of reverse DNS suffixes, separated with spaces, to block. |
|`BLACKLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to block. |
|`BLACKLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS blacklist checks on global IP addresses. |
|`BLACKLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to block. |
|`BLACKLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to block. |
|`BLACKLIST_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to block. |
|`BLACKLIST_USER_AGENT_URLS` |`https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list`|global |no |List of URLs, separated with spaces, containing bad User-Agent to block. |
|`BLACKLIST_URI` | |multisite|no |List of URI, separated with spaces, to block. |
|`BLACKLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to block. |
|`BLACKLIST_IGNORE_IP_URLS` | |global |no |List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. |
|`BLACKLIST_IGNORE_IP` | |multisite|no |List of IP/network, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_IP_URLS` | |global |no |List of URLs, separated with spaces, containing IP/network to ignore in the blacklist. |
|`BLACKLIST_IGNORE_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to ignore in the blacklist. |
|`BLACKLIST_IGNORE_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to ignore in the blacklist.|
|`BLACKLIST_IGNORE_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to ignore in the blacklist. |
@ -128,12 +132,12 @@ When settings are considered as "multiple", it means that you can have multiple
### Client cache
| Setting | Default | Context |Multiple| Description |
|-------------------------|------------------------------------------------------------|---------|--------|-----------------------------------------------|
|`USE_CLIENT_CACHE` |`no` |multisite|no |Tell client to store locally static files. |
|`CLIENT_CACHE_EXTENSIONS`|`jpg\|jpeg\|png\|bmp\|ico\|svg\|tif\|css\|js\|otf\|ttf\|eot\|woff\|woff2`|global |no |List of file extensions that should be cached. |
|`CLIENT_CACHE_ETAG` |`yes` |multisite|no |Send the HTTP ETag header for static resources.|
|`CLIENT_CACHE_CONTROL` |`public, max-age=15552000` |multisite|no |Value of the Cache-Control HTTP header. |
| Setting | Default | Context |Multiple| Description |
|-------------------------|------------------------------------------------------------|---------|--------|--------------------------------------------------------------------|
|`USE_CLIENT_CACHE` |`no` |multisite|no |Tell client to store locally static files. |
|`CLIENT_CACHE_EXTENSIONS`|`jpg\|jpeg\|png\|bmp\|ico\|svg\|tif\|css\|js\|otf\|ttf\|eot\|woff\|woff2`|global |no |List of file extensions, separated with pipes that should be cached.|
|`CLIENT_CACHE_ETAG` |`yes` |multisite|no |Send the HTTP ETag header for static resources. |
|`CLIENT_CACHE_CONTROL` |`public, max-age=15552000` |multisite|no |Value of the Cache-Control HTTP header. |
### Country
@ -144,17 +148,17 @@ When settings are considered as "multiple", it means that you can have multiple
### Custom HTTPS certificate
| Setting |Default| Context |Multiple| Description |
|-------------------|-------|---------|--------|--------------------------------------------|
|`USE_CUSTOM_HTTPS` |`no` |multisite|no |Use custom HTTPS certificate. |
|`CUSTOM_HTTPS_CERT`| |multisite|no |Full path of the certificate or bundle file.|
|`CUSTOM_HTTPS_KEY` | |multisite|no |Full path of the key file. |
| Setting |Default| Context |Multiple| Description |
|-----------------|-------|---------|--------|--------------------------------------------|
|`USE_CUSTOM_SSL` |`no` |multisite|no |Use custom HTTPS certificate. |
|`CUSTOM_SSL_CERT`| |multisite|no |Full path of the certificate or bundle file.|
|`CUSTOM_SSL_KEY` | |multisite|no |Full path of the key file. |
### DB
| Setting | Default |Context|Multiple| Description |
|--------------|----------------------------|-------|--------|--------------------------------------------------|
|`DATABASE_URI`|`sqlite:////data/db.sqlite3`|global |no |The database URI, following the sqlalchemy format.|
| Setting | Default |Context|Multiple| Description |
|--------------|-----------------------------------------|-------|--------|--------------------------------------------------|
|`DATABASE_URI`|`sqlite:////var/lib/bunkerweb/db.sqlite3`|global |no |The database URI, following the sqlalchemy format.|
### DNSBL
@ -165,20 +169,21 @@ When settings are considered as "multiple", it means that you can have multiple
### Errors
|Setting |Default| Context |Multiple| Description |
|--------|-------|---------|--------|-------------------------------------------------------------------------------------------------|
|`ERRORS`| |multisite|no |List of HTTP error code and corresponding error pages (404=/my404.html 403=/errors/403.html ...).|
| Setting | Default | Context |Multiple| Description |
|-------------------------|-------------------------------------------------|---------|--------|------------------------------------------------------------------------------------------------------------------------|
|`ERRORS` | |multisite|no |List of HTTP error code and corresponding error pages, separated with spaces (404=/my404.html 403=/errors/403.html ...).|
|`INTERCEPTED_ERROR_CODES`|`400 401 403 404 405 413 429 500 501 502 503 504`|multisite|no |List of HTTP error code intercepted by Bunkerweb |
### Greylist
| Setting |Default| Context |Multiple| Description |
|--------------------------|-------|---------|--------|----------------------------------------------------------------------------------------------|
|`USE_GREYLIST` |`no` |multisite|no |Activate greylist feature. |
|`GREYLIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to put into the greylist. |
|`GREYLIST_IP` | |multisite|no |List of IP/network, separated with spaces, to put into the greylist. |
|`GREYLIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to put into the greylist. |
|`GREYLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS greylist checks on global IP addresses. |
|`GREYLIST_RDNS` | |multisite|no |List of reverse DNS suffixes, separated with spaces, to put into the greylist. |
|`GREYLIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to put into the greylist.|
|`GREYLIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS greylist checks on global IP addresses. |
|`GREYLIST_ASN` | |multisite|no |List of ASN numbers, separated with spaces, to put into the greylist. |
|`GREYLIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to put into the greylist. |
|`GREYLIST_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to put into the greylist. |
@ -203,20 +208,20 @@ When settings are considered as "multiple", it means that you can have multiple
### Headers
| Setting | Default | Context |Multiple| Description |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|----------------------------------------------------------------------------------------------|
|`CUSTOM_HEADER` | |multisite|yes |Custom header to add (HeaderName: HeaderValue). |
|`REMOVE_HEADERS` |`Server X-Powered-By X-AspNet-Version X-AspNetMvc-Version` |multisite|no |Headers to remove (Header1 Header2 Header3 ...) |
|`STRICT_TRANSPORT_SECURITY`|`max-age=31536000` |multisite|no |Value for the Strict-Transport-Security header. |
|`COOKIE_FLAGS` |`* HttpOnly SameSite=Lax` |multisite|no |Cookie flags automatically added to all cookies (value accepted for nginx_cookie_flag_module).|
|`COOKIE_AUTO_SECURE_FLAG` |`yes` |multisite|no |Automatically add the Secure flag to all cookies. |
|`CONTENT_SECURITY_POLICY` |`object-src 'none'; form-action 'self'; frame-ancestors 'self';` |multisite|no |Value for the Content-Security-Policy header. |
|`REFERRER_POLICY` |`strict-origin-when-cross-origin` |multisite|no |Value for the Referrer-Policy header. |
|`PERMISSIONS_POLICY` |`accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), web-share=(), xr-spatial-tracking=()` |multisite|no |Value for the Permissions-Policy header. |
|`FEATURE_POLICY` |`accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; fullscreen 'none'; 'none'; geolocation 'none'; gyroscope 'none'; layout-animation 'none'; legacy-image-formats 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; speaker-selection 'none'; sync-xhr 'none'; unoptimized-images 'none'; unsized-media 'none'; usb 'none'; screen-wake-lock 'none'; web-share 'none'; xr-spatial-tracking 'none';`|multisite|no |Value for the Feature-Policy header. |
|`X_FRAME_OPTIONS` |`SAMEORIGIN` |multisite|no |Value for the X-Frame-Options header. |
|`X_CONTENT_TYPE_OPTIONS` |`nosniff` |multisite|no |Value for the X-Content-Type-Options header. |
|`X_XSS_PROTECTION` |`1; mode=block` |multisite|no |Value for the X-XSS-Protection header. |
| Setting | Default | Context |Multiple| Description |
|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|----------------------------------------------------------------------------------------------|
|`CUSTOM_HEADER` | |multisite|yes |Custom header to add (HeaderName: HeaderValue). |
|`REMOVE_HEADERS` |`Server X-Powered-By X-AspNet-Version X-AspNetMvc-Version` |multisite|no |Headers to remove (Header1 Header2 Header3 ...) |
|`STRICT_TRANSPORT_SECURITY`|`max-age=31536000` |multisite|no |Value for the Strict-Transport-Security header. |
|`COOKIE_FLAGS` |`* HttpOnly SameSite=Lax` |multisite|yes |Cookie flags automatically added to all cookies (value accepted for nginx_cookie_flag_module).|
|`COOKIE_AUTO_SECURE_FLAG` |`yes` |multisite|no |Automatically add the Secure flag to all cookies. |
|`CONTENT_SECURITY_POLICY` |`object-src 'none'; form-action 'self'; frame-ancestors 'self';` |multisite|no |Value for the Content-Security-Policy header. |
|`REFERRER_POLICY` |`strict-origin-when-cross-origin` |multisite|no |Value for the Referrer-Policy header. |
|`PERMISSIONS_POLICY` |`accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), web-share=(), xr-spatial-tracking=()` |multisite|no |Value for the Permissions-Policy header. |
|`FEATURE_POLICY` |`accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; battery 'none'; camera 'none'; display-capture 'none'; document-domain 'none'; encrypted-media 'none'; execution-while-not-rendered 'none'; execution-while-out-of-viewport 'none'; fullscreen 'none'; geolocation 'none'; gyroscope 'none'; layout-animation 'none'; legacy-image-formats 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; navigation-override 'none'; payment 'none'; picture-in-picture 'none'; publickey-credentials-get 'none'; speaker-selection 'none'; sync-xhr 'none'; unoptimized-images 'none'; unsized-media 'none'; usb 'none'; screen-wake-lock 'none'; web-share 'none'; xr-spatial-tracking 'none';`|multisite|no |Value for the Feature-Policy header. |
|`X_FRAME_OPTIONS` |`SAMEORIGIN` |multisite|no |Value for the X-Frame-Options header. |
|`X_CONTENT_TYPE_OPTIONS` |`nosniff` |multisite|no |Value for the X-Content-Type-Options header. |
|`X_XSS_PROTECTION` |`1; mode=block` |multisite|no |Value for the X-XSS-Protection header. |
### Let's Encrypt
@ -244,11 +249,11 @@ When settings are considered as "multiple", it means that you can have multiple
|`DISABLE_DEFAULT_SERVER` |`no` |global |no |Close connection if the request vhost is unknown. |
|`REDIRECT_HTTP_TO_HTTPS` |`no` |multisite|no |Redirect all HTTP request to HTTPS. |
|`AUTO_REDIRECT_HTTP_TO_HTTPS`|`yes` |multisite|no |Try to detect if HTTPS is used and activate HTTP to HTTPS redirection if that's the case. |
|`ALLOWED_METHODS` |`GET\|POST\|HEAD` |multisite|no |Allowed HTTP methods to be sent by clients. |
|`ALLOWED_METHODS` |`GET\|POST\|HEAD` |multisite|no |Allowed HTTP and WebDAV methods, separated with pipes to be sent by clients. |
|`MAX_CLIENT_SIZE` |`10m` |multisite|no |Maximum body size (0 for infinite). |
|`SERVE_FILES` |`yes` |multisite|no |Serve files from the local folder. |
|`ROOT_FOLDER` | |multisite|no |Root folder containing files to serve (/var/www/html/{server_name} if unset). |
|`HTTPS_PROTOCOLS` |`TLSv1.2 TLSv1.3` |multisite|no |The supported version of TLS. We recommend the default value TLSv1.2 TLSv1.3 for compatibility reasons. |
|`SSL_PROTOCOLS` |`TLSv1.2 TLSv1.3` |multisite|no |The supported version of TLS. We recommend the default value TLSv1.2 TLSv1.3 for compatibility reasons. |
|`HTTP2` |`yes` |multisite|no |Support HTTP2 protocol when HTTPS is enabled. |
|`LISTEN_HTTP` |`yes` |multisite|no |Respond to (insecure) HTTP requests. |
|`USE_OPEN_FILE_CACHE` |`no` |multisite|no |Enable open file cache feature |
@ -280,14 +285,14 @@ When settings are considered as "multiple", it means that you can have multiple
### Real IP
| Setting | Default | Context |Multiple| Description |
|--------------------|-----------------------------------------|---------|--------|--------------------------------------------------------------------------------------|
|`USE_REAL_IP` |`no` |multisite|no |Retrieve the real IP of client. |
|`USE_PROXY_PROTOCOL`|`no` |multisite|no |Enable PROXY protocol communication. |
|`REAL_IP_FROM` |`192.168.0.0/16 172.16.0.0/12 10.0.0.0/8`|multisite|no |List of trusted IPs / networks where proxied requests come from. |
|`REAL_IP_FROM_URLS` | |global |no |List of URLs containing trusted IPs / networks where proxied requests come from. |
|`REAL_IP_HEADER` |`X-Forwarded-For` |multisite|no |HTTP header containing the real IP or special value proxy_protocol for PROXY protocol.|
|`REAL_IP_RECURSIVE` |`yes` |multisite|no |Perform a recursive search in the header container IP address. |
| Setting | Default | Context |Multiple| Description |
|--------------------|-----------------------------------------|---------|--------|--------------------------------------------------------------------------------------------------------|
|`USE_REAL_IP` |`no` |multisite|no |Retrieve the real IP of client. |
|`USE_PROXY_PROTOCOL`|`no` |multisite|no |Enable PROXY protocol communication. |
|`REAL_IP_FROM` |`192.168.0.0/16 172.16.0.0/12 10.0.0.0/8`|multisite|no |List of trusted IPs / networks, separated with spaces, where proxied requests come from. |
|`REAL_IP_FROM_URLS` | |global |no |List of URLs containing trusted IPs / networks, separated with spaces, where proxied requests come from.|
|`REAL_IP_HEADER` |`X-Forwarded-For` |multisite|no |HTTP header containing the real IP or special value proxy_protocol for PROXY protocol. |
|`REAL_IP_RECURSIVE` |`yes` |multisite|no |Perform a recursive search in the header container IP address. |
### Redirect
@ -296,44 +301,75 @@ When settings are considered as "multiple", it means that you can have multiple
|`REDIRECT_TO` | |multisite|no |Redirect a whole site to another one. |
|`REDIRECT_TO_REQUEST_URI`|`no` |multisite|no |Append the requested URI to the redirect address.|
### Redis
| Setting |Default|Context|Multiple| Description |
|----------------------|-------|-------|--------|------------------------------------------------------------------|
|`USE_REDIS` |`no` |global |no |Activate Redis. |
|`REDIS_HOST` | |global |no |Redis server IP or hostname. |
|`REDIS_PORT` |`6379` |global |no |Redis server port. |
|`REDIS_DATABASE` |`0` |global |no |Redis database number. |
|`REDIS_SSL` |`no` |global |no |Use SSL/TLS connection with Redis server. |
|`REDIS_TIMEOUT` |`1000` |global |no |Redis server timeout (in ms) for connect, read and write. |
|`REDIS_KEEPALIVE_IDLE`|`30000`|global |no |Max idle time (in ms) before closing redis connection in the pool.|
|`REDIS_KEEPALIVE_POOL`|`10` |global |no |Max number of redis connection(s) kept in the pool. |
### Reverse proxy
| Setting | Default | Context |Multiple| Description |
|---------------------------------------|----------------------------------|---------|--------|--------------------------------------------------------------------------------------------------------------------|
|`USE_REVERSE_PROXY` |`no` |multisite|no |Activate reverse proxy mode. |
|`REVERSE_PROXY_INTERCEPT_ERRORS` |`yes` |multisite|no |Intercept and rewrite errors. |
|`REVERSE_PROXY_HOST` | |multisite|yes |Full URL of the proxied resource (proxy_pass). |
|`REVERSE_PROXY_URL` | |multisite|yes |Location URL that will be proxied. |
|`REVERSE_PROXY_WS` |`no` |multisite|yes |Enable websocket on the proxied resource. |
|`REVERSE_PROXY_HEADERS` | |multisite|yes |List of HTTP headers to send to proxied resource separated with ; (values for proxy_set_header directive). |
|`REVERSE_PROXY_HEADERS_CLIENT` | |multisite|yes |List of HTTP headers to send to client separated with ; (values for add_header directive). |
|`REVERSE_PROXY_BUFFERING` |`yes` |multisite|yes |Enable or disable buffering of responses from proxied resource. |
|`REVERSE_PROXY_KEEPALIVE` |`no` |multisite|yes |Enable or disable keepalive connections with the proxied resource. |
|`REVERSE_PROXY_AUTH_REQUEST` | |multisite|yes |Enable authentication using an external provider (value of auth_request directive). |
|`REVERSE_PROXY_AUTH_REQUEST_SIGNIN_URL`| |multisite|yes |Redirect clients to sign-in URL when using REVERSE_PROXY_AUTH_REQUEST (used when auth_request call returned 401). |
|`REVERSE_PROXY_AUTH_REQUEST_SET` | |multisite|yes |List of variables to set from the authentication provider, separated with ; (values of auth_request_set directives).|
|`USE_PROXY_CACHE` |`no` |multisite|no |Enable or disable caching of the proxied resources. |
|`PROXY_CACHE_PATH_LEVELS` |`1:2` |global |no |Hierarchy levels of the cache. |
|`PROXY_CACHE_PATH_ZONE_SIZE` |`10m` |global |no |Maximum size of cached metadata when caching proxied resources. |
|`PROXY_CACHE_PATH_PARAMS` |`max_size=100m` |global |no |Additional parameters to add to the proxy_cache directive. |
|`PROXY_CACHE_METHODS` |`GET HEAD` |multisite|no |HTTP methods that should trigger a cache operation. |
|`PROXY_CACHE_MIN_USES` |`2` |multisite|no |The minimum number of requests before a response is cached. |
|`PROXY_CACHE_KEY` |`$scheme$host$request_uri` |multisite|no |The key used to uniquely identify a cached response. |
|`PROXY_CACHE_VALID` |`200=24h 301=1h 302=24h` |multisite|no |Define the caching time depending on the HTTP status code (list of status=time). |
|`PROXY_NO_CACHE` |`$http_pragma $http_authorization`|multisite|no |Conditions to disable caching of responses. |
|`PROXY_CACHE_BYPASS` |`0` |multisite|no |Conditions to bypass caching of responses. |
|`REVERSE_PROXY_CONNECT_TIMEOUT` |`60s` |multisite|yes |Timeout when connecting to the proxied resource. |
|`REVERSE_PROXY_READ_TIMEOUT` |`60s` |multisite|yes |Timeout when reading from the proxied resource. |
|`REVERSE_PROXY_SEND_TIMEOUT` |`60s` |multisite|yes |Timeout when sending to the proxied resource. |
| Setting | Default | Context |Multiple| Description |
|---------------------------------------|----------------------------------|---------|--------|-----------------------------------------------------------------------------------------------------------------------------|
|`USE_REVERSE_PROXY` |`no` |multisite|no |Activate reverse proxy mode. |
|`REVERSE_PROXY_INTERCEPT_ERRORS` |`yes` |multisite|no |Intercept and rewrite errors. |
|`REVERSE_PROXY_HOST` | |multisite|yes |Full URL of the proxied resource (proxy_pass). |
|`REVERSE_PROXY_URL` | |multisite|yes |Location URL that will be proxied. |
|`REVERSE_PROXY_WS` |`no` |multisite|yes |Enable websocket on the proxied resource. |
|`REVERSE_PROXY_HEADERS` | |multisite|yes |List of HTTP headers to send to proxied resource separated with semicolons (values for proxy_set_header directive). |
|`REVERSE_PROXY_HEADERS_CLIENT` | |multisite|yes |List of HTTP headers to send to client separated with semicolons (values for add_header directive). |
|`REVERSE_PROXY_BUFFERING` |`yes` |multisite|yes |Enable or disable buffering of responses from proxied resource. |
|`REVERSE_PROXY_KEEPALIVE` |`no` |multisite|yes |Enable or disable keepalive connections with the proxied resource. |
|`REVERSE_PROXY_AUTH_REQUEST` | |multisite|yes |Enable authentication using an external provider (value of auth_request directive). |
|`REVERSE_PROXY_AUTH_REQUEST_SIGNIN_URL`| |multisite|yes |Redirect clients to sign-in URL when using REVERSE_PROXY_AUTH_REQUEST (used when auth_request call returned 401). |
|`REVERSE_PROXY_AUTH_REQUEST_SET` | |multisite|yes |List of variables to set from the authentication provider, separated with semicolons (values of auth_request_set directives).|
|`USE_PROXY_CACHE` |`no` |multisite|no |Enable or disable caching of the proxied resources. |
|`PROXY_CACHE_PATH_LEVELS` |`1:2` |global |no |Hierarchy levels of the cache. |
|`PROXY_CACHE_PATH_ZONE_SIZE` |`10m` |global |no |Maximum size of cached metadata when caching proxied resources. |
|`PROXY_CACHE_PATH_PARAMS` |`max_size=100m` |global |no |Additional parameters to add to the proxy_cache directive. |
|`PROXY_CACHE_METHODS` |`GET HEAD` |multisite|no |HTTP methods that should trigger a cache operation. |
|`PROXY_CACHE_MIN_USES` |`2` |multisite|no |The minimum number of requests before a response is cached. |
|`PROXY_CACHE_KEY` |`$scheme$host$request_uri` |multisite|no |The key used to uniquely identify a cached response. |
|`PROXY_CACHE_VALID` |`200=24h 301=1h 302=24h` |multisite|no |Define the caching time depending on the HTTP status code (list of status=time), separated with spaces. |
|`PROXY_NO_CACHE` |`$http_pragma $http_authorization`|multisite|no |Conditions to disable caching of responses. |
|`PROXY_CACHE_BYPASS` |`0` |multisite|no |Conditions to bypass caching of responses. |
|`REVERSE_PROXY_CONNECT_TIMEOUT` |`60s` |multisite|yes |Timeout when connecting to the proxied resource. |
|`REVERSE_PROXY_READ_TIMEOUT` |`60s` |multisite|yes |Timeout when reading from the proxied resource. |
|`REVERSE_PROXY_SEND_TIMEOUT` |`60s` |multisite|yes |Timeout when sending to the proxied resource. |
### Reverse scan
| Setting | Default | Context |Multiple| Description |
|----------------------|--------------------------|---------|--------|------------------------------------------------------------------|
|`USE_REVERSE_SCAN` |`no` |multisite|no |Enable scanning of clients ports and deny access if one is opened.|
|`REVERSE_SCAN_PORTS` |`22 80 443 3128 8000 8080`|multisite|no |List of port to scan when using reverse scan feature. |
|`REVERSE_SCAN_TIMEOUT`|`500` |multisite|no |Specify the maximum timeout (in ms) when scanning a port. |
### Self-signed certificate
| Setting | Default | Context |Multiple| Description |
|--------------------------|----------------------|---------|--------|-----------------------------------------|
|`GENERATE_SELF_SIGNED_SSL`|`no` |multisite|no |Generate and use self-signed certificate.|
|`SELF_SIGNED_SSL_EXPIRY` |`365` |multisite|no |Self-signed certificate expiry. |
|`SELF_SIGNED_SSL_EXPIRY` |`365` |multisite|no |Self-signed certificate expiry in days. |
|`SELF_SIGNED_SSL_SUBJ` |`/CN=www.example.com/`|multisite|no |Self-signed certificate subject. |
### Sessions
| Setting |Default |Context|Multiple| Description |
|---------------------------|--------|-------|--------|---------------------------------------------------------------------------------|
|`SESSIONS_SECRET` |`random`|global |no |Secret used to encrypt sessions variables for storing data related to challenges.|
|`SESSIONS_NAME` |`random`|global |no |Name of the cookie given to clients. |
|`SESSIONS_IDLING_TIMEOUT` |`1800` |global |no |Maximum time (in seconds) of inactivity before the session is invalidated. |
|`SESSIONS_ROLLING_TIMEOUT` |`3600` |global |no |Maximum time (in seconds) before a session must be renewed. |
|`SESSIONS_ABSOLUTE_TIMEOUT`|`86400` |global |no |Maximum time (in seconds) before a session is destroyed. |
### UI
|Setting |Default| Context |Multiple|Description|
@ -345,11 +381,11 @@ When settings are considered as "multiple", it means that you can have multiple
| Setting | Default | Context |Multiple| Description |
|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|----------------------------------------------------------------------------------|
|`USE_WHITELIST` |`yes` |multisite|no |Activate whitelist feature. |
|`WHITELIST_IP` |`20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247 54.208.102.37 107.21.1.8`|multisite|no |List of IP/network, separated with spaces, to put into the whitelist. |
|`WHITELIST_IP_URLS` | |global |no |List of URLs, separated with spaces, containing good IP/network to whitelist. |
|`WHITELIST_IP` |`20.191.45.212 40.88.21.235 40.76.173.151 40.76.163.7 20.185.79.47 52.142.26.175 20.185.79.15 52.142.24.149 40.76.162.208 40.76.163.23 40.76.162.191 40.76.162.247 54.208.102.37 107.21.1.8`|multisite|no |List of IP/network, separated with spaces, to whitelist. |
|`WHITELIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS whitelist checks on global IP addresses. |
|`WHITELIST_RDNS` |`.google.com .googlebot.com .yandex.ru .yandex.net .yandex.com .search.msn.com .baidu.com .baidu.jp .crawl.yahoo.net .fwd.linkedin.com .twitter.com .twttr.com .discord.com` |multisite|no |List of reverse DNS suffixes, separated with spaces, to whitelist. |
|`WHITELIST_RDNS_URLS` | |global |no |List of URLs, separated with spaces, containing reverse DNS suffixes to whitelist.|
|`WHITELIST_RDNS_GLOBAL` |`yes` |multisite|no |Only perform RDNS whitelist checks on global IP addresses. |
|`WHITELIST_ASN` |`32934` |multisite|no |List of ASN numbers, separated with spaces, to whitelist. |
|`WHITELIST_ASN_URLS` | |global |no |List of URLs, separated with spaces, containing ASN to whitelist. |
|`WHITELIST_USER_AGENT` | |multisite|no |List of User-Agent, separated with spaces, to whitelist. |

View File

@ -1,8 +1,5 @@
# Web UI
!!! note "Supported integrations"
At the moment, the web UI is only supported with the [Docker](/1.4/integrations/#docker), [Linux](/1.4/integrations/#linux) and [Ansible](/1.4/integrations/#ansible) integrations. It's not possible to use the web UI with other integrations like [Docker autoconf](/1.4/integrations/#docker-autoconf), [Swarm](/1.4/integrations/#swarm) or [Kubernetes](/1.4/integrations/#kubernetes). Please note that we plan to support more integrations as the project evolves.
## Overview
<p align="center">
@ -39,53 +36,50 @@ Because the web UI is a web application, the recommended installation procedure
!!! info "UI specific env variables"
* Don't forget to add `USE_UI` environnement variable as it adds the security rules needed for `Modsecurity` to work with the UI.
* Also add the `REVERSE_PROXY_INTERCEPT_ERRORS` environnement variable to stop Bunkerweb from intercepting HTTP errors.
* Also it is advised to tweak the `INTERCEPTED_ERROR_CODES` setting to stop Bunkerweb from intercepting certain HTTP errors.
=== "Docker"
When using the [Docker integration](/1.4/integrations/#docker), we recommend you to connect the BunkerWeb and web UI using a dedicated network and use another dedicated network for the communications between BunkerWeb and your web applications. The web UI can be deployed using a dedicated container based on the [bunkerweb-ui image](https://hub.docker.com/r/bunkerity/bunkerweb-ui).
When using the [Docker integration](/1.4/integrations/#docker), we recommend you to connect BunkerWeb and web UI using a dedicated network like with the scheduler and use another dedicated network for the communications between BunkerWeb and your web applications. The web UI can be deployed using a dedicated container based on the [bunkerweb-ui image](https://hub.docker.com/r/bunkerity/bunkerweb-ui).
Let's start by creating the networks (replace 10.20.30.0/24 with an unused network of your choice) :
```shell
docker network create --subnet 10.20.30.0/24 bw-ui && \
docker network create --subnet 10.20.30.0/24 bw-universe && \
docker network create bw-services
```
You will also need two volumes, one for the BunkerWeb data and another one to share the configuration files between the web UI and BunkerWeb :
You will also need the data volume, which where BunkerWeb's data will be stored :
```shell
docker volume create bw-data && \
docker volume create bw-confs
docker volume create bw-data
```
You can now create the BunkerWeb container with specific settings and volumes related to the web UI, please note the special `bunkerweb.UI` label which is mandatory :
You can now create the BunkerWeb container with specific settings related to the web UI, please note the special `bunkerweb.INSTANCE` label which is mandatory for the scheduler as well as the web UI to work properly :
```shell
docker run -d \
--name mybunker \
--name bunkerweb \
--network bw-services \
-p 80:8080 \
-p 443:8443 \
-v bw-data:/data \
-v bw-confs:/etc/nginx \
-e SERVER_NAME=bwadm.example.com \
-e MULTISITE=yes \
-e "API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24" \
-e bwadm.example.com_USE_UI=yes \
-e bwadm.example.com_USE_REVERSE_PROXY=yes \
-e bwadm.example.com_REVERSE_PROXY_URL=/changeme/ \
-e bwadm.example.com_REVERSE_PROXY_HOST=http://myui:7000 \
-e bwadm.example.com_REVERSE_PROXY_HOST=http://bw-ui:7000 \
-e "bwadm.example.com_REVERSE_PROXY_HEADERS=X-Script-Name /changeme" \
-e bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS=no \
-l bunkerweb.UI \
-e bwadm.example.com_INTERCEPTED_ERROR_CODES="400 401 405 413 429 500 501 502 503 504" \
-l bunkerweb.INSTANCE \
bunkerity/bunkerweb:1.4.6 && \
docker network connect bw-ui mybunker
docker network connect bw-universe bunkerweb
```
Important things to note :
* `bwadm.example.com` is the dedicated (sub)domain for accessing the web UI
* replace `10.20.30.0/24` with the same network address used for the `bw-ui` network
* replace `10.20.30.0/24` with the same network address used for the `bw-universe` network
* replace the `/changeme` URL with a custom one of your choice
* the `bunkerweb.UI` label is mandatory
* the `bunkerweb.INSTANCE` label is mandatory
The web UI will need to access the Docker API in order to get metadata about the running containers. It can be done easily by mounting the **docker.sock** file into the container. But there is a security risk : if the web UI is exploited, all your container(s) and the host will be impacted because, at the moment, Docker doesn't provide any restriction feature. We highly recommend using something like a [docker socket proxy](https://github.com/Tecnativa/docker-socket-proxy) to mitigate that risk (only a subset of read-only API endpoints will be available to the web UI container).
@ -97,26 +91,36 @@ Because the web UI is a web application, the recommended installation procedure
Once the network is created, you can now create the docker socket proxy container :
```shell
docker run -d \
--name mydocker \
--name bw-docker \
--network bw-docker \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-e CONTAINERS=1 \
tecnativa/docker-socket-proxy
```
You can then create the scheduler container with the bw-data volume and the docker socket proxy network :
```shell
docker run -d \
--name bw-scheduler \
--network bw-universe \
-v bw-data:/data \
-e DOCKER_HOST=tcp://bw-docker:2375 \
bunkerity/bunkerweb-scheduler:1.4.6 && \
docker network connect bw-docker bw-scheduler
```
We can finally create the web UI container :
```shell
docker run -d \
--name myui \
--network bw-ui \
--name bw-ui \
--network bw-universe \
-v bw-data:/data \
-v bw-confs:/etc/nginx \
-e DOCKER_HOST=tcp://mydocker:2375 \
-e DOCKER_HOST=tcp://bw-docker:2375 \
-e ADMIN_USERNAME=admin \
-e ADMIN_PASSWORD=changeme \
-e ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/ \
bunkerity/bunkerweb-ui:1.4.6 && \
docker network connect bw-docker myui
docker network connect bw-docker bw-ui
```
Important things to note :
@ -126,20 +130,14 @@ Because the web UI is a web application, the recommended installation procedure
Here is the docker-compose equivalent :
```yaml
version: '3'
version: "3"
services:
mybunker:
bunkerweb:
image: bunkerity/bunkerweb:1.4.6
networks:
- bw-services
- bw-ui
ports:
- 80:8080
volumes:
- bw-data:/data
- bw-confs:/etc/nginx
- "80:8080"
- "443:8443"
environment:
- SERVER_NAME=bwadm.example.com
- MULTISITE=yes
@ -147,51 +145,258 @@ Because the web UI is a web application, the recommended installation procedure
- bwadm.example.com_USE_UI=yes
- bwadm.example.com_USE_REVERSE_PROXY=yes
- bwadm.example.com_REVERSE_PROXY_URL=/changeme/
- bwadm.example.com_REVERSE_PROXY_HOST=http://myui:7000
- bwadm.example.com_REVERSE_PROXY_HOST=http://bw-ui:7000
- bwadm.example.com_REVERSE_PROXY_HEADERS=X-Script-Name /changeme
- bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS=no
labels:
- "bunkerweb.UI"
myui:
image: bunkerity/bunkerweb-ui:1.4.6
depends_on:
- mydocker
- "bunkerweb.INSTANCE"
networks:
- bw-ui
- bw-docker
- bw-universe
- bw-services
bw-scheduler:
image: bunkerity/bunkerweb-scheduler:1.4.6
volumes:
- bw-data:/data
- bw-confs:/etc/nginx
environment:
- DOCKER_HOST=tcp://mydocker:2375
- DOCKER_HOST=tcp://bw-docker:2375
networks:
- bw-universe
- bw-docker
bw-ui:
image: bunkerity/bunkerweb-ui:1.4.6
volumes:
- bw-data:/data
environment:
- DOCKER_HOST=tcp://bw-docker:2375
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=changeme
- ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/
mydocker:
image: tecnativa/docker-socket-proxy
networks:
- bw-docker
- bw-universe
bw-docker:
image: tecnativa/docker-socket-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- CONTAINERS=1
networks:
- bw-docker
volumes:
bw-data:
networks:
bw-services:
bw-ui:
bw-universe:
name: bw-universe
ipam:
driver: default
config:
- subnet: 10.20.30.0/24
bw-services:
bw-docker:
```
=== "Docker autoconf"
When using the [Docker autoconf integration](/1.4/integrations/#docker-autoconf), we recommend you to connect the Autoconf and web UI containers using a dedicated network like with the scheduler and use another dedicated network for the communications between BunkerWeb and your web applications. The web UI can be deployed using a dedicated container based on the [bunkerweb-ui image](https://hub.docker.com/r/bunkerity/bunkerweb-ui).
Let's start by creating the networks (replace 10.20.30.0/24 with an unused network of your choice) :
```shell
docker network create --subnet 10.20.30.0/24 bw-universe && \
docker network create bw-services
```
You will also need the data volume, which where BunkerWeb's data will be stored :
```shell
docker volume create bw-data
```
You can now create the BunkerWeb container, please note the special `bunkerweb.INSTANCE` label which is mandatory for the scheduler as well as the web UI to work properly :
```shell
docker run -d \
--name bunkerweb \
--network bw-universe \
-p 80:8080 \
-p 443:8443 \
-e SERVER_NAME= \
-e MULTISITE=yes \
-e "API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24" \
-l bunkerweb.INSTANCE \
bunkerity/bunkerweb:1.4.6
```
Important things to note :
* replace `10.20.30.0/24` with the same network address used for the `bw-universe` network
* the `bunkerweb.INSTANCE` label is mandatory
The Autoconf and web UI will need to access the Docker API in order to get metadata about the running containers. It can be done easily by mounting the **docker.sock** file into the container. But there is a security risk : if the web UI is exploited, all your container(s) and the host will be impacted because, at the moment, Docker doesn't provide any restriction feature. We highly recommend using something like a [docker socket proxy](https://github.com/Tecnativa/docker-socket-proxy) to mitigate that risk (only a subset of read-only API endpoints will be available to the web UI container).
To connect the docker socket proxy and the web UI, you will need another network :
```shell
docker network create bw-docker
```
Once the network is created, you can now create the docker socket proxy container :
```shell
docker run -d \
--name bw-docker \
--network bw-docker \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-e CONTAINERS=1 \
tecnativa/docker-socket-proxy
```
You can then create the autoconf container connected to the docker socket proxy network :
```shell
docker run -d \
--name bw-autoconf \
--network bw-universe \
-v bw-data:/data \
-e DOCKER_HOST=tcp://bw-docker:2375 \
bunkerity/bunkerweb-autoconf:1.4.6 && \
docker network connect bw-docker bw-autoconf
```
You can then create the scheduler container with the bw-data volume and the docker socket proxy network :
```shell
docker run -d \
--name bw-scheduler \
--network bw-universe \
-v bw-data:/data \
-e DOCKER_HOST=tcp://bw-docker:2375 \
bunkerity/bunkerweb-scheduler:1.4.6 && \
docker network connect bw-docker bw-scheduler
```
We can finally create the web UI container :
```shell
docker run -d \
--name bw-ui \
--network bw-universe \
-v bw-data:/data \
-e DOCKER_HOST=tcp://bw-docker:2375 \
-e ADMIN_USERNAME=admin \
-e ADMIN_PASSWORD=changeme \
-e ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/ \
-l "bunkerweb.SERVER_NAME=bwadm.example.com" \
-l "bunkerweb.USE_UI=yes" \
-l "bunkerweb.USE_REVERSE_PROXY=yes" \
-l "bunkerweb.REVERSE_PROXY_URL=/changeme" \
-l "bunkerweb.REVERSE_PROXY_HOST=http://bw-ui:7000" \
-l "bunkerweb.REVERSE_PROXY_HEADERS=X-Script-Name /changeme" \
-l "bunkerweb.INTERCEPTED_ERROR_CODES=400 401 404 405 413 429 500 501 502 503 504" \
bunkerity/bunkerweb-ui:1.4.6 && \
docker network connect bw-docker bw-ui
```
Important things to note :
* `bwadm.example.com` is the dedicated (sub)domain for accessing the web UI
* replace the `/changeme` URL with a custom one of your choice
* `http(s)://bwadmin.example.com/changeme/` is the full base URL of the web UI (must match the sub(domain) and /changeme URL used when creating the BunkerWeb container)
* Replace the username `admin` and password `changeme` with strong ones
Here is the docker-compose equivalent :
```yaml
version: "3.5"
services:
bunkerweb:
image: bunkerity/bunkerweb:1.4.6
ports:
- 80:8080
- 443:8443
labels:
- "bunkerweb.INSTANCE"
environment:
- SERVER_NAME=
- MULTISITE=yes
- API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24
- AUTOCONF_MODE=yes
networks:
- bw-universe
- bw-services
bw-autoconf:
image: bunkerity/bunkerweb-autoconf:1.4.6
volumes:
- bw-data:/data
environment:
- DOCKER_HOST=tcp://bw-docker:2375
networks:
- bw-universe
- bw-docker
bw-scheduler:
image: bunkerity/bunkerweb-scheduler:1.4.6
volumes:
- bw-data:/data
environment:
- DOCKER_HOST=tcp://bw-docker:2375
- AUTOCONF_MODE=yes
networks:
- bw-universe
- bw-docker
bw-docker:
image: tecnativa/docker-socket-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- CONTAINERS=1
networks:
- bw-docker
bw-ui:
image: bunkerity/bunkerweb-ui:1.4.6
networks:
bw-docker:
bw-universe:
aliases:
- bw-ui
volumes:
- bw-data:/data
environment:
- DOCKER_HOST=tcp://bw-docker:2375
- AUTOCONF_MODE=yes
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=changeme
- ABSOLUTE_URI=http://bwadm.example.com/changeme/
labels:
- "bunkerweb.SERVER_NAME=bwadm.example.com"
- "bunkerweb.USE_UI=yes"
- "bunkerweb.USE_REVERSE_PROXY=yes"
- "bunkerweb.REVERSE_PROXY_URL=/changeme"
- "bunkerweb.REVERSE_PROXY_HOST=http://bw-ui:7000"
- "bunkerweb.REVERSE_PROXY_HEADERS=X-Script-Name /changeme"
- "bunkerweb.INTERCEPTED_ERROR_CODES=400 401 404 405 413 429 500 501 502 503 504"
volumes:
bw-data:
bw-confs:
networks:
bw-universe:
name: bw-universe
ipam:
driver: default
config:
- subnet: 10.20.30.0/24
bw-services:
name: bw-services
bw-docker:
name: bw-docker
```
=== "Swarm"
=== "Kubernetes"
=== "Linux"
The installation of the web UI using the [Linux integration](/1.4/integrations/#linux) is pretty straightforward because it is installed with BunkerWeb.

View File

@ -1,3 +1,4 @@
{% if USE_UI == "yes" +%}
SecRule REQUEST_FILENAME "@rx /services$" "id:1001,ctl:ruleRemoveByTag=attack-rce,ctl:ruleRemoveByTag=attack-xss,ctl:ruleRemoveByTag=attack-generic,nolog"
SecRule REQUEST_FILENAME "@rx /global_config$" "id:1002,ctl:ruleRemoveByTag=platform-pgsql,nolog"
{% endif +%}

View File

@ -208,6 +208,7 @@ try:
SEND_FILE_MAX_AGE_DEFAULT=86400,
PLUGIN_ARGS={},
RELOADING=False,
LAST_RELOAD=0,
TO_FLASH=[],
DARK_MODE=False,
)
@ -249,8 +250,10 @@ def manage_bunkerweb(method: str, operation: str = "reloads", *args):
operation = app.config["INSTANCES"].stop_instance(args[0])
elif operation == "restart":
operation = app.config["INSTANCES"].restart_instance(args[0])
else:
elif Path("/usr/sbin/nginx").is_file():
operation = app.config["INSTANCES"].reload_instances()
else:
operation = "The scheduler will be in charge of reloading the instances."
if isinstance(operation, list):
for op in operation:
@ -387,6 +390,7 @@ def instances():
return redirect(url_for("loading", next=url_for("instances")))
app.config["RELOADING"] = True
app.config["LAST_RELOAD"] = time()
Thread(
target=manage_bunkerweb,
name="Reloading instances",
@ -500,6 +504,7 @@ def services():
# Reload instances
app.config["RELOADING"] = True
app.config["LAST_RELOAD"] = time()
Thread(
target=manage_bunkerweb,
name="Reloading instances",
@ -581,6 +586,7 @@ def global_config():
# Reload instances
app.config["RELOADING"] = True
app.config["LAST_RELOAD"] = time()
Thread(
target=manage_bunkerweb,
name="Reloading instances",
@ -1203,6 +1209,7 @@ def plugins():
# Reload instances
app.config["RELOADING"] = True
app.config["LAST_RELOAD"] = time()
Thread(
target=manage_bunkerweb,
name="Reloading instances",
@ -1773,7 +1780,12 @@ def darkmode():
@app.route("/check_reloading")
@login_required
def check_reloading():
if app.config["RELOADING"] is False:
if not app.config["RELOADING"] or app.config["LAST_RELOAD"] + 60 < time():
if app.config["RELOADING"]:
logger.warning("Reloading took too long, forcing the state to be reloaded")
flash("Forced the status to be reloaded", "error")
app.config["RELOADING"] = False
for f in app.config["TO_FLASH"]:
if f["type"] == "error":
flash(f["content"], "error")

View File

@ -3,7 +3,7 @@ version: "3.5"
services:
mybunker:
build:
context: .
context: ../..
dockerfile: src/bw/Dockerfile
ports:
- 80:80
@ -29,7 +29,6 @@ services:
www.example.com_REVERSE_PROXY_HEADERS: "X-Script-Name /admin"
www.example.com_CUSTOM_CONF_MODSEC_CRS_config: 'SecRule REQUEST_FILENAME "@rx /global_config$$" "id:999,ctl:ruleRemoveByTag=platform-pgsql,nolog"'
www.example.com_INTERCEPTED_ERROR_CODES: "400 405 413 429 500 501 502 503 504"
CUSTOM_CONF_SERVER_HTTP_port-redirect: "port_in_redirect on;"
labels:
- "bunkerweb.INSTANCE"
networks:
@ -39,7 +38,7 @@ services:
bw-scheduler:
build:
context: .
context: ../..
dockerfile: src/scheduler/Dockerfile
depends_on:
- mybunker
@ -53,7 +52,7 @@ services:
bw-ui:
build:
context: .
context: ../..
dockerfile: src/ui/Dockerfile
depends_on:
- mybunker
@ -83,17 +82,16 @@ services:
networks:
bw-services:
ipv4_address: 192.168.0.4
ui-tests:
build: tests/ui
environment:
- PYTHONUNBUFFERED=1
extra_hosts:
- "www.example.com:192.168.0.2"
- "app1.example.com:192.168.0.2"
networks:
bw-services:
ipv4_address: 192.168.0.3
# ui-tests:
# build: .
# environment:
# - PYTHONUNBUFFERED=1
# extra_hosts:
# - "www.example.com:192.168.0.2"
# - "app1.example.com:192.168.0.2"
# networks:
# bw-services:
# ipv4_address: 192.168.0.3
volumes:
bw-data:

View File

@ -81,7 +81,6 @@ services:
volumes:
bw-data:
networks:
bw-universe:
name: bw-universe