1 line
258 KiB
JSON
1 line
258 KiB
JSON
{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Introduction Overview Make your web services secure by default ! BunkerWeb is a web server based on the notorious NGINX and focused on security. It integrates into existing environments ( Linux , Docker , Swarm , Kubernetes , \u2026) to make your web services \"secure by default\" without any hassle. The security best practices are automatically applied for you while keeping control of every setting to meet your use case. BunkerWeb contains primary security features as part of the core but can be easily extended with additional ones thanks to a plugin system . Why BunkerWeb ? Easy integration into existing environments : support for Linux, Docker, Swarm and Kubernetes Highly customizable : enable, disable and configure features easily to meet your use case Secure by default : offers out-of-the-box and hassle-free minimal security for your web services Free as in \"freedom\" : licensed under the free AGPLv3 license Security features A non-exhaustive list of security features : HTTPS support with transparent Let's Encrypt automation State-of-the-art web security : HTTP security headers, prevent leaks, TLS hardening, ... Integrated ModSecurity WAF with the OWASP Core Rule Set Automatic ban of strange behaviors based on HTTP status code Apply connections and requests limit for clients Block bots by asking them to solve a challenge (e.g. : cookie, javascript, captcha, hCaptcha or reCAPTCHA) Block known bad IPs with external blacklists and DNSBL And much more ... Learn more about the core security features in the security tuning section of the documentation. Demo Fooling automated tools/scanners A demo website protected with BunkerWeb is available at demo.bunkerweb.io . Feel free to visit it and perform some security tests.","title":"Introduction"},{"location":"#introduction","text":"","title":"Introduction"},{"location":"#overview","text":"Make your web services secure by default ! BunkerWeb is a web server based on the notorious NGINX and focused on security. It integrates into existing environments ( Linux , Docker , Swarm , Kubernetes , \u2026) to make your web services \"secure by default\" without any hassle. The security best practices are automatically applied for you while keeping control of every setting to meet your use case. BunkerWeb contains primary security features as part of the core but can be easily extended with additional ones thanks to a plugin system .","title":"Overview"},{"location":"#why-bunkerweb","text":"Easy integration into existing environments : support for Linux, Docker, Swarm and Kubernetes Highly customizable : enable, disable and configure features easily to meet your use case Secure by default : offers out-of-the-box and hassle-free minimal security for your web services Free as in \"freedom\" : licensed under the free AGPLv3 license","title":"Why BunkerWeb ?"},{"location":"#security-features","text":"A non-exhaustive list of security features : HTTPS support with transparent Let's Encrypt automation State-of-the-art web security : HTTP security headers, prevent leaks, TLS hardening, ... Integrated ModSecurity WAF with the OWASP Core Rule Set Automatic ban of strange behaviors based on HTTP status code Apply connections and requests limit for clients Block bots by asking them to solve a challenge (e.g. : cookie, javascript, captcha, hCaptcha or reCAPTCHA) Block known bad IPs with external blacklists and DNSBL And much more ... Learn more about the core security features in the security tuning section of the documentation.","title":"Security features"},{"location":"#demo","text":"Fooling automated tools/scanners A demo website protected with BunkerWeb is available at demo.bunkerweb.io . Feel free to visit it and perform some security tests.","title":"Demo"},{"location":"about/","text":"About Who maintains BunkerWeb ? BunkerWeb is maintained by Bunkerity , a French \ud83c\uddeb\ud83c\uddf7 company specialised in Cybersecurity \ud83d\udee1\ufe0f. Do you offer professional services ? Yes, we offer professional services related to BunkerWeb like : Consulting Support Custom development Partnership Please contact us at contact@bunkerity.com if you are interested. Where to get community support ? To get free community support you can use the following medias : The #help channel of BunkerWeb in the Discord server The help category of GitHub dicussions The /r/BunkerWeb subreddit The Server Fault and Super User forums Please don't use GitHub issues to ask for help, use it only for bug reports and feature requests. How can I contribute ? Here is a non-exhaustive list of what you can do : Join the Discord server , /r/BunkerWeb subreddit and GitHub discussions to talk about the project and help others Follow us on LinkedIn , Twitter and GitHub Report bugs and propose new features using issues Contribute to the code using pull requests Write an awesome plugin Talk about BunkerWeb to your friends/colleagues, on social media, on your blog, ... How to report security issue ? Please contact us at security@bunkerity.com using the following PGP key : -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGCEMiMBEACtXJBDbF86qjC/Q1cfmJfYcYrbk6eE5czknG294XObC97wAgDf /MbX6bnti4kDRpflGDqQtwOXudcEzledTD4bdDUKvZwqPoYQGa24uCuUxSINTLXr RuoMaKfpvs7trsFXp5iYUqf4Org2aaJE7Tk/9sOvxgdqsT22jEgCZXTRU1qG494U u6XRQN8hKlw6aa6njjX9vUk6Jpl46/kwwO9mpXBZX6iFKYnBlUWs2k8d6D6cO5aZ KLoYyz5v3Gw2hHSqj4qbVQPTIT7qrrcfd8nblYK7Dh3IM+vQq7a7lB0AudIyBNPd rsypi9ZYgwI3lv/rmQnDc32Ua5cLvTvgg/XoaNK9ogc3kei1+hXODEgRA/zvSKqq 20i/1Y0OnIGv89LOI6urWpOgDAhQUV5xvANll2lm3Bkmy29UOzNadUc/yImxrM06 HwX82ju6PFAqOaxMW6SEE71ylGOSlikAGNcmmc5Ihd1J/VRZA4PBiQ31gQxFRpUC 3NTw2QNAD1kjni5PuQD10Q1Ognvb6uJh/MtqsoX6r1t+Oly9MblFSuyqFkqNO3F0 QAJqprhJlQ3YOcJdJ1EZR7qs0xJm5h+lw0Z/UINqkwiZUW3PCO8BKxfq6sfdwM8L 5hPhyUzy2gIJ0J/4NGYEBH1ojoYODGU8OCSmyjSTY9SoVMeWDfqYP4ZTvQARAQAB tCVidW5rZXJpdHktcGdwIDxjb250YWN0QGJ1bmtlcml0eS5jb20+iQJUBBMBCAA+ FiEEw78SjkcVxXCq7hStPYCAbxJgKnwFAmCEMiMCGwMFCQPCIP0FCwkIBwIGFQoJ CAsCBBYCAwECHgECF4AACgkQPYCAbxJgKnzvYhAAnNqGB6ce2eZzwk1EiNlNaXaA hFWLq/s/J1IOAP+0V5jKJxA6zTX01HyIfIIHQy6nrxxEXzYsIUHdJ+HBPCNswCqn 2d/aDkkfoEUc1bUD0c2bXfoSCsAeIoK+eOf6iSr4IENVoIUYFQTUKFNu+Y7eDL0I J8Xadg53G+fkK9LE6TeYpBs3hDT4w7vlDfIwWa1NC9HoLzSmZ2fqZ7SnihLGsLmp 98VqDrDjhRPzrz5/tVYgvPCQQU5ED/TayCCYvrGpw9gP8qmEOabIUz0ppGwEfQVs Wycilm1/Js/qjdbxUFMipBIzDu7bI3kMLmENhI+16Xtub9dUrvkW2SdDngYhtWj8 IzVOe6N/XDuiRGpaYFpEuXbrnDFexe1ygZwnVHt3fukPfa7W8mhMs2kY1ishIA0O WElKO1Q6N0ZWEad0PwM8NCDjaDUNWQC36ZF/MS+ipHWx9joPUjImY2AXDjN+L+Si ABQIe4Fo6Jx6S6Bi8YvPq8idYZvaWFJjBvmaPjxdUMPbIsMRiEjvlrhvqhLuVBpE lGA+M4UJGw5yBl+yiiLDuws/Fppv9HwNqw6Uq1m1XaW859Om1GGBKYfphyn+fHjR 7ftOuT7Ss4zioXT4mscOZgkfzDAqgpZiHjYhe7tLUu7iD6UEsZmey/gRV0hCxng3 N7yaRrBu0+3sIQV4jYC5Ag0EYIQyIwEQALSurJGOx7At5mRFjvhXd4/JHuBZZOSI M45LSJ+mKYnAGmwsL0AneZMIf6Yc0Vcn32oqlIXN5aB8jIt91pChLre8tl/lFZZP xY3WIEBJhZF0FIUqSQLjg4HD0S70REii7Om1kgtZueid8V6T5F1JDcO2mDoh8oc9 h9nRQ1Ld6dblEuwBzbFkI1K6OUk1+ec7+mQc7orHdBVgelmqwG7fGZnPiN3XfklF dnwSkFIX/qkAsKQmmx1VSzaGFoPLajf4wrkzZdA3iEafsHyvdEFlezZCZ7TsoHBh tNg1Psg6MbBVgiMfHyRHSEBJZ7r5Awj2MpFUFMOd1IPcor1I254mx0VYfCvof4Km Ri1F/86kHc23A77pd4HFYZWiZjaWhh12L+wz5fDL5/sSFXVGSCtSWIKx6FjysZ+v szk3lItHoomZhA7M+FjU/cOjq9hae9uwZeU39DQk0/npln2RcHitoqgUIzII5woO S3SlMSc910tHf40D2cBr1iFKC0jQICjkDexB9CtNx/N25SJmLfiimYtk6/NHlPq4 HXdq6ZfLZ7xQmuGcyWv4f0pwA2CK3twISpsIxIKe456WYTDtQu9d1s987dvmw6F/ qURC6m2WPGroHb8COQTKzbshjpGUmLpyR3FXki4wNXeI1KaQLL7NpZmK6yJlWviO 1sCjh4m7VS+zABEBAAGJAjwEGAEIACYWIQTDvxKORxXFcKruFK09gIBvEmAqfAUC YIQyIwIbDAUJA8Ig/QAKCRA9gIBvEmAqfP2WEACqmXEhu4ARl2yT9bay0+W3F1q1 MrLQkcVOau2ihXx3PhYsXRUoEFj72VDAar41WIlHsPJfB14WtSlYcX2XdjHLHMpC dL2eGhqIcHzFChR0vGjtvm2wae/rJTChWf8WXiHrRnRcfFFfhpCvkNi43fQeH4yp cel2a35WV+IRbnkCkaly2NG3XO0t83Siok8Ku+OJGPatUMxJmaEVQeeXVPDzVRva rtvyd9Sclkd9QDPBLZyWHC1vsPKGRJpi5uDZjGxhaFRkimw/SYtFHj7AUrMKAIHB GfEcwC3Eq4rF0FeCOPfBd2vwGGrRflx76jK9rj288ta9Oq6u6ev8PCVzt0E7jrSf AX88vfVRcxihNfj/9i5xmY596jpgbvNA2aJX2hAO3Q8pD6AunVXPUyc3RlFHt7jC tL+9Xv7Qwjz7OToWqj+9cM6T+6oZLxYNVPT72Z/KOFW+mzGb87qjcsDMb/hu2fNq tSWyZk2AAgHQyG1y8vCQQzsDnUDM6NIPwYG5XMP+11WAsPk5fP1ksixpUqIWgjhY M22YUsjLeaRtgSmhAGIkbBgecs1EHSZZ6sf2lB8gSom1wW0UCBPSifP0DwYFizS5 SOk62kZ0lqEctwgKDe3MNQnPxt9+tU9L1pIkyXgXihcOLiCMl434K0djJXxIbiX0 JvbFAfI3qteepvnjBQ== =g1tf -----END PGP PUBLIC KEY BLOCK-----","title":"About"},{"location":"about/#about","text":"","title":"About"},{"location":"about/#who-maintains-bunkerweb","text":"BunkerWeb is maintained by Bunkerity , a French \ud83c\uddeb\ud83c\uddf7 company specialised in Cybersecurity \ud83d\udee1\ufe0f.","title":"Who maintains BunkerWeb ?"},{"location":"about/#do-you-offer-professional-services","text":"Yes, we offer professional services related to BunkerWeb like : Consulting Support Custom development Partnership Please contact us at contact@bunkerity.com if you are interested.","title":"Do you offer professional services ?"},{"location":"about/#where-to-get-community-support","text":"To get free community support you can use the following medias : The #help channel of BunkerWeb in the Discord server The help category of GitHub dicussions The /r/BunkerWeb subreddit The Server Fault and Super User forums Please don't use GitHub issues to ask for help, use it only for bug reports and feature requests.","title":"Where to get community support ?"},{"location":"about/#how-can-i-contribute","text":"Here is a non-exhaustive list of what you can do : Join the Discord server , /r/BunkerWeb subreddit and GitHub discussions to talk about the project and help others Follow us on LinkedIn , Twitter and GitHub Report bugs and propose new features using issues Contribute to the code using pull requests Write an awesome plugin Talk about BunkerWeb to your friends/colleagues, on social media, on your blog, ...","title":"How can I contribute ?"},{"location":"about/#how-to-report-security-issue","text":"Please contact us at security@bunkerity.com using the following PGP key : -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGCEMiMBEACtXJBDbF86qjC/Q1cfmJfYcYrbk6eE5czknG294XObC97wAgDf /MbX6bnti4kDRpflGDqQtwOXudcEzledTD4bdDUKvZwqPoYQGa24uCuUxSINTLXr RuoMaKfpvs7trsFXp5iYUqf4Org2aaJE7Tk/9sOvxgdqsT22jEgCZXTRU1qG494U u6XRQN8hKlw6aa6njjX9vUk6Jpl46/kwwO9mpXBZX6iFKYnBlUWs2k8d6D6cO5aZ KLoYyz5v3Gw2hHSqj4qbVQPTIT7qrrcfd8nblYK7Dh3IM+vQq7a7lB0AudIyBNPd rsypi9ZYgwI3lv/rmQnDc32Ua5cLvTvgg/XoaNK9ogc3kei1+hXODEgRA/zvSKqq 20i/1Y0OnIGv89LOI6urWpOgDAhQUV5xvANll2lm3Bkmy29UOzNadUc/yImxrM06 HwX82ju6PFAqOaxMW6SEE71ylGOSlikAGNcmmc5Ihd1J/VRZA4PBiQ31gQxFRpUC 3NTw2QNAD1kjni5PuQD10Q1Ognvb6uJh/MtqsoX6r1t+Oly9MblFSuyqFkqNO3F0 QAJqprhJlQ3YOcJdJ1EZR7qs0xJm5h+lw0Z/UINqkwiZUW3PCO8BKxfq6sfdwM8L 5hPhyUzy2gIJ0J/4NGYEBH1ojoYODGU8OCSmyjSTY9SoVMeWDfqYP4ZTvQARAQAB tCVidW5rZXJpdHktcGdwIDxjb250YWN0QGJ1bmtlcml0eS5jb20+iQJUBBMBCAA+ FiEEw78SjkcVxXCq7hStPYCAbxJgKnwFAmCEMiMCGwMFCQPCIP0FCwkIBwIGFQoJ CAsCBBYCAwECHgECF4AACgkQPYCAbxJgKnzvYhAAnNqGB6ce2eZzwk1EiNlNaXaA hFWLq/s/J1IOAP+0V5jKJxA6zTX01HyIfIIHQy6nrxxEXzYsIUHdJ+HBPCNswCqn 2d/aDkkfoEUc1bUD0c2bXfoSCsAeIoK+eOf6iSr4IENVoIUYFQTUKFNu+Y7eDL0I J8Xadg53G+fkK9LE6TeYpBs3hDT4w7vlDfIwWa1NC9HoLzSmZ2fqZ7SnihLGsLmp 98VqDrDjhRPzrz5/tVYgvPCQQU5ED/TayCCYvrGpw9gP8qmEOabIUz0ppGwEfQVs Wycilm1/Js/qjdbxUFMipBIzDu7bI3kMLmENhI+16Xtub9dUrvkW2SdDngYhtWj8 IzVOe6N/XDuiRGpaYFpEuXbrnDFexe1ygZwnVHt3fukPfa7W8mhMs2kY1ishIA0O WElKO1Q6N0ZWEad0PwM8NCDjaDUNWQC36ZF/MS+ipHWx9joPUjImY2AXDjN+L+Si ABQIe4Fo6Jx6S6Bi8YvPq8idYZvaWFJjBvmaPjxdUMPbIsMRiEjvlrhvqhLuVBpE lGA+M4UJGw5yBl+yiiLDuws/Fppv9HwNqw6Uq1m1XaW859Om1GGBKYfphyn+fHjR 7ftOuT7Ss4zioXT4mscOZgkfzDAqgpZiHjYhe7tLUu7iD6UEsZmey/gRV0hCxng3 N7yaRrBu0+3sIQV4jYC5Ag0EYIQyIwEQALSurJGOx7At5mRFjvhXd4/JHuBZZOSI M45LSJ+mKYnAGmwsL0AneZMIf6Yc0Vcn32oqlIXN5aB8jIt91pChLre8tl/lFZZP xY3WIEBJhZF0FIUqSQLjg4HD0S70REii7Om1kgtZueid8V6T5F1JDcO2mDoh8oc9 h9nRQ1Ld6dblEuwBzbFkI1K6OUk1+ec7+mQc7orHdBVgelmqwG7fGZnPiN3XfklF dnwSkFIX/qkAsKQmmx1VSzaGFoPLajf4wrkzZdA3iEafsHyvdEFlezZCZ7TsoHBh tNg1Psg6MbBVgiMfHyRHSEBJZ7r5Awj2MpFUFMOd1IPcor1I254mx0VYfCvof4Km Ri1F/86kHc23A77pd4HFYZWiZjaWhh12L+wz5fDL5/sSFXVGSCtSWIKx6FjysZ+v szk3lItHoomZhA7M+FjU/cOjq9hae9uwZeU39DQk0/npln2RcHitoqgUIzII5woO S3SlMSc910tHf40D2cBr1iFKC0jQICjkDexB9CtNx/N25SJmLfiimYtk6/NHlPq4 HXdq6ZfLZ7xQmuGcyWv4f0pwA2CK3twISpsIxIKe456WYTDtQu9d1s987dvmw6F/ qURC6m2WPGroHb8COQTKzbshjpGUmLpyR3FXki4wNXeI1KaQLL7NpZmK6yJlWviO 1sCjh4m7VS+zABEBAAGJAjwEGAEIACYWIQTDvxKORxXFcKruFK09gIBvEmAqfAUC YIQyIwIbDAUJA8Ig/QAKCRA9gIBvEmAqfP2WEACqmXEhu4ARl2yT9bay0+W3F1q1 MrLQkcVOau2ihXx3PhYsXRUoEFj72VDAar41WIlHsPJfB14WtSlYcX2XdjHLHMpC dL2eGhqIcHzFChR0vGjtvm2wae/rJTChWf8WXiHrRnRcfFFfhpCvkNi43fQeH4yp cel2a35WV+IRbnkCkaly2NG3XO0t83Siok8Ku+OJGPatUMxJmaEVQeeXVPDzVRva rtvyd9Sclkd9QDPBLZyWHC1vsPKGRJpi5uDZjGxhaFRkimw/SYtFHj7AUrMKAIHB GfEcwC3Eq4rF0FeCOPfBd2vwGGrRflx76jK9rj288ta9Oq6u6ev8PCVzt0E7jrSf AX88vfVRcxihNfj/9i5xmY596jpgbvNA2aJX2hAO3Q8pD6AunVXPUyc3RlFHt7jC tL+9Xv7Qwjz7OToWqj+9cM6T+6oZLxYNVPT72Z/KOFW+mzGb87qjcsDMb/hu2fNq tSWyZk2AAgHQyG1y8vCQQzsDnUDM6NIPwYG5XMP+11WAsPk5fP1ksixpUqIWgjhY M22YUsjLeaRtgSmhAGIkbBgecs1EHSZZ6sf2lB8gSom1wW0UCBPSifP0DwYFizS5 SOk62kZ0lqEctwgKDe3MNQnPxt9+tU9L1pIkyXgXihcOLiCMl434K0djJXxIbiX0 JvbFAfI3qteepvnjBQ== =g1tf -----END PGP PUBLIC KEY BLOCK-----","title":"How to report security issue ?"},{"location":"concepts/","text":"Concepts Integrations The first concept is the integration of BunkerWeb into the target environment. We prefer to use the word \"integration\" instead of \"installation\" because one of the goals of BunkerWeb is to integrate seamlessly into existing environments. The following integrations are officially supported : Docker Docker autoconf Swarm Kubernetes Linux If you think that a new integration should be supported, do not hesitate to open a new issue on the GitHub repository. Going further The technical details of all BunkerWeb integrations are available in the integrations section of the documentation. Settings Once BunkerWeb is integrated into your environment, you will need to configure it to serve and protect your web applications. Configuration of BunkerWeb is done using what we called the \"settings\" or \"variables\". Each setting is identified by a name like AUTO_LETS_ENCRYPT or USE_ANTIBOT for example. You can assign values to the settings to configure BunkerWeb. Here is a dummy example of a BunkerWeb configuration : SERVER_NAME=www.example.com AUTO_LETS_ENCRYPT=yes USE_ANTIBOT=captcha REFERRER_POLICY=no-referrer USE_MODSECURITY=no USE_GZIP=yes USE_BROTLI=no Going further The complete list of available settings with descriptions and possible values is available in the settings section of the documentation. Settings generator tool To help you tuning BunkerWeb we have made an easy to use settings generator tool available at config.bunkerweb.io . Multisite mode The multisite mode is a crucial concept to understand when using BunkerWeb. Because the goal is to protect web applications, we intrinsically inherit the concept of \"virtual host\" or \"vhost\" (more info here ) which makes it possible to serve multiple web applications from a single (or a cluster of) instance. By default, the multisite mode of BunkerWeb is disabled which means that only one web application will be served and all the settings will be applied to it. The typical use case is when you have a single application to protect : you don't have to worry about the multisite and the default behavior should be the right one for you. When multisite mode is enabled, BunkerWeb will serve and protect multiple web applications. Each web application is identified by a unique server name and have its own set of settings. The typical use case is when you have multiple applications to protect and you want to use a single (or a cluster depending of the integration) instance of BunkerWeb. The multisite mode is controlled by the MULTISITE setting which can be set to yes (enabled) or no (disabled, which is the default). Each setting has a context which defines \"where\" it can be applied. If the context is global then the setting can't be set per server (or \"per site\", \"per app\") but only to the whole configuration. Otherwise, if the context is multisite, the setting can be set globally and per server. Defining a multisite setting to a specific server is done by adding the server name as a prefix of the setting name like app1.example.com_AUTO_LETS_ENCRYPT or app2.example.com_USE_ANTIBOT for example. When a multisite setting is defined globally (without any server prefix), all the servers will inherit that setting (but can still be overriden if we set the same setting with the server name prefix). Here is a dummy example of a multisite BunkerWeb configuration : MULTISITE=yes SERVER_NAME=app1.example.com app2.example.com app3.example.com AUTO_LETS_ENCRYPT=yes USE_GZIP=yes USE_BROTLI=yes app1.example.com_USE_ANTIBOT=javascript app1.example.com_USE_MODSECURITY=no app2.example.com_USE_ANTIBOT=cookie app2.example.com_WHITELIST_COUNTRY=FR app3.example.com_USE_BAD_BEHAVIOR=no Going further You will find concrete examples of multisite mode in the quickstart guide of the documentation and the examples directory of the repository. Custom configurations Because meeting all the use cases only using the settings is not an option (even with external plugins ), you can use custom configurations to solve your specific challenges. Under the hood, BunkerWeb uses the notorious NGINX web server, that's why you can leverage its configuration system for your specific needs. Custom NGINX configurations can be included in different contexts like HTTP or server (all servers and/or specific server block). Another core component of BunkerWeb is the ModSecurity Web Application Firewall : you can also use custom configurations to fix some false positives or add custom rules for example. Going further You will find concrete examples of custom configurations in the quickstart guide of the documentation and the examples directory of the repository.","title":"Concepts"},{"location":"concepts/#concepts","text":"","title":"Concepts"},{"location":"concepts/#integrations","text":"The first concept is the integration of BunkerWeb into the target environment. We prefer to use the word \"integration\" instead of \"installation\" because one of the goals of BunkerWeb is to integrate seamlessly into existing environments. The following integrations are officially supported : Docker Docker autoconf Swarm Kubernetes Linux If you think that a new integration should be supported, do not hesitate to open a new issue on the GitHub repository. Going further The technical details of all BunkerWeb integrations are available in the integrations section of the documentation.","title":"Integrations"},{"location":"concepts/#settings","text":"Once BunkerWeb is integrated into your environment, you will need to configure it to serve and protect your web applications. Configuration of BunkerWeb is done using what we called the \"settings\" or \"variables\". Each setting is identified by a name like AUTO_LETS_ENCRYPT or USE_ANTIBOT for example. You can assign values to the settings to configure BunkerWeb. Here is a dummy example of a BunkerWeb configuration : SERVER_NAME=www.example.com AUTO_LETS_ENCRYPT=yes USE_ANTIBOT=captcha REFERRER_POLICY=no-referrer USE_MODSECURITY=no USE_GZIP=yes USE_BROTLI=no Going further The complete list of available settings with descriptions and possible values is available in the settings section of the documentation. Settings generator tool To help you tuning BunkerWeb we have made an easy to use settings generator tool available at config.bunkerweb.io .","title":"Settings"},{"location":"concepts/#multisite-mode","text":"The multisite mode is a crucial concept to understand when using BunkerWeb. Because the goal is to protect web applications, we intrinsically inherit the concept of \"virtual host\" or \"vhost\" (more info here ) which makes it possible to serve multiple web applications from a single (or a cluster of) instance. By default, the multisite mode of BunkerWeb is disabled which means that only one web application will be served and all the settings will be applied to it. The typical use case is when you have a single application to protect : you don't have to worry about the multisite and the default behavior should be the right one for you. When multisite mode is enabled, BunkerWeb will serve and protect multiple web applications. Each web application is identified by a unique server name and have its own set of settings. The typical use case is when you have multiple applications to protect and you want to use a single (or a cluster depending of the integration) instance of BunkerWeb. The multisite mode is controlled by the MULTISITE setting which can be set to yes (enabled) or no (disabled, which is the default). Each setting has a context which defines \"where\" it can be applied. If the context is global then the setting can't be set per server (or \"per site\", \"per app\") but only to the whole configuration. Otherwise, if the context is multisite, the setting can be set globally and per server. Defining a multisite setting to a specific server is done by adding the server name as a prefix of the setting name like app1.example.com_AUTO_LETS_ENCRYPT or app2.example.com_USE_ANTIBOT for example. When a multisite setting is defined globally (without any server prefix), all the servers will inherit that setting (but can still be overriden if we set the same setting with the server name prefix). Here is a dummy example of a multisite BunkerWeb configuration : MULTISITE=yes SERVER_NAME=app1.example.com app2.example.com app3.example.com AUTO_LETS_ENCRYPT=yes USE_GZIP=yes USE_BROTLI=yes app1.example.com_USE_ANTIBOT=javascript app1.example.com_USE_MODSECURITY=no app2.example.com_USE_ANTIBOT=cookie app2.example.com_WHITELIST_COUNTRY=FR app3.example.com_USE_BAD_BEHAVIOR=no Going further You will find concrete examples of multisite mode in the quickstart guide of the documentation and the examples directory of the repository.","title":"Multisite mode"},{"location":"concepts/#custom-configurations","text":"Because meeting all the use cases only using the settings is not an option (even with external plugins ), you can use custom configurations to solve your specific challenges. Under the hood, BunkerWeb uses the notorious NGINX web server, that's why you can leverage its configuration system for your specific needs. Custom NGINX configurations can be included in different contexts like HTTP or server (all servers and/or specific server block). Another core component of BunkerWeb is the ModSecurity Web Application Firewall : you can also use custom configurations to fix some false positives or add custom rules for example. Going further You will find concrete examples of custom configurations in the quickstart guide of the documentation and the examples directory of the repository.","title":"Custom configurations"},{"location":"integrations/","text":"Integrations Docker Docker integration Using BunkerWeb as a Docker container is a quick and easy way to test and use it as long as you are familiar with the Docker technology. We provide ready to use prebuilt images for x64, x86 armv8 and armv7 architectures on Docker Hub : docker pull bunkerity/bunkerweb:1.4.1 Alternatively, you can build the Docker images directly from the source (and take a coffee \u2615 because it may be long depending on your hardware) : git clone https://github.com/bunkerity/bunkerweb.git && \\ cd bunkerweb && \\ docker build -t my-bunkerweb . Usage and configuration of the BunkerWeb container are based on : Environment variables to configure BunkerWeb and meet your use cases Volume to cache important data and mount custom configuration files Networks to expose ports for clients and connect to upstream web services Environment variables Settings are passed to BunkerWeb using Docker environment variables. You can use the -e flag : docker run \\ ... -e MY_SETTING = value \\ -e \"MY_OTHER_SETTING=value with spaces\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 environment : - MY_SETTING=value Full list For the complete list of environment variables, see the settings section of the documentation. Volume A volume is used to share data with BunkerWeb and store persistent data like certificates, cached files, ... The easiest way of managing the volume is by using a named one. You will first need to create it : docker volume create bw-data Once it's created, you can mount it on /data when running the container : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - bw-data:/data ... volumes : bw-data : Warning BunkerWeb runs as an unprivileged user with UID 101 and GID 101 inside the container. The reason behind this is the security : in case a vulnerability is exploited, the attacker won't have full root (UID/GID 0) privileges. But there is a downside : if you use a local folder for the persistent data , you will need to set the correct permissions so the unprivileged user can write data to it. Something like that should do the trick : shell mkdir bw-data && \\ chown root:101 bw-data && \\ chmod 770 bw-data Alternatively, if the folder already exists : chown -R root:101 bw-data && \\ chmod -R 770 bw-data Mounting the folder : docker run \\ ... -v ./bw-data:/data \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data Networks The easiest way to connect BunkerWeb to web applications is by using Docker networks. First of all, you will need to create a network : docker network create mynetwork Once it's created, you will need to connect the container to that network : docker run \\ ... --network mynetwork \\ ... bunkerity/bunkerweb:1.4.1 You will also need to do the same with your web application(s). Please note that the other containers are accessible using their name as the hostname. Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 networks : - bw-net ... networks : bw-net : Docker autoconf Docker autoconf integration Docker integration The Docker autoconf integration is an \"evolution\" of the Docker one. Please read the Docker integration section first if needed. The downside of using environment variables is that the container needs to be recreated each time there is an update which is not very convenient. To counter that issue, you can use another image called autoconf which will listen for Docker events and automatically reconfigure BunkerWeb in real-time without recreating the container. Instead of defining environment variables for the BunkerWeb container, you simply add labels to your web applications containers and the autoconf will \"automagically\" take care of the rest. Multisite mode The Docker autoconf integration implies the use of multisite mode . Please refer to the multisite section of the documentation for more information. First of all, you will need to create the data volume : docker volume create bw-data Then, you can create two networks (replace 10.20.30.0/24 with an unused subnet of your choice) : docker network create --subnet 10 .20.30.0/24 bw-autoconf && \\ docker network create bw-services One for communication between BunkerWeb and autoconf Another one for communication between BunkerWeb and web applications You can now create the BunkerWeb container with the AUTOCONF_MODE=yes setting and the bunkerweb.AUTOCONF label (replace 10.20.30.0/24 with the subnet specified before) : docker run \\ -d \\ --name mybunker \\ --network bw-autoconf \\ -p 80 :8080 \\ -p 443 :8443 \\ -e AUTOCONF_MODE = yes \\ -e MULTISITE = yes \\ -e SERVER_NAME = \\ -e \"API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24\" \\ -l bunkerweb.AUTOCONF \\ bunkerity/bunkerweb:1.4.1 && \\ docker network connect bw-services mybunker And the autoconf one : docker run \\ -d \\ --name myautoconf \\ --network bw-autoconf \\ -v bw-data:/data \\ -v /var/run/docker.sock:/var/run/docker.sock:ro \\ bunkerity/bunkerweb-autoconf:1.4.1 Here is the docker-compose equivalent for the BunkerWeb autoconf stack : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - 80:8080 - 443:8443 environment : - AUTOCONF_MODE=yes - MULTISITE=yes - SERVER_NAME= - API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24 labels : - \"bunkerweb.AUTOCONF\" networks : - bw-autoconf - bw-services myautoconf : image : bunkerity/bunkerweb-autoconf:1.4.1 volumes : - bw-data:/data - /var/run/docker.sock:/var/run/docker.sock:ro networks : - bw-autoconf volumes : bw-data : networks : bw-autoconf : ipam : driver : default config : - subnet : 10.20.30.0/24 bw-services : name : bw-services Once the stack is setup, you can now create the web application container and add the settings as labels using the \"bunkerweb.\" prefix in order to automatically setup BunkerWeb : docker run \\ -d \\ --name myapp \\ --network bw-services \\ -l bunkerweb.MY_SETTING_1 = value1 \\ -l bunkerweb.MY_SETTING_2 = value2 \\ ... mywebapp:4.2 Here is the docker-compose equivalent : ... services : myapp : image : mywebapp:4.2 networks : bw-services : aliases : - myapp labels : - \"bunkerweb.MY_SETTING_1=value1\" - \"bunkerweb.MY_SETTING_2=value2\" ... networks : bw-services : external : name : bw-services ... Swarm Docker Swarm integration Docker autoconf The Docker autoconf integration is similar of the Docker autoconf one (but with services instead of containers). Please read the Docker autoconf integration section first if needed. To automatically configure BunkerWeb instances, a special service, called autoconf , will be scheduled on a manager node. That service will listen for Docker Swarm events like service creation or deletion and automatically configure the BunkerWeb instances in real-time without downtime. Like the Docker autoconf integration , configuration for web services is defined using labels starting with the special bunkerweb. prefix. The recommended setup is to schedule the BunkerWeb service as a global service on all worker nodes and the autoconf service as a single replicated service on a manager node. First of all, you will need to create two networks (replace 10.20.30.0/24 with an unused subnet of your choice) : docker network create -d overlay --attachable --subnet 10 .20.30.0/24 bw-autoconf && \\ docker network create -d overlay --attachable bw-services One for communication between BunkerWeb and autoconf Another one for communication between BunkerWeb and web applications You can now create the BunkerWeb service (replace 10.20.30.0/24 with the subnet specified before) : docker service create \\ --name mybunker \\ --mode global \\ --constraint node.role == worker \\ --network bw-autoconf \\ --network bw-services \\ -p published = 80 ,target = 8080 ,mode = host \\ -p published = 443 ,target = 8443 ,mode = host \\ -e SWARM_MODE = yes \\ -e SERVER_NAME = \\ -e MULTISITE = yes \\ -e \"API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24\" \\ -l bunkerweb.AUTOCONF \\ bunkerity/bunkerweb:1.4.1 And the autoconf one : docker service \\ create \\ --name myautoconf \\ --constraint node.role == manager \\ --network bw-autoconf \\ --mount type = bind,source = /var/run/docker.sock,destination = /var/run/docker.sock,ro \\ --mount type = volume,source = bw-data,destination = /data \\ -e SWARM_MODE = yes \\ bunkerity/bunkerweb-autoconf:1.4.1 Here is the docker-compose equivalent (using docker stack deploy ) : version : '3.5' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - published : 80 target : 8080 mode : host protocol : tcp - published : 443 target : 8443 mode : host protocol : tcp environment : - SWARM_MODE=yes - SERVER_NAME= - MULTISITE=yes - API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24 networks : - bw-autoconf - bw-services deploy : mode : global placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.AUTOCONF\" myautoconf : image : bunkerity/bunkerweb-autoconf:1.4.1 environment : - SWARM_MODE=yes volumes : - bw-data:/data - /var/run/docker.sock:/var/run/docker.sock:ro networks : - bw-autoconf deploy : replicas : 1 placement : constraints : - \"node.role==manager\" networks : bw-autoconf : driver : overlay attachable : true name : bw-autoconf ipam : config : - subnet : 10.20.30.0/24 bw-services : driver : overlay attachable : true name : bw-services volumes : bw-data : Once the BunkerWeb Swarm stack is set up and running (see autoconf logs for more information), you can now deploy web applications in the cluster and use labels to dynamically configure BunkerWeb : docker service \\ create \\ --name myapp \\ --network bw-services \\ -l bunkerweb.MY_SETTING_1 = value1 \\ -l bunkerweb.MY_SETTING_2 = value2 \\ ... mywebapp:4.2 Here is the docker-compose equivalent (using docker stack deploy ) : ... services : myapp : image : mywebapp:4.2 networks : - bw-services deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.MY_SETTING_1=value1\" - \"bunkerweb.MY_SETTING_2=value2\" ... networks : bw-services : external : name : bw-services Kubernetes Kubernetes integration The autoconf acts as an Ingress controller and will configure the BunkerWeb instances according to the Ingress resources . It also monitors other Kubernetes objects like ConfigMap for custom configurations. The first step to install BunkerWeb on a Kubernetes cluster is to add a role and permissions on the cluster for the autoconf : apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRole metadata : name : cr-bunkerweb rules : - apiGroups : [ \"\" ] resources : [ \"services\" , \"pods\" , \"configmaps\" ] verbs : [ \"get\" , \"watch\" , \"list\" ] - apiGroups : [ \"networking.k8s.io\" ] resources : [ \"ingresses\" ] verbs : [ \"get\" , \"watch\" , \"list\" ] --- apiVersion : v1 kind : ServiceAccount metadata : name : sa-bunkerweb --- apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRoleBinding metadata : name : crb-bunkerweb subjects : - kind : ServiceAccount name : sa-bunkerweb namespace : default apiGroup : \"\" roleRef : kind : ClusterRole name : cr-bunkerweb apiGroup : rbac.authorization.k8s.io The recommended way of deploying BunkerWeb is using a DaemonSet which means each node in the cluster will run an instance of BunkerWeb : apiVersion : apps/v1 kind : DaemonSet metadata : name : bunkerweb spec : selector : matchLabels : app : bunkerweb template : metadata : labels : app : bunkerweb # mandatory annotation annotations : bunkerweb.io/AUTOCONF : \"yes\" spec : containers : - name : bunkerweb image : bunkerity/bunkerweb securityContext : runAsUser : 101 runAsGroup : 101 allowPrivilegeEscalation : false capabilities : drop : - ALL ports : - containerPort : 8080 hostPort : 80 - containerPort : 8443 hostPort : 443 env : - name : KUBERNETES_MODE value : \"yes\" # replace with your DNS resolvers # e.g. : kube-dns.kube-system.svc.cluster.local - name : DNS_RESOLVERS value : \"coredns.kube-system.svc.cluster.local\" - name : USE_API value : \"yes\" # 10.0.0.0/8 is the cluster internal subnet - name : API_WHITELIST_IP value : \"127.0.0.0/8 10.0.0.0/8\" - name : SERVER_NAME value : \"\" - name : MULTISITE value : \"yes\" livenessProbe : exec : command : - /opt/bunkerweb/helpers/healthcheck.sh initialDelaySeconds : 30 periodSeconds : 5 timeoutSeconds : 1 failureThreshold : 3 readinessProbe : exec : command : - /opt/bunkerweb/helpers/healthcheck.sh initialDelaySeconds : 30 periodSeconds : 1 timeoutSeconds : 1 failureThreshold : 3 --- apiVersion : v1 kind : Service metadata : name : svc-bunkerweb spec : clusterIP : None selector : app : bunkerweb In order to store persistent data, you will need a PersistentVolumeClaim : apiVersion : v1 kind : PersistentVolumeClaim metadata : name : pvc-bunkerweb spec : accessModes : - ReadWriteOnce resources : requests : storage : 5Gi Now, you can start the autoconf as a single replica Deployment : apiVersion : apps/v1 kind : Deployment metadata : name : bunkerweb-controller spec : replicas : 1 strategy : type : Recreate selector : matchLabels : app : bunkerweb-controller template : metadata : labels : app : bunkerweb-controller spec : serviceAccountName : sa-bunkerweb volumes : - name : vol-bunkerweb persistentVolumeClaim : claimName : pvc-bunkerweb containers : - name : bunkerweb-controller image : bunkerity/bunkerweb-autoconf imagePullPolicy : Always env : - name : KUBERNETES_MODE value : \"yes\" volumeMounts : - name : vol-bunkerweb mountPath : /data Once the BunkerWeb Kubernetes stack is setup and running (see autoconf logs for more information), you can now deploy web applications in the cluster and declare your Ingress resource. Please note that settings need to be set as annotations for the Ingress resource with the special value bunkerweb.io for the domain part : apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : ingress annotations : bunkerweb.io/MY_SETTING_1 : \"value1\" bunkerweb.io/MY_SETTING_2 : \"value2\" spec : rules : ... Linux Linux integration List of supported Linux distros : Debian 11 \"Bullseye\" Ubuntu 22.04 \"Jammy\" Fedora 36 CentOS Stream 8 Please note that you will need to install NGINX 1.20.2 before BunkerWeb . For all distros, except Fedora, using prebuilt packages from official NGINX repository is mandatory. Compiling NGINX from source or using packages from different repositories won't work with the official prebuild packages of BunkerWeb but you can build it from source. Repositories of Linux packages for BunkerWeb are available on PackageCloud , they provide a bash script to automatically add and trust the repository (but you can also follow the manual installation instructions if you prefer). Debian Ubuntu Fedora CentOS Stream From source The first step is to add NGINX official repository : sudo apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring && \\ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \\ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null && \\ echo \"deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \\ http://nginx.org/packages/debian `lsb_release -cs` nginx\" \\ | sudo tee /etc/apt/sources.list.d/nginx.list You should now be able to install NGINX 1.20.2 : sudo apt update && \\ sudo apt install -y nginx = 1 .20.2-1~bullseye And finally install BunkerWeb 1.4.1 : curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.deb.sh | sudo bash && \\ sudo apt update && \\ sudo apt install -y bunkerweb = 1 .4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing apt upgrade , you can use the following command : sudo apt-mark hold nginx bunkerweb The first step is to add NGINX official repository : sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring && \\ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \\ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null && \\ echo \"deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \\ http://nginx.org/packages/ubuntu `lsb_release -cs` nginx\" \\ | sudo tee /etc/apt/sources.list.d/nginx.list You should now be able to install NGINX 1.20.2 : sudo apt update && \\ sudo apt install -y nginx = 1 .20.2-1~jammy And finally install BunkerWeb 1.4.1 : curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.deb.sh | sudo bash && \\ sudo apt update && \\ sudo apt install -y bunkerweb = 1 .4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing apt upgrade , you can use the following command : sudo apt-mark hold nginx bunkerweb Fedora already provides NGINX 1.20.2 that we support : sudo dnf install -y nginx-1.20.2 curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.rpm.sh | sudo bash && \\ sudo dnf check-update && \\ sudo dnf install -y bunkerweb-1.4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing dnf upgrade , you can use the following command : sudo dnf versionlock add nginx && \\ sudo dnf versionlock add bunkerweb The first step is to add NGINX official repository, create the following file at /etc/yum.repos.d/nginx.repo : [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true You should now be able to install NGINX 1.20.2 : sudo dnf install nginx-1.20.2 And finally install BunkerWeb 1.4.1 : dnf install -y epel-release && \\ curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.rpm.sh | sudo bash && \\ sudo dnf check-update && \\ sudo dnf install -y bunkerweb-1.4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing dnf upgrade , you can use the following command : sudo dnf versionlock add nginx && \\ sudo dnf versionlock add bunkerweb The first step is to install NGINX 1.20.2 using the repository of your choice or by compiling it from source . The target installation folder of BunkerWeb is located at /opt/bunkerweb , let's create it : mkdir /opt/bunkerweb You can now clone the BunkerWeb project to the /tmp folder : https://github.com/bunkerity/bunkerweb.git /tmp/bunkerweb BunkerWeb needs some dependencies to be compiled and install to /opt/bunkerweb/deps , the easiest way to it is by executing the install.sh helper script (please note that you will need to install additional packages which is not covered in this procedure and depends on your own system) : mkdir /opt/bunkerweb/deps && \\ /tmp/bunkerweb/deps/install.sh Additional Python dependencies needs to be installed into the /opt/bunkerweb/deps/python folder : mkdir /opt/bunkerweb/deps/python && \\ pip install --no-cache-dir --require-hashes --target /opt/bunkerweb/deps/python -r /tmp/bunkerweb/deps/requirements.txt && \\ pip install --no-cache-dir --target /opt/bunkerweb/deps/python -r /tmp/bunkerweb/ui/requirements.txt Once dependencies had been installed, you can now copy the BunkerWeb sources to the target /opt/bunkerweb folder : for src in api cli confs core gen helpers job lua misc utils ui settings.json VERSION linux/variables.env linux/bunkerweb-ui.env linux/scripts ; do cp -r /tmp/bunkerweb/ ${ src } /opt/bunkerweb done cp /opt/bunkerweb/helpers/bwcli /usr/local/bin Additional folders also need to be created : mkdir /opt/bunkerweb/ { configs,cache,plugins,tmp } Permissions needs to be fixed : find /opt/bunkerweb -path /opt/bunkerweb/deps -prune -o -type f -exec chmod 0740 {} \\; && \\ find /opt/bunkerweb -path /opt/bunkerweb/deps -prune -o -type d -exec chmod 0750 {} \\; && \\ find /opt/bunkerweb/core/*/jobs/* -type f -exec chmod 750 {} \\; && \\ chmod 770 /opt/bunkerweb/cache /opt/bunkerweb/tmp && \\ chmod 750 /opt/bunkerweb/gen/main.py /opt/bunkerweb/job/main.py /opt/bunkerweb/cli/main.py /opt/bunkerweb/helpers/*.sh /opt/bunkerweb/scripts/*.sh /usr/local/bin/bwcli /opt/bunkerweb/ui/main.py && \\ chown -R root:nginx /opt/bunkerweb Last but not least, you will need to setup systemd unit files : cp /tmp/bunkerweb/linux/*.service /etc/systemd/system && \\ systemctl daemon-reload && \\ systemctl stop nginx && \\ systemctl disable nginx && \\ systemctl enable bunkerweb && \\ systemctl enable bunkerweb-ui Configuration of BunkerWeb is done by editing the /opt/bunkerweb/variables.env file : MY_SETTING_1=value1 MY_SETTING_2=value2 ... BunkerWeb is managed using systemctl : Check BunkerWeb status : systemctl status bunkerweb Reload the configuration : systemctl reload bunkerweb Start it if it's stopped : systemctl start bunkerweb Stop it if it's started : systemctl stop bunkerweb And restart : systemctl restart bunkerweb","title":"Integrations"},{"location":"integrations/#integrations","text":"","title":"Integrations"},{"location":"integrations/#docker","text":"Docker integration Using BunkerWeb as a Docker container is a quick and easy way to test and use it as long as you are familiar with the Docker technology. We provide ready to use prebuilt images for x64, x86 armv8 and armv7 architectures on Docker Hub : docker pull bunkerity/bunkerweb:1.4.1 Alternatively, you can build the Docker images directly from the source (and take a coffee \u2615 because it may be long depending on your hardware) : git clone https://github.com/bunkerity/bunkerweb.git && \\ cd bunkerweb && \\ docker build -t my-bunkerweb . Usage and configuration of the BunkerWeb container are based on : Environment variables to configure BunkerWeb and meet your use cases Volume to cache important data and mount custom configuration files Networks to expose ports for clients and connect to upstream web services","title":"Docker"},{"location":"integrations/#environment-variables","text":"Settings are passed to BunkerWeb using Docker environment variables. You can use the -e flag : docker run \\ ... -e MY_SETTING = value \\ -e \"MY_OTHER_SETTING=value with spaces\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 environment : - MY_SETTING=value Full list For the complete list of environment variables, see the settings section of the documentation.","title":"Environment variables"},{"location":"integrations/#volume","text":"A volume is used to share data with BunkerWeb and store persistent data like certificates, cached files, ... The easiest way of managing the volume is by using a named one. You will first need to create it : docker volume create bw-data Once it's created, you can mount it on /data when running the container : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - bw-data:/data ... volumes : bw-data : Warning BunkerWeb runs as an unprivileged user with UID 101 and GID 101 inside the container. The reason behind this is the security : in case a vulnerability is exploited, the attacker won't have full root (UID/GID 0) privileges. But there is a downside : if you use a local folder for the persistent data , you will need to set the correct permissions so the unprivileged user can write data to it. Something like that should do the trick : shell mkdir bw-data && \\ chown root:101 bw-data && \\ chmod 770 bw-data Alternatively, if the folder already exists : chown -R root:101 bw-data && \\ chmod -R 770 bw-data Mounting the folder : docker run \\ ... -v ./bw-data:/data \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data","title":"Volume"},{"location":"integrations/#networks","text":"The easiest way to connect BunkerWeb to web applications is by using Docker networks. First of all, you will need to create a network : docker network create mynetwork Once it's created, you will need to connect the container to that network : docker run \\ ... --network mynetwork \\ ... bunkerity/bunkerweb:1.4.1 You will also need to do the same with your web application(s). Please note that the other containers are accessible using their name as the hostname. Here is the docker-compose equivalent : ... services : mybunker : image : bunkerity/bunkerweb:1.4.1 networks : - bw-net ... networks : bw-net :","title":"Networks"},{"location":"integrations/#docker-autoconf","text":"Docker autoconf integration Docker integration The Docker autoconf integration is an \"evolution\" of the Docker one. Please read the Docker integration section first if needed. The downside of using environment variables is that the container needs to be recreated each time there is an update which is not very convenient. To counter that issue, you can use another image called autoconf which will listen for Docker events and automatically reconfigure BunkerWeb in real-time without recreating the container. Instead of defining environment variables for the BunkerWeb container, you simply add labels to your web applications containers and the autoconf will \"automagically\" take care of the rest. Multisite mode The Docker autoconf integration implies the use of multisite mode . Please refer to the multisite section of the documentation for more information. First of all, you will need to create the data volume : docker volume create bw-data Then, you can create two networks (replace 10.20.30.0/24 with an unused subnet of your choice) : docker network create --subnet 10 .20.30.0/24 bw-autoconf && \\ docker network create bw-services One for communication between BunkerWeb and autoconf Another one for communication between BunkerWeb and web applications You can now create the BunkerWeb container with the AUTOCONF_MODE=yes setting and the bunkerweb.AUTOCONF label (replace 10.20.30.0/24 with the subnet specified before) : docker run \\ -d \\ --name mybunker \\ --network bw-autoconf \\ -p 80 :8080 \\ -p 443 :8443 \\ -e AUTOCONF_MODE = yes \\ -e MULTISITE = yes \\ -e SERVER_NAME = \\ -e \"API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24\" \\ -l bunkerweb.AUTOCONF \\ bunkerity/bunkerweb:1.4.1 && \\ docker network connect bw-services mybunker And the autoconf one : docker run \\ -d \\ --name myautoconf \\ --network bw-autoconf \\ -v bw-data:/data \\ -v /var/run/docker.sock:/var/run/docker.sock:ro \\ bunkerity/bunkerweb-autoconf:1.4.1 Here is the docker-compose equivalent for the BunkerWeb autoconf stack : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - 80:8080 - 443:8443 environment : - AUTOCONF_MODE=yes - MULTISITE=yes - SERVER_NAME= - API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24 labels : - \"bunkerweb.AUTOCONF\" networks : - bw-autoconf - bw-services myautoconf : image : bunkerity/bunkerweb-autoconf:1.4.1 volumes : - bw-data:/data - /var/run/docker.sock:/var/run/docker.sock:ro networks : - bw-autoconf volumes : bw-data : networks : bw-autoconf : ipam : driver : default config : - subnet : 10.20.30.0/24 bw-services : name : bw-services Once the stack is setup, you can now create the web application container and add the settings as labels using the \"bunkerweb.\" prefix in order to automatically setup BunkerWeb : docker run \\ -d \\ --name myapp \\ --network bw-services \\ -l bunkerweb.MY_SETTING_1 = value1 \\ -l bunkerweb.MY_SETTING_2 = value2 \\ ... mywebapp:4.2 Here is the docker-compose equivalent : ... services : myapp : image : mywebapp:4.2 networks : bw-services : aliases : - myapp labels : - \"bunkerweb.MY_SETTING_1=value1\" - \"bunkerweb.MY_SETTING_2=value2\" ... networks : bw-services : external : name : bw-services ...","title":"Docker autoconf"},{"location":"integrations/#swarm","text":"Docker Swarm integration Docker autoconf The Docker autoconf integration is similar of the Docker autoconf one (but with services instead of containers). Please read the Docker autoconf integration section first if needed. To automatically configure BunkerWeb instances, a special service, called autoconf , will be scheduled on a manager node. That service will listen for Docker Swarm events like service creation or deletion and automatically configure the BunkerWeb instances in real-time without downtime. Like the Docker autoconf integration , configuration for web services is defined using labels starting with the special bunkerweb. prefix. The recommended setup is to schedule the BunkerWeb service as a global service on all worker nodes and the autoconf service as a single replicated service on a manager node. First of all, you will need to create two networks (replace 10.20.30.0/24 with an unused subnet of your choice) : docker network create -d overlay --attachable --subnet 10 .20.30.0/24 bw-autoconf && \\ docker network create -d overlay --attachable bw-services One for communication between BunkerWeb and autoconf Another one for communication between BunkerWeb and web applications You can now create the BunkerWeb service (replace 10.20.30.0/24 with the subnet specified before) : docker service create \\ --name mybunker \\ --mode global \\ --constraint node.role == worker \\ --network bw-autoconf \\ --network bw-services \\ -p published = 80 ,target = 8080 ,mode = host \\ -p published = 443 ,target = 8443 ,mode = host \\ -e SWARM_MODE = yes \\ -e SERVER_NAME = \\ -e MULTISITE = yes \\ -e \"API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24\" \\ -l bunkerweb.AUTOCONF \\ bunkerity/bunkerweb:1.4.1 And the autoconf one : docker service \\ create \\ --name myautoconf \\ --constraint node.role == manager \\ --network bw-autoconf \\ --mount type = bind,source = /var/run/docker.sock,destination = /var/run/docker.sock,ro \\ --mount type = volume,source = bw-data,destination = /data \\ -e SWARM_MODE = yes \\ bunkerity/bunkerweb-autoconf:1.4.1 Here is the docker-compose equivalent (using docker stack deploy ) : version : '3.5' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - published : 80 target : 8080 mode : host protocol : tcp - published : 443 target : 8443 mode : host protocol : tcp environment : - SWARM_MODE=yes - SERVER_NAME= - MULTISITE=yes - API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24 networks : - bw-autoconf - bw-services deploy : mode : global placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.AUTOCONF\" myautoconf : image : bunkerity/bunkerweb-autoconf:1.4.1 environment : - SWARM_MODE=yes volumes : - bw-data:/data - /var/run/docker.sock:/var/run/docker.sock:ro networks : - bw-autoconf deploy : replicas : 1 placement : constraints : - \"node.role==manager\" networks : bw-autoconf : driver : overlay attachable : true name : bw-autoconf ipam : config : - subnet : 10.20.30.0/24 bw-services : driver : overlay attachable : true name : bw-services volumes : bw-data : Once the BunkerWeb Swarm stack is set up and running (see autoconf logs for more information), you can now deploy web applications in the cluster and use labels to dynamically configure BunkerWeb : docker service \\ create \\ --name myapp \\ --network bw-services \\ -l bunkerweb.MY_SETTING_1 = value1 \\ -l bunkerweb.MY_SETTING_2 = value2 \\ ... mywebapp:4.2 Here is the docker-compose equivalent (using docker stack deploy ) : ... services : myapp : image : mywebapp:4.2 networks : - bw-services deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.MY_SETTING_1=value1\" - \"bunkerweb.MY_SETTING_2=value2\" ... networks : bw-services : external : name : bw-services","title":"Swarm"},{"location":"integrations/#kubernetes","text":"Kubernetes integration The autoconf acts as an Ingress controller and will configure the BunkerWeb instances according to the Ingress resources . It also monitors other Kubernetes objects like ConfigMap for custom configurations. The first step to install BunkerWeb on a Kubernetes cluster is to add a role and permissions on the cluster for the autoconf : apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRole metadata : name : cr-bunkerweb rules : - apiGroups : [ \"\" ] resources : [ \"services\" , \"pods\" , \"configmaps\" ] verbs : [ \"get\" , \"watch\" , \"list\" ] - apiGroups : [ \"networking.k8s.io\" ] resources : [ \"ingresses\" ] verbs : [ \"get\" , \"watch\" , \"list\" ] --- apiVersion : v1 kind : ServiceAccount metadata : name : sa-bunkerweb --- apiVersion : rbac.authorization.k8s.io/v1 kind : ClusterRoleBinding metadata : name : crb-bunkerweb subjects : - kind : ServiceAccount name : sa-bunkerweb namespace : default apiGroup : \"\" roleRef : kind : ClusterRole name : cr-bunkerweb apiGroup : rbac.authorization.k8s.io The recommended way of deploying BunkerWeb is using a DaemonSet which means each node in the cluster will run an instance of BunkerWeb : apiVersion : apps/v1 kind : DaemonSet metadata : name : bunkerweb spec : selector : matchLabels : app : bunkerweb template : metadata : labels : app : bunkerweb # mandatory annotation annotations : bunkerweb.io/AUTOCONF : \"yes\" spec : containers : - name : bunkerweb image : bunkerity/bunkerweb securityContext : runAsUser : 101 runAsGroup : 101 allowPrivilegeEscalation : false capabilities : drop : - ALL ports : - containerPort : 8080 hostPort : 80 - containerPort : 8443 hostPort : 443 env : - name : KUBERNETES_MODE value : \"yes\" # replace with your DNS resolvers # e.g. : kube-dns.kube-system.svc.cluster.local - name : DNS_RESOLVERS value : \"coredns.kube-system.svc.cluster.local\" - name : USE_API value : \"yes\" # 10.0.0.0/8 is the cluster internal subnet - name : API_WHITELIST_IP value : \"127.0.0.0/8 10.0.0.0/8\" - name : SERVER_NAME value : \"\" - name : MULTISITE value : \"yes\" livenessProbe : exec : command : - /opt/bunkerweb/helpers/healthcheck.sh initialDelaySeconds : 30 periodSeconds : 5 timeoutSeconds : 1 failureThreshold : 3 readinessProbe : exec : command : - /opt/bunkerweb/helpers/healthcheck.sh initialDelaySeconds : 30 periodSeconds : 1 timeoutSeconds : 1 failureThreshold : 3 --- apiVersion : v1 kind : Service metadata : name : svc-bunkerweb spec : clusterIP : None selector : app : bunkerweb In order to store persistent data, you will need a PersistentVolumeClaim : apiVersion : v1 kind : PersistentVolumeClaim metadata : name : pvc-bunkerweb spec : accessModes : - ReadWriteOnce resources : requests : storage : 5Gi Now, you can start the autoconf as a single replica Deployment : apiVersion : apps/v1 kind : Deployment metadata : name : bunkerweb-controller spec : replicas : 1 strategy : type : Recreate selector : matchLabels : app : bunkerweb-controller template : metadata : labels : app : bunkerweb-controller spec : serviceAccountName : sa-bunkerweb volumes : - name : vol-bunkerweb persistentVolumeClaim : claimName : pvc-bunkerweb containers : - name : bunkerweb-controller image : bunkerity/bunkerweb-autoconf imagePullPolicy : Always env : - name : KUBERNETES_MODE value : \"yes\" volumeMounts : - name : vol-bunkerweb mountPath : /data Once the BunkerWeb Kubernetes stack is setup and running (see autoconf logs for more information), you can now deploy web applications in the cluster and declare your Ingress resource. Please note that settings need to be set as annotations for the Ingress resource with the special value bunkerweb.io for the domain part : apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : ingress annotations : bunkerweb.io/MY_SETTING_1 : \"value1\" bunkerweb.io/MY_SETTING_2 : \"value2\" spec : rules : ...","title":"Kubernetes"},{"location":"integrations/#linux","text":"Linux integration List of supported Linux distros : Debian 11 \"Bullseye\" Ubuntu 22.04 \"Jammy\" Fedora 36 CentOS Stream 8 Please note that you will need to install NGINX 1.20.2 before BunkerWeb . For all distros, except Fedora, using prebuilt packages from official NGINX repository is mandatory. Compiling NGINX from source or using packages from different repositories won't work with the official prebuild packages of BunkerWeb but you can build it from source. Repositories of Linux packages for BunkerWeb are available on PackageCloud , they provide a bash script to automatically add and trust the repository (but you can also follow the manual installation instructions if you prefer). Debian Ubuntu Fedora CentOS Stream From source The first step is to add NGINX official repository : sudo apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring && \\ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \\ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null && \\ echo \"deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \\ http://nginx.org/packages/debian `lsb_release -cs` nginx\" \\ | sudo tee /etc/apt/sources.list.d/nginx.list You should now be able to install NGINX 1.20.2 : sudo apt update && \\ sudo apt install -y nginx = 1 .20.2-1~bullseye And finally install BunkerWeb 1.4.1 : curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.deb.sh | sudo bash && \\ sudo apt update && \\ sudo apt install -y bunkerweb = 1 .4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing apt upgrade , you can use the following command : sudo apt-mark hold nginx bunkerweb The first step is to add NGINX official repository : sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring && \\ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \\ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null && \\ echo \"deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \\ http://nginx.org/packages/ubuntu `lsb_release -cs` nginx\" \\ | sudo tee /etc/apt/sources.list.d/nginx.list You should now be able to install NGINX 1.20.2 : sudo apt update && \\ sudo apt install -y nginx = 1 .20.2-1~jammy And finally install BunkerWeb 1.4.1 : curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.deb.sh | sudo bash && \\ sudo apt update && \\ sudo apt install -y bunkerweb = 1 .4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing apt upgrade , you can use the following command : sudo apt-mark hold nginx bunkerweb Fedora already provides NGINX 1.20.2 that we support : sudo dnf install -y nginx-1.20.2 curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.rpm.sh | sudo bash && \\ sudo dnf check-update && \\ sudo dnf install -y bunkerweb-1.4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing dnf upgrade , you can use the following command : sudo dnf versionlock add nginx && \\ sudo dnf versionlock add bunkerweb The first step is to add NGINX official repository, create the following file at /etc/yum.repos.d/nginx.repo : [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true You should now be able to install NGINX 1.20.2 : sudo dnf install nginx-1.20.2 And finally install BunkerWeb 1.4.1 : dnf install -y epel-release && \\ curl -s https://packagecloud.io/install/repositories/bunkerity/bunkerweb/script.rpm.sh | sudo bash && \\ sudo dnf check-update && \\ sudo dnf install -y bunkerweb-1.4.1 To prevent upgrading NGINX and/or BunkerWeb packages when executing dnf upgrade , you can use the following command : sudo dnf versionlock add nginx && \\ sudo dnf versionlock add bunkerweb The first step is to install NGINX 1.20.2 using the repository of your choice or by compiling it from source . The target installation folder of BunkerWeb is located at /opt/bunkerweb , let's create it : mkdir /opt/bunkerweb You can now clone the BunkerWeb project to the /tmp folder : https://github.com/bunkerity/bunkerweb.git /tmp/bunkerweb BunkerWeb needs some dependencies to be compiled and install to /opt/bunkerweb/deps , the easiest way to it is by executing the install.sh helper script (please note that you will need to install additional packages which is not covered in this procedure and depends on your own system) : mkdir /opt/bunkerweb/deps && \\ /tmp/bunkerweb/deps/install.sh Additional Python dependencies needs to be installed into the /opt/bunkerweb/deps/python folder : mkdir /opt/bunkerweb/deps/python && \\ pip install --no-cache-dir --require-hashes --target /opt/bunkerweb/deps/python -r /tmp/bunkerweb/deps/requirements.txt && \\ pip install --no-cache-dir --target /opt/bunkerweb/deps/python -r /tmp/bunkerweb/ui/requirements.txt Once dependencies had been installed, you can now copy the BunkerWeb sources to the target /opt/bunkerweb folder : for src in api cli confs core gen helpers job lua misc utils ui settings.json VERSION linux/variables.env linux/bunkerweb-ui.env linux/scripts ; do cp -r /tmp/bunkerweb/ ${ src } /opt/bunkerweb done cp /opt/bunkerweb/helpers/bwcli /usr/local/bin Additional folders also need to be created : mkdir /opt/bunkerweb/ { configs,cache,plugins,tmp } Permissions needs to be fixed : find /opt/bunkerweb -path /opt/bunkerweb/deps -prune -o -type f -exec chmod 0740 {} \\; && \\ find /opt/bunkerweb -path /opt/bunkerweb/deps -prune -o -type d -exec chmod 0750 {} \\; && \\ find /opt/bunkerweb/core/*/jobs/* -type f -exec chmod 750 {} \\; && \\ chmod 770 /opt/bunkerweb/cache /opt/bunkerweb/tmp && \\ chmod 750 /opt/bunkerweb/gen/main.py /opt/bunkerweb/job/main.py /opt/bunkerweb/cli/main.py /opt/bunkerweb/helpers/*.sh /opt/bunkerweb/scripts/*.sh /usr/local/bin/bwcli /opt/bunkerweb/ui/main.py && \\ chown -R root:nginx /opt/bunkerweb Last but not least, you will need to setup systemd unit files : cp /tmp/bunkerweb/linux/*.service /etc/systemd/system && \\ systemctl daemon-reload && \\ systemctl stop nginx && \\ systemctl disable nginx && \\ systemctl enable bunkerweb && \\ systemctl enable bunkerweb-ui Configuration of BunkerWeb is done by editing the /opt/bunkerweb/variables.env file : MY_SETTING_1=value1 MY_SETTING_2=value2 ... BunkerWeb is managed using systemctl : Check BunkerWeb status : systemctl status bunkerweb Reload the configuration : systemctl reload bunkerweb Start it if it's stopped : systemctl start bunkerweb Stop it if it's started : systemctl stop bunkerweb And restart : systemctl restart bunkerweb","title":"Linux"},{"location":"migrating/","text":"Migrating from bunkerized Read this if you were a bunkerized user A lot of things have changed since the last bunkerized release. If you want to do an upgrade, which we recommend you to do because BunkerWeb is by far better than bunkerized, please read carefully this section and also the whole documentation. Volumes When using container-based integrations like Docker , Docker autoconf , Swarm or Kubernetes , volumes for storing data like certificates, cache or custom configurations has changed. We now have a single \"bw-data\" volume which contains everything and should be easier to manage than bunkerized. Removed features We decided to drop the following features : Blocking \"bad\" referrers : we may add it again in the future ROOT_SITE_SUBFOLDER : we will need to redesign this in the future Changed Authelia support Instead of supporting only Authelia, we decided to support generic auth request settings. See the new authelia example and auth request documentation for more information. Replaced BLOCK_*, WHITELIST_* and BLACKLIST_* settings The blocking mechanisms has been completely redesigned. We have detected that a lot of false positives came from the default blacklists hardcoded into bunkerized. That's why we decided to give the users the choice of their blacklists (and also whitelists) for IP address, reverse DNS, user-agent, URI and ASN, see the Blacklisting and whitelisting section of the security tuning . Changed WHITELIST_USER_AGENT setting behavior The new behavior of the WHITELIST_USER_AGENT setting is to disable completely security checks if the User-Agent value of a client match any of the patterns. In bunkerized it was used to ignore specific User-Agent values when BLOCK_USER_AGENT was set to yes to avoid false positives. You can choose the blacklist of your choice to avoid FP (see previous section). Changed PROXY_REAL_IP_* settings To avoid any confusion between reverse proxy and real IP, we decided to renamed the PROXY_REAL_IP_* settings, you will find more information on the subject here . Default values and new settings The default value of settings may have changed and we have added many other settings, we recommend you to read the security tuning and settings sections of the documentation.","title":"Migrating from bunkerized"},{"location":"migrating/#migrating-from-bunkerized","text":"Read this if you were a bunkerized user A lot of things have changed since the last bunkerized release. If you want to do an upgrade, which we recommend you to do because BunkerWeb is by far better than bunkerized, please read carefully this section and also the whole documentation.","title":"Migrating from bunkerized"},{"location":"migrating/#volumes","text":"When using container-based integrations like Docker , Docker autoconf , Swarm or Kubernetes , volumes for storing data like certificates, cache or custom configurations has changed. We now have a single \"bw-data\" volume which contains everything and should be easier to manage than bunkerized.","title":"Volumes"},{"location":"migrating/#removed-features","text":"We decided to drop the following features : Blocking \"bad\" referrers : we may add it again in the future ROOT_SITE_SUBFOLDER : we will need to redesign this in the future","title":"Removed features"},{"location":"migrating/#changed-authelia-support","text":"Instead of supporting only Authelia, we decided to support generic auth request settings. See the new authelia example and auth request documentation for more information.","title":"Changed Authelia support"},{"location":"migrating/#replaced-block_-whitelist_-and-blacklist_-settings","text":"The blocking mechanisms has been completely redesigned. We have detected that a lot of false positives came from the default blacklists hardcoded into bunkerized. That's why we decided to give the users the choice of their blacklists (and also whitelists) for IP address, reverse DNS, user-agent, URI and ASN, see the Blacklisting and whitelisting section of the security tuning .","title":"Replaced BLOCK_*, WHITELIST_* and BLACKLIST_* settings"},{"location":"migrating/#changed-whitelist_user_agent-setting-behavior","text":"The new behavior of the WHITELIST_USER_AGENT setting is to disable completely security checks if the User-Agent value of a client match any of the patterns. In bunkerized it was used to ignore specific User-Agent values when BLOCK_USER_AGENT was set to yes to avoid false positives. You can choose the blacklist of your choice to avoid FP (see previous section).","title":"Changed WHITELIST_USER_AGENT setting behavior"},{"location":"migrating/#changed-proxy_real_ip_-settings","text":"To avoid any confusion between reverse proxy and real IP, we decided to renamed the PROXY_REAL_IP_* settings, you will find more information on the subject here .","title":"Changed PROXY_REAL_IP_* settings"},{"location":"migrating/#default-values-and-new-settings","text":"The default value of settings may have changed and we have added many other settings, we recommend you to read the security tuning and settings sections of the documentation.","title":"Default values and new settings"},{"location":"plugins/","text":"Plugins BunkerWeb comes with a plugin system to make it possible to easily add new features. Once a plugin is installed, you can manage it using additional settings defined by the plugin. Official plugins Here is the list of \"official\" plugins that we maintain (see the bunkerweb-plugins repository for more information) : Name Version Description Link ClamAV 0.1 Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. bunkerweb-plugins/clamav CrowdSec 0.1 CrowdSec bouncer for BunkerWeb. bunkerweb-plugins/crowdsec VirusTotal 0.1 Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. bunkerweb-plugins/virustotal How to use a plugin The first step is to install the plugin by putting the plugin files inside the corresponding plugins data folder, the procedure depends on your integration : Docker Docker autoconf Swarm Kubernetes Linux When using the Docker integration , plugins must be written to the volume mounted on /data . The first thing to do is to create the plugins folder : mkdir -p ./bw-data/plugins Then you can drop the plugins of your choice into that folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* ./bw-data/plugins Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When starting the BunkerWeb container, you will need to mount the folder on /data : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data ... When using the Docker autoconf integration , plugins must be written to the volume mounted on /data . The easiest way to do it is by starting the Docker autoconf stack with a folder mounted on /data (instead of a named volume). Once the stack is started, you can copy the plugins of your choice to the plugins folder from your host : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* ./bw-data/plugins Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When using the Swarm integration , the easiest way of installing plugins is by using docker exec and downloading the plugins from the container. Execute a shell inside the autoconf container (use docker ps to get the name) : docker exec -it myautoconf /bin/bash Once you have a shell inside the container, you can drop the plugins of your choice inside the /data/plugins folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* /data/plugins When using the Kubernetes integration , the easiest way of installing plugins is by using kubectl exec and downloading the plugins from the container. Execute a shell inside the autoconf container (use kubectl get pods to get the name) : kubectl exec -it myautoconf -- /bin/bash Once you have a shell inside the container, you can drop the plugins of your choice inside the /data/plugins folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* /data/plugins When using the Linux integration , plugins must be written to the /opt/bunkerweb/plugins folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* /data/plugins When a plugin is installed, you are ready to use it, please refer to the plugin documentation for more information. Writing a plugin Existing plugins If the documentation is not enough you can have a look at the existing source code of official plugins and the core plugins (already included in BunkerWeb but they are plugins technically speaking). The first step is to create a folder that will contain the plugin : mkdir myplugin && \\ cd myplugin Metadata A file named plugin.json and written at the root of the plugin folder must contain metadata about the plugin. Here is an example : { \"id\" : \"myplugin\" , \"order\" : 42 , \"name\" : \"My Plugin\" , \"description\" : \"Just an example plugin.\" , \"version\" : \"1.0\" , \"settings\" : { \"DUMMY_SETTING\" : { \"context\" : \"multisite\" , \"default\" : \"1234\" , \"help\" : \"Here is the help of the setting.\" , \"id\" : \"dummy-id\" , \"label\" : \"Dummy setting\" , \"regex\" : \"^.*$\" , \"type\" : \"text\" } } \"jobs\" : [ { \"name\" : \"my-job\" , \"file\" : \"my-job.py\" , \"every\" : \"hour\" } ] } Here are the details of the fields : Field Mandatory Type Description id yes string Internal ID for the plugin : must be unique among other plugins (including \"core\" ones) and contain only lowercase chars. order yes int When the plugin should be executed during the access phase : 1 for whitelisting, 2 for blacklisting, 3 for \"standard security feature\" or 999 if your settings don't use the access phase. name yes string Name of your plugin. description yes string Description of your plugin. version yes string Version of your plugin. settings yes dict List of the settings of your plugin. jobs no list List of the jobs of your plugin. Each setting has the following fields (the key is the ID of the settings used in a configuration) : Field Mandatory Type Description context yes string Context of the setting : multisite or global . default yes string The default value of the setting. help yes string Help text about the plugin (shown in web UI). id yes string Internal ID used by the web UI for HTML elements. label yes string Label shown by the web UI. regex yes string The regex used to validate the value provided by the user. type yes string The type of the field : text , check or select . multiple no string Unique ID to group multiple settings with numbers as suffix. select no list List of possible string values when type is select . Each job has the following fields : Field Mandatory Type Description name yes string Name of the job. file yes string Name of the file inside the jobs folder. every yes string Job scheduling frequency : minute , hour , day , week or once (no frequency, only once before (re)generating the configuration). Configurations You can add custom NGINX configurations by adding a folder named confs with content similar to the custom configurations . Each subfolder inside the confs will contain jinja2 templates that will be generated and loaded at the corresponding context ( http , server-http and default-server-http ). Here is an example for a configuration template file inside the confs/server-http folder named example.conf : location /setting { default_type 'text/plain'; content_by_lua_block { ngx.say('{{ DUMMY_SETTING }}') } } {{ DUMMY_SETTING }} will be replaced by the value of the DUMMY_SETTING chosen by the user of the plugin. LUA Main script Under the hood, BunkerWeb is using the NGINX LUA module to execute code within NGINX. Plugins that need to execute code must provide a lua file at the root directory of the plugin folder using the id value of plugin.json as its name. Here is an example named myplugin.lua : local _M = {} _M . __index = _M local utils = require \"utils\" local datastore = require \"datastore\" local logger = require \"logger\" function _M . new () local self = setmetatable ({}, _M ) self . dummy = \"dummy\" return self , nil end function _M : init () logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"init called\" ) return true , \"success\" end function _M : access () logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"access called\" ) return true , \"success\" , nil , nil end function _M : log () logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"log called\" ) return true , \"success\" end return _M The 3 functions init , access , and log are automatically called during specific contexts. Here are the details of each function : Function Context Description Return value init init_by_lua Called when NGINX just started or received a reload order. the typical use case is to prepare any data that will be used by your plugin. ret , err ret (boolean) : true if no error else false err (string) : success or error message access access_by_lua Called on each request received by the server. The typical use case is to do the security checks here and deny the request if needed. ret , err , return , status ret (boolean) : true if no error else false err (string) : success or error message return (boolean) : true if you want to stop the access phase and send a status to the client status (number) : the return value to set if return is set to true log log_by_lua Called when a request has finished (and before it gets logged to the access logs). The typical use case is to make stats or compute counters for example. ret , err ret (boolean) : true if no error else false err (string) : success or error message Libraries All directives from NGINX LUA module are available. On top of that, you can use the LUA libraries included within BunkerWeb : see this script for the complete list. If you need additional libraries, you can put them in the root folder of the plugin and access them by prefixing them with your plugin ID. Here is an example file named mylibrary.lua : local _M = {} _M . dummy = function () return \"dummy\" end return _M And here is how you can use it from the myplugin.lua file : local mylibrary = require \"myplugin.mylibrary\" ... mylibrary . dummy () ... Helpers Some helpers modules provide common helpful functions : datastore : access the global shared data (key/value store) logger : generate logs utils : various useful functions To access the functions, you first need to require the module : ... local utils = require \"utils\" local datastore = require \"datastore\" local logger = require \"logger\" ... Retrieve a setting value : local value , err = utils : get_variable ( \"DUMMY_SETTING\" ) if not value then logger . log ( ngx . ERR , \"MYPLUGIN\" , \"can't retrieve setting DUMMY_SETTING : \" .. err ) else logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"DUMMY_SETTING = \" .. value ) end Store something in the cache : local ok , err = datastore : set ( \"plugin_myplugin_something\" , \"somevalue\" ) if not value then logger . log ( ngx . ERR , \"MYPLUGIN\" , \"can't save plugin_myplugin_something into datastore : \" .. err ) else logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"successfully saved plugin_myplugin_something into datastore into datastore\" ) end Check if an IP address is global : local ret , err = utils . ip_is_global ( ngx . var . remote_addr ) if ret == nil then logger . log ( ngx . ERR , \"MYPLUGIN\" , \"error while checking if IP \" .. ngx . var . remote_addr .. \" is global or not : \" .. err ) elseif not ret then logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"IP \" .. ngx . var . remote_addr .. \" is not global\" ) else logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"IP \" .. ngx . var . remote_addr .. \" is global\" ) end More examples If you want to see the full list of available functions, you can have a look at the files present in the lua directory of the repository. Jobs BunkerWeb uses an internal job scheduler for periodic tasks like renewing certificates with certbot, downloading blacklists, downloading MMDB files, ... You can add tasks of your choice by putting them inside a subfolder named jobs and listing them in the plugin.json metadata file. Don't forget to add the execution permissions for everyone to avoid any problems when a user is cloning and installing your plugin.","title":"Plugins"},{"location":"plugins/#plugins","text":"BunkerWeb comes with a plugin system to make it possible to easily add new features. Once a plugin is installed, you can manage it using additional settings defined by the plugin.","title":"Plugins"},{"location":"plugins/#official-plugins","text":"Here is the list of \"official\" plugins that we maintain (see the bunkerweb-plugins repository for more information) : Name Version Description Link ClamAV 0.1 Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. bunkerweb-plugins/clamav CrowdSec 0.1 CrowdSec bouncer for BunkerWeb. bunkerweb-plugins/crowdsec VirusTotal 0.1 Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. bunkerweb-plugins/virustotal","title":"Official plugins"},{"location":"plugins/#how-to-use-a-plugin","text":"The first step is to install the plugin by putting the plugin files inside the corresponding plugins data folder, the procedure depends on your integration : Docker Docker autoconf Swarm Kubernetes Linux When using the Docker integration , plugins must be written to the volume mounted on /data . The first thing to do is to create the plugins folder : mkdir -p ./bw-data/plugins Then you can drop the plugins of your choice into that folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* ./bw-data/plugins Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When starting the BunkerWeb container, you will need to mount the folder on /data : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data ... When using the Docker autoconf integration , plugins must be written to the volume mounted on /data . The easiest way to do it is by starting the Docker autoconf stack with a folder mounted on /data (instead of a named volume). Once the stack is started, you can copy the plugins of your choice to the plugins folder from your host : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* ./bw-data/plugins Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When using the Swarm integration , the easiest way of installing plugins is by using docker exec and downloading the plugins from the container. Execute a shell inside the autoconf container (use docker ps to get the name) : docker exec -it myautoconf /bin/bash Once you have a shell inside the container, you can drop the plugins of your choice inside the /data/plugins folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* /data/plugins When using the Kubernetes integration , the easiest way of installing plugins is by using kubectl exec and downloading the plugins from the container. Execute a shell inside the autoconf container (use kubectl get pods to get the name) : kubectl exec -it myautoconf -- /bin/bash Once you have a shell inside the container, you can drop the plugins of your choice inside the /data/plugins folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* /data/plugins When using the Linux integration , plugins must be written to the /opt/bunkerweb/plugins folder : git clone https://github.com/bunkerity/bunkerweb-plugins && \\ cp -rp ./bunkerweb-plugins/* /data/plugins When a plugin is installed, you are ready to use it, please refer to the plugin documentation for more information.","title":"How to use a plugin"},{"location":"plugins/#writing-a-plugin","text":"Existing plugins If the documentation is not enough you can have a look at the existing source code of official plugins and the core plugins (already included in BunkerWeb but they are plugins technically speaking). The first step is to create a folder that will contain the plugin : mkdir myplugin && \\ cd myplugin","title":"Writing a plugin"},{"location":"plugins/#metadata","text":"A file named plugin.json and written at the root of the plugin folder must contain metadata about the plugin. Here is an example : { \"id\" : \"myplugin\" , \"order\" : 42 , \"name\" : \"My Plugin\" , \"description\" : \"Just an example plugin.\" , \"version\" : \"1.0\" , \"settings\" : { \"DUMMY_SETTING\" : { \"context\" : \"multisite\" , \"default\" : \"1234\" , \"help\" : \"Here is the help of the setting.\" , \"id\" : \"dummy-id\" , \"label\" : \"Dummy setting\" , \"regex\" : \"^.*$\" , \"type\" : \"text\" } } \"jobs\" : [ { \"name\" : \"my-job\" , \"file\" : \"my-job.py\" , \"every\" : \"hour\" } ] } Here are the details of the fields : Field Mandatory Type Description id yes string Internal ID for the plugin : must be unique among other plugins (including \"core\" ones) and contain only lowercase chars. order yes int When the plugin should be executed during the access phase : 1 for whitelisting, 2 for blacklisting, 3 for \"standard security feature\" or 999 if your settings don't use the access phase. name yes string Name of your plugin. description yes string Description of your plugin. version yes string Version of your plugin. settings yes dict List of the settings of your plugin. jobs no list List of the jobs of your plugin. Each setting has the following fields (the key is the ID of the settings used in a configuration) : Field Mandatory Type Description context yes string Context of the setting : multisite or global . default yes string The default value of the setting. help yes string Help text about the plugin (shown in web UI). id yes string Internal ID used by the web UI for HTML elements. label yes string Label shown by the web UI. regex yes string The regex used to validate the value provided by the user. type yes string The type of the field : text , check or select . multiple no string Unique ID to group multiple settings with numbers as suffix. select no list List of possible string values when type is select . Each job has the following fields : Field Mandatory Type Description name yes string Name of the job. file yes string Name of the file inside the jobs folder. every yes string Job scheduling frequency : minute , hour , day , week or once (no frequency, only once before (re)generating the configuration).","title":"Metadata"},{"location":"plugins/#configurations","text":"You can add custom NGINX configurations by adding a folder named confs with content similar to the custom configurations . Each subfolder inside the confs will contain jinja2 templates that will be generated and loaded at the corresponding context ( http , server-http and default-server-http ). Here is an example for a configuration template file inside the confs/server-http folder named example.conf : location /setting { default_type 'text/plain'; content_by_lua_block { ngx.say('{{ DUMMY_SETTING }}') } } {{ DUMMY_SETTING }} will be replaced by the value of the DUMMY_SETTING chosen by the user of the plugin.","title":"Configurations"},{"location":"plugins/#lua","text":"","title":"LUA"},{"location":"plugins/#main-script","text":"Under the hood, BunkerWeb is using the NGINX LUA module to execute code within NGINX. Plugins that need to execute code must provide a lua file at the root directory of the plugin folder using the id value of plugin.json as its name. Here is an example named myplugin.lua : local _M = {} _M . __index = _M local utils = require \"utils\" local datastore = require \"datastore\" local logger = require \"logger\" function _M . new () local self = setmetatable ({}, _M ) self . dummy = \"dummy\" return self , nil end function _M : init () logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"init called\" ) return true , \"success\" end function _M : access () logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"access called\" ) return true , \"success\" , nil , nil end function _M : log () logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"log called\" ) return true , \"success\" end return _M The 3 functions init , access , and log are automatically called during specific contexts. Here are the details of each function : Function Context Description Return value init init_by_lua Called when NGINX just started or received a reload order. the typical use case is to prepare any data that will be used by your plugin. ret , err ret (boolean) : true if no error else false err (string) : success or error message access access_by_lua Called on each request received by the server. The typical use case is to do the security checks here and deny the request if needed. ret , err , return , status ret (boolean) : true if no error else false err (string) : success or error message return (boolean) : true if you want to stop the access phase and send a status to the client status (number) : the return value to set if return is set to true log log_by_lua Called when a request has finished (and before it gets logged to the access logs). The typical use case is to make stats or compute counters for example. ret , err ret (boolean) : true if no error else false err (string) : success or error message","title":"Main script"},{"location":"plugins/#libraries","text":"All directives from NGINX LUA module are available. On top of that, you can use the LUA libraries included within BunkerWeb : see this script for the complete list. If you need additional libraries, you can put them in the root folder of the plugin and access them by prefixing them with your plugin ID. Here is an example file named mylibrary.lua : local _M = {} _M . dummy = function () return \"dummy\" end return _M And here is how you can use it from the myplugin.lua file : local mylibrary = require \"myplugin.mylibrary\" ... mylibrary . dummy () ...","title":"Libraries"},{"location":"plugins/#helpers","text":"Some helpers modules provide common helpful functions : datastore : access the global shared data (key/value store) logger : generate logs utils : various useful functions To access the functions, you first need to require the module : ... local utils = require \"utils\" local datastore = require \"datastore\" local logger = require \"logger\" ... Retrieve a setting value : local value , err = utils : get_variable ( \"DUMMY_SETTING\" ) if not value then logger . log ( ngx . ERR , \"MYPLUGIN\" , \"can't retrieve setting DUMMY_SETTING : \" .. err ) else logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"DUMMY_SETTING = \" .. value ) end Store something in the cache : local ok , err = datastore : set ( \"plugin_myplugin_something\" , \"somevalue\" ) if not value then logger . log ( ngx . ERR , \"MYPLUGIN\" , \"can't save plugin_myplugin_something into datastore : \" .. err ) else logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"successfully saved plugin_myplugin_something into datastore into datastore\" ) end Check if an IP address is global : local ret , err = utils . ip_is_global ( ngx . var . remote_addr ) if ret == nil then logger . log ( ngx . ERR , \"MYPLUGIN\" , \"error while checking if IP \" .. ngx . var . remote_addr .. \" is global or not : \" .. err ) elseif not ret then logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"IP \" .. ngx . var . remote_addr .. \" is not global\" ) else logger . log ( ngx . NOTICE , \"MYPLUGIN\" , \"IP \" .. ngx . var . remote_addr .. \" is global\" ) end More examples If you want to see the full list of available functions, you can have a look at the files present in the lua directory of the repository.","title":"Helpers"},{"location":"plugins/#jobs","text":"BunkerWeb uses an internal job scheduler for periodic tasks like renewing certificates with certbot, downloading blacklists, downloading MMDB files, ... You can add tasks of your choice by putting them inside a subfolder named jobs and listing them in the plugin.json metadata file. Don't forget to add the execution permissions for everyone to avoid any problems when a user is cloning and installing your plugin.","title":"Jobs"},{"location":"quickstart-guide/","text":"Quickstart guide Prerequisites We assume that you're already familiar with the core concepts and you have followed the integrations instructions for your environment. Going further To demonstrate the use of BunkerWeb, we will deploy a dummy \"Hello World\" web application as an example. See the examples folder of the repository to get real-world examples. Protect HTTP applications Protecting existing web applications already accessible with the HTTP(S) protocol is the main goal of BunkerWeb : it will act as a classical reverse proxy with extra security features. The following settings can be used : USE_REVERSE_PROXY : enable/disable reverse proxy mode REVERSE_PROXY_URL : the public path prefix REVERSE_PROXY_HOST : (internal) address of the proxied web application You will find more settings about reverse proxy in the settings section of the documentation. Single application Docker Docker autoconf Swarm Kubernetes Linux When using Docker integration, the easiest way of protecting an existing application is to create a network so BunkerWeb can send requests using the container name. Create the Docker network if it's not already created : docker network create bw-net Then instantiate your app : docker run -d \\ --name myapp \\ --network bw-net \\ nginxdemos/hello:plain-text Create the BunkerWeb volume if it's not already created : docker volume create bw-data You can now run BunkerWeb and configure it for your app : docker run -d \\ --name mybunker \\ --network bw-net \\ -p 80 :8080 \\ -p 443 :8443 \\ -v bw-data:/data \\ -e SERVER_NAME = www.example.com \\ -e USE_REVERSE_PROXY = yes \\ -e REVERSE_PROXY_URL = / \\ -e REVERSE_PROXY_HOST = http://myapp \\ bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - 80:8080 - 443:8443 volumes : - bw-data:/data environment : - USE_REVERSE_PROXY=yes - REVERSE_PROXY_URL=/ - REVERSE_PROXY_HOST=http://myapp networks : - bw-net myapp : image : nginxdemos/hello:plain-text networks : - bw-net volumes : bw-data : networks : bw-net : name : bw-net We will assume that you already have the Docker autoconf integration stack running on your machine and connected to a network called bw-services. You can instantiate your container and pass the settings as labels : docker run -d \\ --name myapp \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = www.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp labels : - \"bunkerweb.SERVER_NAME=www.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp\" networks : bw-services : external : name : bw-services We will assume that you already have the Swarm integration stack running on your cluster. You can instantiate your service and pass the settings as labels : docker service \\ create \\ --name myapp \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = www.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=www.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp\" networks : bw-services : external : name : bw-services We will assume that you already have the Kubernetes integration stack running on your cluster. Let's assume that you have a typical Deployment with a Service to access the web application from within the cluster : apiVersion : apps/v1 kind : Deployment metadata : name : app labels : app : app spec : replicas : 1 selector : matchLabels : app : app template : metadata : labels : app : app spec : containers : - name : app image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app spec : selector : app : app ports : - protocol : TCP port : 80 targetPort : 80 Here is the corresponding Ingress definition to serve and protect the web application : apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : ingress annotations : bunkerweb.io/AUTOCONF : \"yes\" spec : rules : - host : www.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app port : number : 80 We will assume that you already have the Linux integration stack running on your machine. The following command will run a basic HTTP server on the port 8000 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 Configuration of BunkerWeb is done by editing the /opt/bunkerweb/variables.env file : SERVER_NAME=www.example.com HTTP_PORT=80 HTTPS_PORT=443 DNS_RESOLVERS=8.8.8.8 8.8.4.4 USE_REVERSE_PROXY=yes REVERSE_PROXY_URL=/ REVERSE_PROXY_HOST=http://127.0.0.1:8000 Let's check the status of BunkerWeb : systemctl status bunkerweb If it's already running we can just reload it : systemctl reload bunkerweb Otherwise, we will need to start it : systemctl start bunkerweb Multiple applications Testing To perform quick tests when multisite mode is enabled (and if you don't have the proper DNS entries set up for the domains) you can use curl with the HTTP Host header of your choice : shell curl -H \"Host: app1.example.com\" http://ip-or-fqdn-of-server Docker Docker autoconf Swarm Kubernetes Linux When using Docker integration, the easiest way of protecting multiple existing applications is to create a network so BunkerWeb can send requests using the container names. Create the Docker network if it's not already created : docker network create bw-net Then instantiate your apps : App #1 App #2 App #3 docker run -d \\ --name myapp1 \\ --network bw-net \\ nginxdemos/hello:plain-text docker run -d \\ --name myapp2 \\ --network bw-net \\ nginxdemos/hello:plain-text docker run -d \\ --name myapp3 \\ --network bw-net \\ nginxdemos/hello:plain-text Create the BunkerWeb volume if it's not already created : docker volume create bw-data You can now run BunkerWeb and configure it for your apps : docker run -d \\ --name mybunker \\ --network bw-net \\ -p 80 :8080 \\ -p 443 :8443 \\ -v bw-data:/data \\ -e MULTISITE = yes -e \"SERVER_NAME=app1.example.com app2.example.com app3.example.com\" \\ -e USE_REVERSE_PROXY = yes \\ -e REVERSE_PROXY_URL = / \\ -e app1.example.com_REVERSE_PROXY_HOST = http://myapp1 \\ -e app2.example.com_REVERSE_PROXY_HOST = http://myapp2 \\ -e app3.example.com_REVERSE_PROXY_HOST = http://myapp3 \\ bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - 80:8080 - 443:8443 volumes : - bw-data:/data environment : - MULTISITE=yes - SERVER_NAME=app1.example.com app2.example.com app3.example.com - USE_REVERSE_PROXY=yes - REVERSE_PROXY_URL=/ - app1.example.com_REVERSE_PROXY_HOST=http://myapp1 - app2.example.com_REVERSE_PROXY_HOST=http://myapp2 - app3.example.com_REVERSE_PROXY_HOST=http://myapp3 networks : - bw-net myapp1 : image : nginxdemos/hello:plain-text networks : - bw-net myapp2 : image : nginxdemos/hello:plain-text networks : - bw-net myapp3 : image : nginxdemos/hello:plain-text networks : - bw-net volumes : bw-data : networks : bw-net : name : bw-net We will assume that you already have the Docker autoconf integration stack running on your machine and connected to a network called bw-services. You can instantiate your containers and pass the settings as labels : App #1 App #2 App #3 docker run -d \\ --name myapp1 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app1.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp1 \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp1 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp1 labels : - \"bunkerweb.SERVER_NAME=app1.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp1\" networks : bw-services : external : name : bw-services docker run -d \\ --name myapp2 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app2.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp2 \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp2 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp2 labels : - \"bunkerweb.SERVER_NAME=app2.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp2\" networks : bw-services : external : name : bw-services docker run -d \\ --name myapp3 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app3.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp3 \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp3 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp3 labels : - \"bunkerweb.SERVER_NAME=app3.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp3\" networks : bw-services : external : name : bw-services We will assume that you already have the Swarm integration stack running on your cluster. You can instantiate your services and pass the settings as labels : App #1 App #2 App #3 docker service \\ create \\ --name myapp1 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app1.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp1 \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp1 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp1 deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=app1.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp1\" networks : bw-services : external : name : bw-services docker service \\ create \\ --name myapp2 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app2.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp2 \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp2 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp2 deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=app2.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp2\" networks : bw-services : external : name : bw-services docker service \\ create \\ --name myapp3 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app3.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp3 \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp3 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp3 deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=app3.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp3\" networks : bw-services : external : name : bw-services We will assume that you already have the Kubernetes integration stack running on your cluster. Let's also assume that you have some typical Deployments with Services to access the web applications from within the cluster : App #1 App #2 App #3 apiVersion : apps/v1 kind : Deployment metadata : name : app1 labels : app : app1 spec : replicas : 1 selector : matchLabels : app : app1 template : metadata : labels : app : app1 spec : containers : - name : app1 image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app1 spec : selector : app : app1 ports : - protocol : TCP port : 80 targetPort : 80 apiVersion : apps/v1 kind : Deployment metadata : name : app2 labels : app : app2 spec : replicas : 1 selector : matchLabels : app : app2 template : metadata : labels : app : app2 spec : containers : - name : app2 image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app2 spec : selector : app : app2 ports : - protocol : TCP port : 80 targetPort : 80 apiVersion : apps/v1 kind : Deployment metadata : name : app3 labels : app : app3 spec : replicas : 1 selector : matchLabels : app : app3 template : metadata : labels : app : app3 spec : containers : - name : app1 image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app3 spec : selector : app : app3 ports : - protocol : TCP port : 80 targetPort : 80 Here is the corresponding Ingress definition to serve and protect the web applications : apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : ingress annotations : bunkerweb.io/AUTOCONF : \"yes\" spec : rules : - host : app1.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app1 port : number : 80 - host : app2.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app2 port : number : 80 - host : app3.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app3 port : number : 80 We will assume that you already have the Linux integration stack running on your machine. Let's assume that you have some web applications running on the same machine as BunkerWeb : App #1 App #2 App #3 The following command will run a basic HTTP server on the port 8001 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 8001 The following command will run a basic HTTP server on the port 8002 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 8002 The following command will run a basic HTTP server on the port 8003 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 8003 Configuration of BunkerWeb is done by editing the /opt/bunkerweb/variables.env file : SERVER_NAME=app1.example.com app2.example.com app3.example.com HTTP_PORT=80 HTTPS_PORT=443 DNS_RESOLVERS=8.8.8.8 8.8.4.4 USE_REVERSE_PROXY=yes REVERSE_PROXY_URL=/ app1.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:8001 app2.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:8002 app3.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:8003 Let's check the status of BunkerWeb : systemctl status bunkerweb If it's already running we can just reload it : systemctl reload bunkerweb Otherwise, we will need to start it : systemctl start bunkerweb Behind load balancer or reverse proxy When BunkerWeb is itself behind a load balancer or a reverse proxy, you will need to configure it so it can get the real IP address of the clients. If you don't do it, the security features will block the IP address of the load balancer or reverse proxy instead of the client one. BunkerWeb actually supports two methods to retrieve the real IP address of the client : Using the PROXY protocol Using a HTTP header like X-Forwarded-For The following settings can be used : USE_REAL_IP : enable/disable real IP retrieval USE_PROXY_PROTOCOL : enable/disable PROXY protocol support REAL_IP_FROM : list of trusted IP/network address allowed to send us the \"real IP\" REAL_IP_HEADER : the HTTP header containing the real IP or special value \"proxy_protocol\" when using PROXY protocol You will find more settings about real IP in the settings section of the documentation. HTTP header We will assume the following regarding the load balancers or reverse proxies (you will need to update the settings depending on your configuration) : They use the X-Forwarded-For header to set the real IP They have IPs in the 1.2.3.0/24 and 100.64.0.0/16 networks The following settings need to be set : USE_REAL_IP=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=X-Forwarded-For Docker Docker autoconf Swarm Kubernetes Linux When starting the BunkerWeb container, you will need to add the settings : docker run \\ ... -e USE_REAL_IP = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = X-Forwarded-For \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=X-Forwarded-For ... Before running the Docker autoconf integration stack, you will need to add the settings for the BunkerWeb container : docker run \\ ... -e USE_REAL_IP = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = X-Forwarded-For \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=X-Forwarded-For ... Before running the Swarm integration stack, you will need to add the settings for the BunkerWeb service : docker service create \\ ... -e USE_REAL_IP = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = X-Forwarded-For \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent (using docker stack deploy ) : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=X-Forwarded-For ... You will need to add the settings to the environment variables of the bunkerweb containers (doing it using the ingress is not supported because you will get into trouble when using things like Let's Encrypt) : apiVersion : apps/v1 kind : DaemonSet metadata : name : bunkerweb spec : selector : matchLabels : app : bunkerweb template : spec : containers : - name : bunkerweb image : bunkerity/bunkerweb:1.4.1 ... env : - name : USE_REAL_IP value : \"yes\" - name : REAL_IP_HEADER value : \"X-Forwarded-For\" - name : REAL_IP_FROM value : \"1.2.3.0/24 100.64.0.0/16\" ... You will need to add the settings to the /opt/bunkerweb/variables.env file : ... USE_REAL_IP=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=X-Forwarded-For ... Don't forget to reload the bunkerweb service once it's done. Proxy protocol We will assume the following regarding the load balancers or reverse proxies (you will need to update the settings depending on your configuration) : They use the PROXY protocol v1 or v2 to set the real IP They have IPs in the 1.2.3.0/24 and 100.64.0.0/16 networks The following settings need to be set : USE_REAL_IP=yes USE_PROXY_PROTOCOL=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=proxy_protocol Docker Docker autoconf Swarm Kubernetes Linux When starting the BunkerWeb container, you will need to add the settings : docker run \\ ... -e USE_REAL_IP = yes \\ -e USE_PROXY_PROTOCOL = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = proxy_protocol \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - USE_PROXY_PROTOCOL=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=proxy_protocol ... Before running the Docker autoconf integration stack, you will need to add the settings for the BunkerWeb container : docker run \\ ... -e USE_REAL_IP = yes \\ -e USE_PROXY_PROTOCOL = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = proxy_protocol \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - USE_PROXY_PROTOCOL=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=proxy_protocol ... Before running the Swarm integration stack, you will need to add the settings for the BunkerWeb service : docker service create \\ ... -e USE_REAL_IP = yes \\ -e USE_PROXY_PROTOCOL = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = proxy_protocol \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent (using docker stack deploy ) : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - USE_PROXY_PROTOCOL=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=proxy_protocol ... You will need to add the settings to the environment variables of the bunkerweb containers (doing it using the ingress is not supported because you will get into trouble when using things like Let's Encrypt) : apiVersion : apps/v1 kind : DaemonSet metadata : name : bunkerweb spec : selector : matchLabels : app : bunkerweb template : spec : containers : - name : bunkerweb image : bunkerity/bunkerweb:1.4.1 ... env : - name : USE_REAL_IP value : \"yes\" - name : USE_PROXY_PROTOCOL value : \"yes\" - name : REAL_IP_HEADER value : \"proxy_protocol\" - name : REAL_IP_FROM value : \"1.2.3.0/24 100.64.0.0/16\" ... You will need to add the settings to the /opt/bunkerweb/variables.env file : ... USE_REAL_IP=yes USE_PROXY_PROTOCOL=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=proxy_protocol ... Don't forget to reload the bunkerweb service once it's done. Custom configurations Because BunkerWeb is based on the NGINX web server, you can add custom NGINX configurations in different NGINX contexts. You can also apply custom configurations for the ModSecurity WAF which is a core component of BunkerWeb (more info here ). Here is the list of custom configurations types : http : http level of NGINX server-http : server level of NGINX default-server-http : server level of NGINX (only apply to the \"default server\" when the name supplied by the client doesn't match any server name in SERVER_NAME ) modsec-crs : before the OWASP Core Rule Set is loaded modsec : after the OWASP Core Rule Set is loaded (also used if CRS is not loaded) Custom configurations can be applied globally or only for a specific server when applicable and if multisite mode is enabled. The howto depends on the integration used but under the hood, applying custom configurations is done by adding files ending with the .conf suffix in their name to specific folders. To apply a custom configuration for a specific server, the file is written to a subfolder which is named as the primary server name. Some integrations offer a more convenient way of applying configurations for example using Configs with Swarm or ConfigMap with Kubernetes. Docker Docker autoconf Swarm Kubernetes Linux When using the Docker integration , custom configurations must be written to the volume mounted on /data. The first thing to do is to create the folders : mkdir -p ./bw-data/configs/server-http You can now write your configurations : echo \"location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } }\" > ./bw-data/configs/server-http/hello-world.conf Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When starting the BunkerWeb container, you will need to mount the folder on /data : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data ... When using the Docker autoconf integration , custom configurations must be written to the volume mounted on /data. The first thing to do is to create the folders : mkdir -p ./bw-data/configs/server-http You can now write your configurations : echo \"location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } }\" > ./bw-data/configs/server-http/hello-world.conf Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When starting the BunkerWeb container, you will need to mount the folder on /data : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data ... When using the Swarm integration , custom configurations are managed using Docker Configs . To keep it simple, you don't even need to attach the Config to a service : the autoconf service is listening for Config events and will update the custom configurations when needed. When creating a Config you will need to add special labels : bunkerweb.CONFIG_TYPE : must be set to a valid custom configuration type (http, server-http, default-server-http, modsec or modsec-crs) bunkerweb.CONFIG_SITE : set to a server name to apply configuration to that specific server (optional, will be applied globally if unset) Here is the example : echo \"location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } }\" | docker config create -l bunkerweb.CONFIG_TYPE = server-http my-config - There is no update mechanism : the alternative is to remove an existing config using docker config rm and then recreate it. When using the Kubernetes integration , custom configurations are managed using ConfigMap . To keep it simple, you don't even need to use the ConfigMap with a Pod (e.g. as environment variable or volume) : the autoconf Pod is listening for ConfigMap events and will update the custom configurations when needed. When creating a ConfigMap you will need to add special labels : bunkerweb.io/CONFIG_TYPE : must be set to a valid custom configuration type (http, server-http, default-server-http, modsec or modsec-crs) bunkerweb.io/CONFIG_SITE : set to a server name to apply configuration to that specific server (optional, will be applied globally if unset) Here is the example : apiVersion : v1 kind : ConfigMap metadata : name : cfg-bunkerweb-all-server-http annotations : bunkerweb.io/CONFIG_TYPE : \"server-http\" data : myconf : | location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } } When using the Linux integration , custom configurations must be written to the /opt/bunkerweb/configs folder. Here is an example for server-http/hello-world.conf : location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } } Because BunkerWeb runs as an unprivileged user (nginx:nginx), you will need to edit the permissions : chown -R root:nginx /opt/bunkerweb/configs && \\ chmod -R 770 /opt/bunkerweb/configs Don't forget to reload the bunkerweb service once it's done.","title":"Quickstart guide"},{"location":"quickstart-guide/#quickstart-guide","text":"Prerequisites We assume that you're already familiar with the core concepts and you have followed the integrations instructions for your environment. Going further To demonstrate the use of BunkerWeb, we will deploy a dummy \"Hello World\" web application as an example. See the examples folder of the repository to get real-world examples.","title":"Quickstart guide"},{"location":"quickstart-guide/#protect-http-applications","text":"Protecting existing web applications already accessible with the HTTP(S) protocol is the main goal of BunkerWeb : it will act as a classical reverse proxy with extra security features. The following settings can be used : USE_REVERSE_PROXY : enable/disable reverse proxy mode REVERSE_PROXY_URL : the public path prefix REVERSE_PROXY_HOST : (internal) address of the proxied web application You will find more settings about reverse proxy in the settings section of the documentation.","title":"Protect HTTP applications"},{"location":"quickstart-guide/#single-application","text":"Docker Docker autoconf Swarm Kubernetes Linux When using Docker integration, the easiest way of protecting an existing application is to create a network so BunkerWeb can send requests using the container name. Create the Docker network if it's not already created : docker network create bw-net Then instantiate your app : docker run -d \\ --name myapp \\ --network bw-net \\ nginxdemos/hello:plain-text Create the BunkerWeb volume if it's not already created : docker volume create bw-data You can now run BunkerWeb and configure it for your app : docker run -d \\ --name mybunker \\ --network bw-net \\ -p 80 :8080 \\ -p 443 :8443 \\ -v bw-data:/data \\ -e SERVER_NAME = www.example.com \\ -e USE_REVERSE_PROXY = yes \\ -e REVERSE_PROXY_URL = / \\ -e REVERSE_PROXY_HOST = http://myapp \\ bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - 80:8080 - 443:8443 volumes : - bw-data:/data environment : - USE_REVERSE_PROXY=yes - REVERSE_PROXY_URL=/ - REVERSE_PROXY_HOST=http://myapp networks : - bw-net myapp : image : nginxdemos/hello:plain-text networks : - bw-net volumes : bw-data : networks : bw-net : name : bw-net We will assume that you already have the Docker autoconf integration stack running on your machine and connected to a network called bw-services. You can instantiate your container and pass the settings as labels : docker run -d \\ --name myapp \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = www.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp labels : - \"bunkerweb.SERVER_NAME=www.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp\" networks : bw-services : external : name : bw-services We will assume that you already have the Swarm integration stack running on your cluster. You can instantiate your service and pass the settings as labels : docker service \\ create \\ --name myapp \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = www.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=www.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp\" networks : bw-services : external : name : bw-services We will assume that you already have the Kubernetes integration stack running on your cluster. Let's assume that you have a typical Deployment with a Service to access the web application from within the cluster : apiVersion : apps/v1 kind : Deployment metadata : name : app labels : app : app spec : replicas : 1 selector : matchLabels : app : app template : metadata : labels : app : app spec : containers : - name : app image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app spec : selector : app : app ports : - protocol : TCP port : 80 targetPort : 80 Here is the corresponding Ingress definition to serve and protect the web application : apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : ingress annotations : bunkerweb.io/AUTOCONF : \"yes\" spec : rules : - host : www.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app port : number : 80 We will assume that you already have the Linux integration stack running on your machine. The following command will run a basic HTTP server on the port 8000 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 Configuration of BunkerWeb is done by editing the /opt/bunkerweb/variables.env file : SERVER_NAME=www.example.com HTTP_PORT=80 HTTPS_PORT=443 DNS_RESOLVERS=8.8.8.8 8.8.4.4 USE_REVERSE_PROXY=yes REVERSE_PROXY_URL=/ REVERSE_PROXY_HOST=http://127.0.0.1:8000 Let's check the status of BunkerWeb : systemctl status bunkerweb If it's already running we can just reload it : systemctl reload bunkerweb Otherwise, we will need to start it : systemctl start bunkerweb","title":"Single application"},{"location":"quickstart-guide/#multiple-applications","text":"Testing To perform quick tests when multisite mode is enabled (and if you don't have the proper DNS entries set up for the domains) you can use curl with the HTTP Host header of your choice : shell curl -H \"Host: app1.example.com\" http://ip-or-fqdn-of-server Docker Docker autoconf Swarm Kubernetes Linux When using Docker integration, the easiest way of protecting multiple existing applications is to create a network so BunkerWeb can send requests using the container names. Create the Docker network if it's not already created : docker network create bw-net Then instantiate your apps : App #1 App #2 App #3 docker run -d \\ --name myapp1 \\ --network bw-net \\ nginxdemos/hello:plain-text docker run -d \\ --name myapp2 \\ --network bw-net \\ nginxdemos/hello:plain-text docker run -d \\ --name myapp3 \\ --network bw-net \\ nginxdemos/hello:plain-text Create the BunkerWeb volume if it's not already created : docker volume create bw-data You can now run BunkerWeb and configure it for your apps : docker run -d \\ --name mybunker \\ --network bw-net \\ -p 80 :8080 \\ -p 443 :8443 \\ -v bw-data:/data \\ -e MULTISITE = yes -e \"SERVER_NAME=app1.example.com app2.example.com app3.example.com\" \\ -e USE_REVERSE_PROXY = yes \\ -e REVERSE_PROXY_URL = / \\ -e app1.example.com_REVERSE_PROXY_HOST = http://myapp1 \\ -e app2.example.com_REVERSE_PROXY_HOST = http://myapp2 \\ -e app3.example.com_REVERSE_PROXY_HOST = http://myapp3 \\ bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 ports : - 80:8080 - 443:8443 volumes : - bw-data:/data environment : - MULTISITE=yes - SERVER_NAME=app1.example.com app2.example.com app3.example.com - USE_REVERSE_PROXY=yes - REVERSE_PROXY_URL=/ - app1.example.com_REVERSE_PROXY_HOST=http://myapp1 - app2.example.com_REVERSE_PROXY_HOST=http://myapp2 - app3.example.com_REVERSE_PROXY_HOST=http://myapp3 networks : - bw-net myapp1 : image : nginxdemos/hello:plain-text networks : - bw-net myapp2 : image : nginxdemos/hello:plain-text networks : - bw-net myapp3 : image : nginxdemos/hello:plain-text networks : - bw-net volumes : bw-data : networks : bw-net : name : bw-net We will assume that you already have the Docker autoconf integration stack running on your machine and connected to a network called bw-services. You can instantiate your containers and pass the settings as labels : App #1 App #2 App #3 docker run -d \\ --name myapp1 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app1.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp1 \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp1 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp1 labels : - \"bunkerweb.SERVER_NAME=app1.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp1\" networks : bw-services : external : name : bw-services docker run -d \\ --name myapp2 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app2.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp2 \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp2 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp2 labels : - \"bunkerweb.SERVER_NAME=app2.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp2\" networks : bw-services : external : name : bw-services docker run -d \\ --name myapp3 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app3.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.USE_REVERSE_URL = / \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp3 \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent : version : '3' services : myapp3 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp3 labels : - \"bunkerweb.SERVER_NAME=app3.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp3\" networks : bw-services : external : name : bw-services We will assume that you already have the Swarm integration stack running on your cluster. You can instantiate your services and pass the settings as labels : App #1 App #2 App #3 docker service \\ create \\ --name myapp1 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app1.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp1 \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp1 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp1 deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=app1.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp1\" networks : bw-services : external : name : bw-services docker service \\ create \\ --name myapp2 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app2.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp2 \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp2 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp2 deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=app2.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp2\" networks : bw-services : external : name : bw-services docker service \\ create \\ --name myapp3 \\ --network bw-services \\ -l bunkerweb.SERVER_NAME = app3.example.com \\ -l bunkerweb.USE_REVERSE_PROXY = yes \\ -l bunkerweb.REVERSE_PROXY_HOST = http://myapp3 \\ -l bunkerweb.REVERSE_PROXY_URL = / \\ nginxdemos/hello:plain-text Here is the docker-compose equivalent (using docker stack deploy ) : version : \"3\" services : myapp3 : image : nginxdemos/hello:plain-text networks : bw-services : aliases : - myapp3 deploy : placement : constraints : - \"node.role==worker\" labels : - \"bunkerweb.SERVER_NAME=app3.example.com\" - \"bunkerweb.USE_REVERSE_PROXY=yes\" - \"bunkerweb.REVERSE_PROXY_URL=/\" - \"bunkerweb.REVERSE_PROXY_HOST=http://myapp3\" networks : bw-services : external : name : bw-services We will assume that you already have the Kubernetes integration stack running on your cluster. Let's also assume that you have some typical Deployments with Services to access the web applications from within the cluster : App #1 App #2 App #3 apiVersion : apps/v1 kind : Deployment metadata : name : app1 labels : app : app1 spec : replicas : 1 selector : matchLabels : app : app1 template : metadata : labels : app : app1 spec : containers : - name : app1 image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app1 spec : selector : app : app1 ports : - protocol : TCP port : 80 targetPort : 80 apiVersion : apps/v1 kind : Deployment metadata : name : app2 labels : app : app2 spec : replicas : 1 selector : matchLabels : app : app2 template : metadata : labels : app : app2 spec : containers : - name : app2 image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app2 spec : selector : app : app2 ports : - protocol : TCP port : 80 targetPort : 80 apiVersion : apps/v1 kind : Deployment metadata : name : app3 labels : app : app3 spec : replicas : 1 selector : matchLabels : app : app3 template : metadata : labels : app : app3 spec : containers : - name : app1 image : nginxdemos/hello:plain-text ports : - containerPort : 80 --- apiVersion : v1 kind : Service metadata : name : svc-app3 spec : selector : app : app3 ports : - protocol : TCP port : 80 targetPort : 80 Here is the corresponding Ingress definition to serve and protect the web applications : apiVersion : networking.k8s.io/v1 kind : Ingress metadata : name : ingress annotations : bunkerweb.io/AUTOCONF : \"yes\" spec : rules : - host : app1.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app1 port : number : 80 - host : app2.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app2 port : number : 80 - host : app3.example.com http : paths : - path : / pathType : Prefix backend : service : name : svc-app3 port : number : 80 We will assume that you already have the Linux integration stack running on your machine. Let's assume that you have some web applications running on the same machine as BunkerWeb : App #1 App #2 App #3 The following command will run a basic HTTP server on the port 8001 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 8001 The following command will run a basic HTTP server on the port 8002 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 8002 The following command will run a basic HTTP server on the port 8003 and deliver the files in the current directory : python3 -m http.server -b 127 .0.0.1 8003 Configuration of BunkerWeb is done by editing the /opt/bunkerweb/variables.env file : SERVER_NAME=app1.example.com app2.example.com app3.example.com HTTP_PORT=80 HTTPS_PORT=443 DNS_RESOLVERS=8.8.8.8 8.8.4.4 USE_REVERSE_PROXY=yes REVERSE_PROXY_URL=/ app1.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:8001 app2.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:8002 app3.example.com_REVERSE_PROXY_HOST=http://127.0.0.1:8003 Let's check the status of BunkerWeb : systemctl status bunkerweb If it's already running we can just reload it : systemctl reload bunkerweb Otherwise, we will need to start it : systemctl start bunkerweb","title":"Multiple applications"},{"location":"quickstart-guide/#behind-load-balancer-or-reverse-proxy","text":"When BunkerWeb is itself behind a load balancer or a reverse proxy, you will need to configure it so it can get the real IP address of the clients. If you don't do it, the security features will block the IP address of the load balancer or reverse proxy instead of the client one. BunkerWeb actually supports two methods to retrieve the real IP address of the client : Using the PROXY protocol Using a HTTP header like X-Forwarded-For The following settings can be used : USE_REAL_IP : enable/disable real IP retrieval USE_PROXY_PROTOCOL : enable/disable PROXY protocol support REAL_IP_FROM : list of trusted IP/network address allowed to send us the \"real IP\" REAL_IP_HEADER : the HTTP header containing the real IP or special value \"proxy_protocol\" when using PROXY protocol You will find more settings about real IP in the settings section of the documentation.","title":"Behind load balancer or reverse proxy"},{"location":"quickstart-guide/#http-header","text":"We will assume the following regarding the load balancers or reverse proxies (you will need to update the settings depending on your configuration) : They use the X-Forwarded-For header to set the real IP They have IPs in the 1.2.3.0/24 and 100.64.0.0/16 networks The following settings need to be set : USE_REAL_IP=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=X-Forwarded-For Docker Docker autoconf Swarm Kubernetes Linux When starting the BunkerWeb container, you will need to add the settings : docker run \\ ... -e USE_REAL_IP = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = X-Forwarded-For \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=X-Forwarded-For ... Before running the Docker autoconf integration stack, you will need to add the settings for the BunkerWeb container : docker run \\ ... -e USE_REAL_IP = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = X-Forwarded-For \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=X-Forwarded-For ... Before running the Swarm integration stack, you will need to add the settings for the BunkerWeb service : docker service create \\ ... -e USE_REAL_IP = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = X-Forwarded-For \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent (using docker stack deploy ) : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=X-Forwarded-For ... You will need to add the settings to the environment variables of the bunkerweb containers (doing it using the ingress is not supported because you will get into trouble when using things like Let's Encrypt) : apiVersion : apps/v1 kind : DaemonSet metadata : name : bunkerweb spec : selector : matchLabels : app : bunkerweb template : spec : containers : - name : bunkerweb image : bunkerity/bunkerweb:1.4.1 ... env : - name : USE_REAL_IP value : \"yes\" - name : REAL_IP_HEADER value : \"X-Forwarded-For\" - name : REAL_IP_FROM value : \"1.2.3.0/24 100.64.0.0/16\" ... You will need to add the settings to the /opt/bunkerweb/variables.env file : ... USE_REAL_IP=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=X-Forwarded-For ... Don't forget to reload the bunkerweb service once it's done.","title":"HTTP header"},{"location":"quickstart-guide/#proxy-protocol","text":"We will assume the following regarding the load balancers or reverse proxies (you will need to update the settings depending on your configuration) : They use the PROXY protocol v1 or v2 to set the real IP They have IPs in the 1.2.3.0/24 and 100.64.0.0/16 networks The following settings need to be set : USE_REAL_IP=yes USE_PROXY_PROTOCOL=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=proxy_protocol Docker Docker autoconf Swarm Kubernetes Linux When starting the BunkerWeb container, you will need to add the settings : docker run \\ ... -e USE_REAL_IP = yes \\ -e USE_PROXY_PROTOCOL = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = proxy_protocol \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - USE_PROXY_PROTOCOL=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=proxy_protocol ... Before running the Docker autoconf integration stack, you will need to add the settings for the BunkerWeb container : docker run \\ ... -e USE_REAL_IP = yes \\ -e USE_PROXY_PROTOCOL = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = proxy_protocol \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - USE_PROXY_PROTOCOL=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=proxy_protocol ... Before running the Swarm integration stack, you will need to add the settings for the BunkerWeb service : docker service create \\ ... -e USE_REAL_IP = yes \\ -e USE_PROXY_PROTOCOL = yes \\ -e \"REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16\" \\ -e REAL_IP_HEADER = proxy_protocol \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent (using docker stack deploy ) : mybunker : image : bunkerity/bunkerweb:1.4.1 ... environment : - USE_REAL_IP=yes - USE_PROXY_PROTOCOL=yes - REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 - REAL_IP_HEADER=proxy_protocol ... You will need to add the settings to the environment variables of the bunkerweb containers (doing it using the ingress is not supported because you will get into trouble when using things like Let's Encrypt) : apiVersion : apps/v1 kind : DaemonSet metadata : name : bunkerweb spec : selector : matchLabels : app : bunkerweb template : spec : containers : - name : bunkerweb image : bunkerity/bunkerweb:1.4.1 ... env : - name : USE_REAL_IP value : \"yes\" - name : USE_PROXY_PROTOCOL value : \"yes\" - name : REAL_IP_HEADER value : \"proxy_protocol\" - name : REAL_IP_FROM value : \"1.2.3.0/24 100.64.0.0/16\" ... You will need to add the settings to the /opt/bunkerweb/variables.env file : ... USE_REAL_IP=yes USE_PROXY_PROTOCOL=yes REAL_IP_FROM=1.2.3.0/24 100.64.0.0/16 REAL_IP_HEADER=proxy_protocol ... Don't forget to reload the bunkerweb service once it's done.","title":"Proxy protocol"},{"location":"quickstart-guide/#custom-configurations","text":"Because BunkerWeb is based on the NGINX web server, you can add custom NGINX configurations in different NGINX contexts. You can also apply custom configurations for the ModSecurity WAF which is a core component of BunkerWeb (more info here ). Here is the list of custom configurations types : http : http level of NGINX server-http : server level of NGINX default-server-http : server level of NGINX (only apply to the \"default server\" when the name supplied by the client doesn't match any server name in SERVER_NAME ) modsec-crs : before the OWASP Core Rule Set is loaded modsec : after the OWASP Core Rule Set is loaded (also used if CRS is not loaded) Custom configurations can be applied globally or only for a specific server when applicable and if multisite mode is enabled. The howto depends on the integration used but under the hood, applying custom configurations is done by adding files ending with the .conf suffix in their name to specific folders. To apply a custom configuration for a specific server, the file is written to a subfolder which is named as the primary server name. Some integrations offer a more convenient way of applying configurations for example using Configs with Swarm or ConfigMap with Kubernetes. Docker Docker autoconf Swarm Kubernetes Linux When using the Docker integration , custom configurations must be written to the volume mounted on /data. The first thing to do is to create the folders : mkdir -p ./bw-data/configs/server-http You can now write your configurations : echo \"location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } }\" > ./bw-data/configs/server-http/hello-world.conf Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When starting the BunkerWeb container, you will need to mount the folder on /data : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data ... When using the Docker autoconf integration , custom configurations must be written to the volume mounted on /data. The first thing to do is to create the folders : mkdir -p ./bw-data/configs/server-http You can now write your configurations : echo \"location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } }\" > ./bw-data/configs/server-http/hello-world.conf Because BunkerWeb runs as an unprivileged user with UID and GID 101, you will need to edit the permissions : chown -R root:101 bw-data && \\ chmod -R 770 bw-data When starting the BunkerWeb container, you will need to mount the folder on /data : docker run \\ ... -v \" ${ PWD } /bw-data:/data\" \\ ... bunkerity/bunkerweb:1.4.1 Here is the docker-compose equivalent : mybunker : image : bunkerity/bunkerweb:1.4.1 volumes : - ./bw-data:/data ... When using the Swarm integration , custom configurations are managed using Docker Configs . To keep it simple, you don't even need to attach the Config to a service : the autoconf service is listening for Config events and will update the custom configurations when needed. When creating a Config you will need to add special labels : bunkerweb.CONFIG_TYPE : must be set to a valid custom configuration type (http, server-http, default-server-http, modsec or modsec-crs) bunkerweb.CONFIG_SITE : set to a server name to apply configuration to that specific server (optional, will be applied globally if unset) Here is the example : echo \"location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } }\" | docker config create -l bunkerweb.CONFIG_TYPE = server-http my-config - There is no update mechanism : the alternative is to remove an existing config using docker config rm and then recreate it. When using the Kubernetes integration , custom configurations are managed using ConfigMap . To keep it simple, you don't even need to use the ConfigMap with a Pod (e.g. as environment variable or volume) : the autoconf Pod is listening for ConfigMap events and will update the custom configurations when needed. When creating a ConfigMap you will need to add special labels : bunkerweb.io/CONFIG_TYPE : must be set to a valid custom configuration type (http, server-http, default-server-http, modsec or modsec-crs) bunkerweb.io/CONFIG_SITE : set to a server name to apply configuration to that specific server (optional, will be applied globally if unset) Here is the example : apiVersion : v1 kind : ConfigMap metadata : name : cfg-bunkerweb-all-server-http annotations : bunkerweb.io/CONFIG_TYPE : \"server-http\" data : myconf : | location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } } When using the Linux integration , custom configurations must be written to the /opt/bunkerweb/configs folder. Here is an example for server-http/hello-world.conf : location /hello { default_type 'text/plain'; content_by_lua_block { ngx.say('world') } } Because BunkerWeb runs as an unprivileged user (nginx:nginx), you will need to edit the permissions : chown -R root:nginx /opt/bunkerweb/configs && \\ chmod -R 770 /opt/bunkerweb/configs Don't forget to reload the bunkerweb service once it's done.","title":"Custom configurations"},{"location":"security-tuning/","text":"Security tuning BunkerWeb offers many security features that you can configure with settings . Even if the default values of settings ensure a minimal \"security by default\", we strongly recommend you to tune them. By doing so you will be able to ensure a security level of your choice but also manage false positives. Other settings This section only focuses on security tuning, see the settings section of the documentation for other settings. HTTP protocol Default server In the HTTP protocol, the Host header is used to determine which server the client wants to send the request to. That header is facultative and may be missing from the request or can be set as an unknown value. This is a common case, a lot of bots are scanning the Internet and are trying to exploit services or simply doing some fingerprinting. You can disable any request containing undefined or unknown Host value by setting DISABLE_DEFAULT_SERVER to yes (default : no ). Please note that clients won't even receive a response, the TCP connection will be closed (using the special 444 status code of NGINX). Allowed methods You can control the allowed HTTP methods by listing them (separated with \"|\") in the ALLOWED_METHODS setting (default : GET|POST|HEAD ). Clients sending a method which is not listed will get a \"405 - Method Not Allowed\". Max sizes You can control the maximum body size with the MAX_CLIENT_SIZE setting (default : 10m ). See here for accepted values. You can use the special value 0 to allow a body of infinite size (not recommended). Serve files To disable serving files from the www folder, you can set SERVE_FILES to no (default : yes ). The value no is recommended if you use BunkerWeb as a reverse proxy. Headers Headers are very important when it comes to HTTP security. Not only some of them are too verbose but others can add some security, especially on the client-side. Remove headers You can automatically remove verbose headers in the HTTP responses by using the REMOVE_HEADERS setting (default : Server X-Powered-By X-AspNet-Version X-AspNetMvc-Version ). Cookies When it comes to cookies security, we can use the following flags : HttpOnly : disable any access to the cookie from Javascript using document.cookie SameSite : policy when requests come from third-party websites Secure : only send cookies on HTTPS request Cookie flags can be overridden with values of your choice by using the COOKIE_FLAGS setting (default : * HttpOnly SameSite=Lax ). See here for accepted values. The Secure flag can be automatically added if HTTPS is used by using the COOKIE_AUTO_SECURE_FLAG setting (default : yes ). The value no is not recommended unless you know what you're doing. Security headers Various security headers are available and most of them can be set using BunkerWeb settings. Here is the list of headers, the corresponding setting and default value : Header Setting Default Content-Security-Policy CONTENT_SECURITY_POLICY object-src 'none'; frame-src 'self'; child-src 'self'; form-action 'self'; frame-ancestors 'self'; Strict-Transport-Security STRICT_TRANSPORT_SECURITY max-age=31536000 Referrer-Policy REFERRER_POLICY strict-origin-when-cross-origin Permissions-Policy 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=() Feature-Policy 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'; X-Frame-Options X_FRAME_OPTIONS SAMEORIGIN X-Content-Type-Options X_CONTENT_TYPE_OPTIONS nosniff X-XSS-Protection X_XSS_PROTECTION 1; mode=block HTTPS Besides the HTTPS configuration, the following settings related to HTTPS can be set : Setting Default Description REDIRECT_HTTP_TO_HTTPS no When set to yes , will redirect every HTTP request to HTTPS even if BunkerWeb is not configured with HTTPS. AUTO_REDIRECT_HTTP_TO_HTTPS yes When set to yes , will redirect every HTTP request to HTTPS only if BunkerWeb is configured with HTTPS. HTTPS_PROTOCOLS TLSv1.2 TLSv1.3 List of supported SSL/TLS protocols when HTTPS is enabled. HTTP2 yes When set to yes , will enable HTTP2 protocol support when using HTTPS. LISTEN_HTTP yes When set to no , BunkerWeb will not listen for HTTP requests. Useful if you want HTTPS only for example. Let's Encrypt BunkerWeb comes with automatic Let's Encrypt certificate generation and renewal. This is the easiest way of getting HTTPS working out of the box for public-facing web applications. Please note that you will need to set up proper DNS A record(s) for each of your domains pointing to your public IP(s) where BunkerWeb is accessible. Here is the list of related settings : Setting Default Description AUTO_LETS_ENCRYPT no When set to yes , HTTPS will be enabled with automatic certificate generation and renewal from Let's Encrypt. EMAIL_LETS_ENCRYPT contact@{FIRST_SERVER} Email to use when generating certificates. Let's Encrypt will send notifications to that email like certificate expiration. USE_LETS_ENCRYPT_STAGING no When set to yes , the staging server of Let's Encrypt will be used instead of the production one. Useful when doing tests to avoid being \"blocked\" due to limits. Custom certificate If you want to use your own certificates, here is the list of related settings : Setting Default Description USE_CUSTOM_HTTPS no When set to yes , HTTPS will be enabled with custom certificates. CUSTOM_HTTPS_CERT Full path to the certificate. If you have one or more intermediate certificate(s) in your chain of trust, you will need to provide the bundle (more info here ). CUSTOM_HTTPS_KEY Full path to the private key. When USE_CUSTOM_HTTPS is set to yes , BunkerWeb will check every day if the custom certificate specified in CUSTOM_HTTPS_CERT is modified and will reload NGINX if that's the case. Self-signed If you want to quickly test HTTPS for staging/dev environment you can configure BunkerWeb to generate self-signed certificates, here is the list of related Setting Default Description GENERATE_SELF_SIGNED_SSL no When set to yes , HTTPS will be enabled with automatic self-signed certificate generation and renewal from Let's Encrypt. SELF_SIGNED_SSL_EXPIRY 365 Number of days for the certificate expiration ( -days value used with openssl ). SELF_SIGNED_SSL_SUBJ /CN=www.example.com/ Certificate subject to use ( -subj value used with openssl ). ModSecurity ModSecurity is integrated and enabled by default alongside the OWASP Core Rule Set within BunkerWeb. Here is the list of related settings : Setting Default Description USE_MODSECURITY yes When set to yes , ModSecurity will be enabled. USE_MODSECURITY_CRS yes When set to yes and USE_MODSECURITY is also set to yes , the OWASP Core Rule Set will be loaded. We strongly recommend keeping both ModSecurity and the OWASP Core Rule Set enabled. The only downsides are the false positives that may occur. But they can be fixed with some efforts and the CRS team maintains a list of exclusions for common applications (e.g., WordPress, Nextcloud, Drupal, Cpanel, ...). Tuning ModSecurity and the CRS can be done using custom configurations : modsec-crs : before the OWASP Core Rule Set is loaded modsec : after the OWASP Core Rule Set is loaded (also used if CRS is not loaded) For example, you can add a custom configuration with type modsec-crs to add CRS exclusions : SecAction \\ \"id:900130,\\ phase:1,\\ nolog,\\ pass,\\ t:none,\\ setvar:tx.crs_exclusions_wordpress=1\" You can also add a custom configuration with type modsec to update loaded CRS rules : SecRule REQUEST_FILENAME \"/wp-admin/admin-ajax.php\" \"id:1,ctl:ruleRemoveByTag=attack-xss,ctl:ruleRemoveByTag=attack-rce\" SecRule REQUEST_FILENAME \"/wp-admin/options.php\" \"id:2,ctl:ruleRemoveByTag=attack-xss\" SecRule REQUEST_FILENAME \"^/wp-json/yoast\" \"id:3,ctl:ruleRemoveById=930120\" Bad behavior When attackers search for and/or exploit vulnerabilities they might generate some \"suspicious\" HTTP status codes that a \"regular\" user won\u2019t generate within a period of time. If we detect that kind of behavior we can ban the offending IP address and force the attacker to come up with a new one. That kind of security measure is implemented and enabled by default in BunkerWeb and is called \"Bad behavior\". Here is the list of the related settings : Setting Default Description USE_BAD_BEHAVIOR yes When set to yes , the Bad behavior feature will be enabled. BAD_BEHAVIOR_STATUS_CODES 400 401 403 404 405 429 444 List of HTTP status codes considered as \"suspicious\". BAD_BEHAVIOR_BAN_TIME 86400 The duration time (in seconds) of a ban when a client reached the threshold. BAD_BEHAVIOR_THRESHOLD 10 Maximum number of \"suspicious\" HTTP status codes within the time period. BAD_BEHAVIOR_COUNT_TIME 60 Period of time where we count \"suspicious\" HTTP status codes. In other words, with the default values, if a client generates more than 10 status codes from the list 400 401 403 404 405 429 444 within 60 seconds his IP address will be banned for 86400 seconds. Antibot Attackers will certainly use automated tools to exploit/find some vulnerabilities in your web applications. One countermeasure is to challenge the users to detect if they look like a bot. If the challenge is solved, we consider the client as \"legitimate\" and he can access the web application. That kind of security is implemented but not enabled by default in BunkerWeb and is called \"Antibot\". Here is the list of supported challenges : Cookie : send a cookie to the client, we expect to get the cookie back on other requests Javascript : force a client to solve a computation challenge using Javascript Captcha : force the client to solve a classical captcha (no external dependencies) hCaptcha : force the client to solve a captcha from hCaptcha reCAPTCHA : force the client to get a minimum score with Google reCAPTCHA Here is the list of related settings : Setting Default Description USE_ANTIBOT no Accepted values to enable Antibot feature : cookie , javascript , captcha , hcaptcha and recaptcha . ANTIBOT_URI /challenge URI that clients will be redirected to in order to solve the challenge. Be sure that it isn't used in your web application. ANTIBOT_SESSION_SECRET random The secret used to encrypt cookies when using Antibot. The special value random will generate one for you. Be sure to set it when you use a clustered integration (32 chars). ANTIBOT_HCAPTCHA_SITEKEY and ANTIBOT_RECAPTCHA_SITEKEY The Sitekey value to use when USE_ANTIBOT is set to hcaptcha or recaptcha . ANTIBOT_HCAPTCHA_SECRET and ANTIBOT_RECAPTCHA_SECRET The Secret value to use when USE_ANTIBOT is set to hcaptcha or recaptcha . ANTIBOT_RECAPTCHA_SCORE 0.7 The minimum score that clients must have when USE_ANTIBOT is set to recaptcha . Blacklisting and whitelisting The blacklisting security feature is very easy to understand : if a specific criteria is met, the client will be banned. As for the whitelisting, it's the exact opposite : if a specific criteria is met, the client will be allowed and no additional security check will be done. You can configure blacklisting and whitelisting at the same time. If that's the case, note that whitelisting is executed before blacklisting : if a criteria is true for both, the client will be whitelisted. Blacklisting You can use the following settings to setup blacklisting : Setting Default Description USE_BLACKLIST yes When set to yes , will enable blacklisting based on various criteria. BLACKLIST_IP List of IPs and networks to blacklist. BLACKLIST_IP_URLS https://www.dan.me.uk/torlist/?exit List of URL containing IP and network to blacklist. The default list contains TOR exit nodes. BLACKLIST_RDNS .shodan.io .censys.io List of reverse DNS to blacklist. BLACKLIST_RDNS_URLS List of URLs containing reverse DNS to blacklist. BLACKLIST_ASN List of ASN to blacklist. BLACKLIST_ASN_URLS List of URLs containing ASN to blacklist. BLACKLIST_USER_AGENT List of User-Agents to blacklist. BLACKLIST_USER_AGENT_URLS https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list List of URLs containing User-Agent(s) to blacklist. BLACKLIST_URI List of requests URI to blacklist. BLACKLIST_URI_URLS List of URLs containing request URI to blacklist. Whitelisting You can use the following settings to setup whitelisting : Setting Default Description USE_WHITELIST yes When set to yes , will enable blacklisting based on various criteria. 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 List of IP and network to whitelist. The default list contains IP from DuckDuckGo crawler. WHITELIST_IP_URLS `` List of URLs containing IP and network to whitelist. 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 List of reverse DNS to whitelist. Default list contains various reverse DNS of search engines and social media crawlers. WHITELIST_RDNS_URLS List of URLs containing reverse DNS to whitelist. WHITELIST_ASN 32934 List of ASN to whitelist. The default list contains the ASN of Facebook. WHITELIST_ASN_URLS List of URL containing ASN to whitelist. WHITELIST_USER_AGENT List of User-Agent to whitelist. WHITELIST_USER_AGENT_URLS List of URLs containing User-Agent to whitelist. WHITELIST_URI List of requests URI to whitelist. WHITELIST_URI_URLS List of URLs containing request(s) URI to whitelist. BunkerNet BunkerNet is a crowdsourced database of malicious requests shared between all BunkerWeb instances over the world. If you enable BunkerNet, malicious requests will be sent to a remote server and will be analyzed by our systems. By doing so, we can extract malicious data from everyone's reports and give back the results to each BunkerWeb instances participating into BunkerNet. At the moment, that feature should be considered in \"beta\". We only extract malicious IP and we are very strict about how we do it to avoid any \"poisoning\". We strongly recommend activating it (which is the default) because the more instances participate, the more data we have to improve the algorithm. The setting used to enable or disable BunkerNet is USE_BUNKERNET (default : yes ). DNSBL DNSBL or \"DNS BlackList\" is an external list of malicious IPs that you query using the DNS protocol. Automatic querying of that kind of blacklist is supported by BunkerWeb. If a remote DNSBL server of your choice says that the IP address of the client is in the blacklist, it will be banned. Here is the list of settings related to DNSBL : Setting Default Description USE_DNSBL yes When set to yes , will enable DNSBL checking. DNSBL_LIST bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org List of DNSBL servers to ask. Limiting BunkerWeb supports applying a limit policy to : Number of connections per IP Number of requests per IP and URL within a time period Please note that it should not be considered as an effective solution against DoS or DDoS but rather an anti-bruteforce measure or rate limit policy for API. In both cases (connections or requests) if the limit is reached, the client will receive the HTTP status \"429 - Too Many Requests\". Connections The following settings are related to the Limiting connections feature : Setting Default Description USE_LIMIT_CONN yes When set to yes , will limit the maximum number of concurrent connections for a given IP. LIMIT_CONN_MAX_HTTP1 10 Maximum number of concurrent connections when using HTTP1 protocol. LIMIT_CONN_MAX_HTTP2 100 Maximum number of concurrent streams when using HTTP2 protocol. Requests The following settings are related to the Limiting requests feature : Setting Default Description USE_LIMIT_REQ yes When set to yes , will limit the number of requests for a given IP on each URL with a period of time. LIMIT_REQ_URL / The URL that will be limited. The special URL / will define a default limit for all URLs. LIMIT_REQ_RATE 2r/s The limit to apply to the corresponding URL. Syntax is Xr/Y where X is the number of request(s) and Y the period of time (s for second, m for minute, h for hour and d for day). Please note that you can add different rate for different URLs by adding a number to suffix to the settings for example : LIMIT_REQ_URL_1=/url1 , LIMIT_REQ_RATE_1=5r/d , LIMIT_REQ_URL_2=/url2 , LIMIT_REQ_RATE_2=1r/m , ... Another important thing to note is that LIMIT_REQ_URL accepts LUA patterns. Country The country security feature allows you to apply policy based on the country of the IP address of clients : Deny any access if the country is in a blacklist Only allow access if the country is in a whitelist (other security checks will still be executed) Here is the list of related settings : Setting Default Description BLACKLIST_COUNTRY List of 2 letters country code to blacklist. WHITELIST_COUNTRY List of 2 letters country code to whitelist. Using both country blacklist and whitelist at the same time makes no sense. If you do please note that only the whitelist will be executed. Authentication Auth basic You can quickly protect sensitive resources like the admin area for example by requiring HTTP basic authentication. Here is the list of related settings : Setting Default Description USE_AUTH_BASIC no When set to yes HTTP auth basic will be enabled. AUTH_BASIC_LOCATION sitewide Location (URL) of the sensitive resource. Use special value sitewide to enable everywhere. AUTH_BASIC_USER changeme The username required. AUTH_BASIC_PASSWORD changeme The password required. AUTH_BASIC_TEXT Restricted area Text to display in the auth prompt. Auth request You can deploy complex authentification (e.g. SSO), by using the auth request settings (see here for more information on the feature). Please note that you will find Authelia and Authentik examples in the repository . Auth request settings are related to reverse proxy rules. Setting Default Context Multiple Description 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 signin 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).","title":"Security tuning"},{"location":"security-tuning/#security-tuning","text":"BunkerWeb offers many security features that you can configure with settings . Even if the default values of settings ensure a minimal \"security by default\", we strongly recommend you to tune them. By doing so you will be able to ensure a security level of your choice but also manage false positives. Other settings This section only focuses on security tuning, see the settings section of the documentation for other settings.","title":"Security tuning"},{"location":"security-tuning/#http-protocol","text":"","title":"HTTP protocol"},{"location":"security-tuning/#default-server","text":"In the HTTP protocol, the Host header is used to determine which server the client wants to send the request to. That header is facultative and may be missing from the request or can be set as an unknown value. This is a common case, a lot of bots are scanning the Internet and are trying to exploit services or simply doing some fingerprinting. You can disable any request containing undefined or unknown Host value by setting DISABLE_DEFAULT_SERVER to yes (default : no ). Please note that clients won't even receive a response, the TCP connection will be closed (using the special 444 status code of NGINX).","title":"Default server"},{"location":"security-tuning/#allowed-methods","text":"You can control the allowed HTTP methods by listing them (separated with \"|\") in the ALLOWED_METHODS setting (default : GET|POST|HEAD ). Clients sending a method which is not listed will get a \"405 - Method Not Allowed\".","title":"Allowed methods"},{"location":"security-tuning/#max-sizes","text":"You can control the maximum body size with the MAX_CLIENT_SIZE setting (default : 10m ). See here for accepted values. You can use the special value 0 to allow a body of infinite size (not recommended).","title":"Max sizes"},{"location":"security-tuning/#serve-files","text":"To disable serving files from the www folder, you can set SERVE_FILES to no (default : yes ). The value no is recommended if you use BunkerWeb as a reverse proxy.","title":"Serve files"},{"location":"security-tuning/#headers","text":"Headers are very important when it comes to HTTP security. Not only some of them are too verbose but others can add some security, especially on the client-side.","title":"Headers"},{"location":"security-tuning/#remove-headers","text":"You can automatically remove verbose headers in the HTTP responses by using the REMOVE_HEADERS setting (default : Server X-Powered-By X-AspNet-Version X-AspNetMvc-Version ).","title":"Remove headers"},{"location":"security-tuning/#cookies","text":"When it comes to cookies security, we can use the following flags : HttpOnly : disable any access to the cookie from Javascript using document.cookie SameSite : policy when requests come from third-party websites Secure : only send cookies on HTTPS request Cookie flags can be overridden with values of your choice by using the COOKIE_FLAGS setting (default : * HttpOnly SameSite=Lax ). See here for accepted values. The Secure flag can be automatically added if HTTPS is used by using the COOKIE_AUTO_SECURE_FLAG setting (default : yes ). The value no is not recommended unless you know what you're doing.","title":"Cookies"},{"location":"security-tuning/#security-headers","text":"Various security headers are available and most of them can be set using BunkerWeb settings. Here is the list of headers, the corresponding setting and default value : Header Setting Default Content-Security-Policy CONTENT_SECURITY_POLICY object-src 'none'; frame-src 'self'; child-src 'self'; form-action 'self'; frame-ancestors 'self'; Strict-Transport-Security STRICT_TRANSPORT_SECURITY max-age=31536000 Referrer-Policy REFERRER_POLICY strict-origin-when-cross-origin Permissions-Policy 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=() Feature-Policy 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'; X-Frame-Options X_FRAME_OPTIONS SAMEORIGIN X-Content-Type-Options X_CONTENT_TYPE_OPTIONS nosniff X-XSS-Protection X_XSS_PROTECTION 1; mode=block","title":"Security headers"},{"location":"security-tuning/#https","text":"Besides the HTTPS configuration, the following settings related to HTTPS can be set : Setting Default Description REDIRECT_HTTP_TO_HTTPS no When set to yes , will redirect every HTTP request to HTTPS even if BunkerWeb is not configured with HTTPS. AUTO_REDIRECT_HTTP_TO_HTTPS yes When set to yes , will redirect every HTTP request to HTTPS only if BunkerWeb is configured with HTTPS. HTTPS_PROTOCOLS TLSv1.2 TLSv1.3 List of supported SSL/TLS protocols when HTTPS is enabled. HTTP2 yes When set to yes , will enable HTTP2 protocol support when using HTTPS. LISTEN_HTTP yes When set to no , BunkerWeb will not listen for HTTP requests. Useful if you want HTTPS only for example.","title":"HTTPS"},{"location":"security-tuning/#lets-encrypt","text":"BunkerWeb comes with automatic Let's Encrypt certificate generation and renewal. This is the easiest way of getting HTTPS working out of the box for public-facing web applications. Please note that you will need to set up proper DNS A record(s) for each of your domains pointing to your public IP(s) where BunkerWeb is accessible. Here is the list of related settings : Setting Default Description AUTO_LETS_ENCRYPT no When set to yes , HTTPS will be enabled with automatic certificate generation and renewal from Let's Encrypt. EMAIL_LETS_ENCRYPT contact@{FIRST_SERVER} Email to use when generating certificates. Let's Encrypt will send notifications to that email like certificate expiration. USE_LETS_ENCRYPT_STAGING no When set to yes , the staging server of Let's Encrypt will be used instead of the production one. Useful when doing tests to avoid being \"blocked\" due to limits.","title":"Let's Encrypt"},{"location":"security-tuning/#custom-certificate","text":"If you want to use your own certificates, here is the list of related settings : Setting Default Description USE_CUSTOM_HTTPS no When set to yes , HTTPS will be enabled with custom certificates. CUSTOM_HTTPS_CERT Full path to the certificate. If you have one or more intermediate certificate(s) in your chain of trust, you will need to provide the bundle (more info here ). CUSTOM_HTTPS_KEY Full path to the private key. When USE_CUSTOM_HTTPS is set to yes , BunkerWeb will check every day if the custom certificate specified in CUSTOM_HTTPS_CERT is modified and will reload NGINX if that's the case.","title":"Custom certificate"},{"location":"security-tuning/#self-signed","text":"If you want to quickly test HTTPS for staging/dev environment you can configure BunkerWeb to generate self-signed certificates, here is the list of related Setting Default Description GENERATE_SELF_SIGNED_SSL no When set to yes , HTTPS will be enabled with automatic self-signed certificate generation and renewal from Let's Encrypt. SELF_SIGNED_SSL_EXPIRY 365 Number of days for the certificate expiration ( -days value used with openssl ). SELF_SIGNED_SSL_SUBJ /CN=www.example.com/ Certificate subject to use ( -subj value used with openssl ).","title":"Self-signed"},{"location":"security-tuning/#modsecurity","text":"ModSecurity is integrated and enabled by default alongside the OWASP Core Rule Set within BunkerWeb. Here is the list of related settings : Setting Default Description USE_MODSECURITY yes When set to yes , ModSecurity will be enabled. USE_MODSECURITY_CRS yes When set to yes and USE_MODSECURITY is also set to yes , the OWASP Core Rule Set will be loaded. We strongly recommend keeping both ModSecurity and the OWASP Core Rule Set enabled. The only downsides are the false positives that may occur. But they can be fixed with some efforts and the CRS team maintains a list of exclusions for common applications (e.g., WordPress, Nextcloud, Drupal, Cpanel, ...). Tuning ModSecurity and the CRS can be done using custom configurations : modsec-crs : before the OWASP Core Rule Set is loaded modsec : after the OWASP Core Rule Set is loaded (also used if CRS is not loaded) For example, you can add a custom configuration with type modsec-crs to add CRS exclusions : SecAction \\ \"id:900130,\\ phase:1,\\ nolog,\\ pass,\\ t:none,\\ setvar:tx.crs_exclusions_wordpress=1\" You can also add a custom configuration with type modsec to update loaded CRS rules : SecRule REQUEST_FILENAME \"/wp-admin/admin-ajax.php\" \"id:1,ctl:ruleRemoveByTag=attack-xss,ctl:ruleRemoveByTag=attack-rce\" SecRule REQUEST_FILENAME \"/wp-admin/options.php\" \"id:2,ctl:ruleRemoveByTag=attack-xss\" SecRule REQUEST_FILENAME \"^/wp-json/yoast\" \"id:3,ctl:ruleRemoveById=930120\"","title":"ModSecurity"},{"location":"security-tuning/#bad-behavior","text":"When attackers search for and/or exploit vulnerabilities they might generate some \"suspicious\" HTTP status codes that a \"regular\" user won\u2019t generate within a period of time. If we detect that kind of behavior we can ban the offending IP address and force the attacker to come up with a new one. That kind of security measure is implemented and enabled by default in BunkerWeb and is called \"Bad behavior\". Here is the list of the related settings : Setting Default Description USE_BAD_BEHAVIOR yes When set to yes , the Bad behavior feature will be enabled. BAD_BEHAVIOR_STATUS_CODES 400 401 403 404 405 429 444 List of HTTP status codes considered as \"suspicious\". BAD_BEHAVIOR_BAN_TIME 86400 The duration time (in seconds) of a ban when a client reached the threshold. BAD_BEHAVIOR_THRESHOLD 10 Maximum number of \"suspicious\" HTTP status codes within the time period. BAD_BEHAVIOR_COUNT_TIME 60 Period of time where we count \"suspicious\" HTTP status codes. In other words, with the default values, if a client generates more than 10 status codes from the list 400 401 403 404 405 429 444 within 60 seconds his IP address will be banned for 86400 seconds.","title":"Bad behavior"},{"location":"security-tuning/#antibot","text":"Attackers will certainly use automated tools to exploit/find some vulnerabilities in your web applications. One countermeasure is to challenge the users to detect if they look like a bot. If the challenge is solved, we consider the client as \"legitimate\" and he can access the web application. That kind of security is implemented but not enabled by default in BunkerWeb and is called \"Antibot\". Here is the list of supported challenges : Cookie : send a cookie to the client, we expect to get the cookie back on other requests Javascript : force a client to solve a computation challenge using Javascript Captcha : force the client to solve a classical captcha (no external dependencies) hCaptcha : force the client to solve a captcha from hCaptcha reCAPTCHA : force the client to get a minimum score with Google reCAPTCHA Here is the list of related settings : Setting Default Description USE_ANTIBOT no Accepted values to enable Antibot feature : cookie , javascript , captcha , hcaptcha and recaptcha . ANTIBOT_URI /challenge URI that clients will be redirected to in order to solve the challenge. Be sure that it isn't used in your web application. ANTIBOT_SESSION_SECRET random The secret used to encrypt cookies when using Antibot. The special value random will generate one for you. Be sure to set it when you use a clustered integration (32 chars). ANTIBOT_HCAPTCHA_SITEKEY and ANTIBOT_RECAPTCHA_SITEKEY The Sitekey value to use when USE_ANTIBOT is set to hcaptcha or recaptcha . ANTIBOT_HCAPTCHA_SECRET and ANTIBOT_RECAPTCHA_SECRET The Secret value to use when USE_ANTIBOT is set to hcaptcha or recaptcha . ANTIBOT_RECAPTCHA_SCORE 0.7 The minimum score that clients must have when USE_ANTIBOT is set to recaptcha .","title":"Antibot"},{"location":"security-tuning/#blacklisting-and-whitelisting","text":"The blacklisting security feature is very easy to understand : if a specific criteria is met, the client will be banned. As for the whitelisting, it's the exact opposite : if a specific criteria is met, the client will be allowed and no additional security check will be done. You can configure blacklisting and whitelisting at the same time. If that's the case, note that whitelisting is executed before blacklisting : if a criteria is true for both, the client will be whitelisted.","title":"Blacklisting and whitelisting"},{"location":"security-tuning/#blacklisting","text":"You can use the following settings to setup blacklisting : Setting Default Description USE_BLACKLIST yes When set to yes , will enable blacklisting based on various criteria. BLACKLIST_IP List of IPs and networks to blacklist. BLACKLIST_IP_URLS https://www.dan.me.uk/torlist/?exit List of URL containing IP and network to blacklist. The default list contains TOR exit nodes. BLACKLIST_RDNS .shodan.io .censys.io List of reverse DNS to blacklist. BLACKLIST_RDNS_URLS List of URLs containing reverse DNS to blacklist. BLACKLIST_ASN List of ASN to blacklist. BLACKLIST_ASN_URLS List of URLs containing ASN to blacklist. BLACKLIST_USER_AGENT List of User-Agents to blacklist. BLACKLIST_USER_AGENT_URLS https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list List of URLs containing User-Agent(s) to blacklist. BLACKLIST_URI List of requests URI to blacklist. BLACKLIST_URI_URLS List of URLs containing request URI to blacklist.","title":"Blacklisting"},{"location":"security-tuning/#whitelisting","text":"You can use the following settings to setup whitelisting : Setting Default Description USE_WHITELIST yes When set to yes , will enable blacklisting based on various criteria. 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 List of IP and network to whitelist. The default list contains IP from DuckDuckGo crawler. WHITELIST_IP_URLS `` List of URLs containing IP and network to whitelist. 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 List of reverse DNS to whitelist. Default list contains various reverse DNS of search engines and social media crawlers. WHITELIST_RDNS_URLS List of URLs containing reverse DNS to whitelist. WHITELIST_ASN 32934 List of ASN to whitelist. The default list contains the ASN of Facebook. WHITELIST_ASN_URLS List of URL containing ASN to whitelist. WHITELIST_USER_AGENT List of User-Agent to whitelist. WHITELIST_USER_AGENT_URLS List of URLs containing User-Agent to whitelist. WHITELIST_URI List of requests URI to whitelist. WHITELIST_URI_URLS List of URLs containing request(s) URI to whitelist.","title":"Whitelisting"},{"location":"security-tuning/#bunkernet","text":"BunkerNet is a crowdsourced database of malicious requests shared between all BunkerWeb instances over the world. If you enable BunkerNet, malicious requests will be sent to a remote server and will be analyzed by our systems. By doing so, we can extract malicious data from everyone's reports and give back the results to each BunkerWeb instances participating into BunkerNet. At the moment, that feature should be considered in \"beta\". We only extract malicious IP and we are very strict about how we do it to avoid any \"poisoning\". We strongly recommend activating it (which is the default) because the more instances participate, the more data we have to improve the algorithm. The setting used to enable or disable BunkerNet is USE_BUNKERNET (default : yes ).","title":"BunkerNet"},{"location":"security-tuning/#dnsbl","text":"DNSBL or \"DNS BlackList\" is an external list of malicious IPs that you query using the DNS protocol. Automatic querying of that kind of blacklist is supported by BunkerWeb. If a remote DNSBL server of your choice says that the IP address of the client is in the blacklist, it will be banned. Here is the list of settings related to DNSBL : Setting Default Description USE_DNSBL yes When set to yes , will enable DNSBL checking. DNSBL_LIST bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org List of DNSBL servers to ask.","title":"DNSBL"},{"location":"security-tuning/#limiting","text":"BunkerWeb supports applying a limit policy to : Number of connections per IP Number of requests per IP and URL within a time period Please note that it should not be considered as an effective solution against DoS or DDoS but rather an anti-bruteforce measure or rate limit policy for API. In both cases (connections or requests) if the limit is reached, the client will receive the HTTP status \"429 - Too Many Requests\".","title":"Limiting"},{"location":"security-tuning/#connections","text":"The following settings are related to the Limiting connections feature : Setting Default Description USE_LIMIT_CONN yes When set to yes , will limit the maximum number of concurrent connections for a given IP. LIMIT_CONN_MAX_HTTP1 10 Maximum number of concurrent connections when using HTTP1 protocol. LIMIT_CONN_MAX_HTTP2 100 Maximum number of concurrent streams when using HTTP2 protocol.","title":"Connections"},{"location":"security-tuning/#requests","text":"The following settings are related to the Limiting requests feature : Setting Default Description USE_LIMIT_REQ yes When set to yes , will limit the number of requests for a given IP on each URL with a period of time. LIMIT_REQ_URL / The URL that will be limited. The special URL / will define a default limit for all URLs. LIMIT_REQ_RATE 2r/s The limit to apply to the corresponding URL. Syntax is Xr/Y where X is the number of request(s) and Y the period of time (s for second, m for minute, h for hour and d for day). Please note that you can add different rate for different URLs by adding a number to suffix to the settings for example : LIMIT_REQ_URL_1=/url1 , LIMIT_REQ_RATE_1=5r/d , LIMIT_REQ_URL_2=/url2 , LIMIT_REQ_RATE_2=1r/m , ... Another important thing to note is that LIMIT_REQ_URL accepts LUA patterns.","title":"Requests"},{"location":"security-tuning/#country","text":"The country security feature allows you to apply policy based on the country of the IP address of clients : Deny any access if the country is in a blacklist Only allow access if the country is in a whitelist (other security checks will still be executed) Here is the list of related settings : Setting Default Description BLACKLIST_COUNTRY List of 2 letters country code to blacklist. WHITELIST_COUNTRY List of 2 letters country code to whitelist. Using both country blacklist and whitelist at the same time makes no sense. If you do please note that only the whitelist will be executed.","title":"Country"},{"location":"security-tuning/#authentication","text":"","title":"Authentication"},{"location":"security-tuning/#auth-basic","text":"You can quickly protect sensitive resources like the admin area for example by requiring HTTP basic authentication. Here is the list of related settings : Setting Default Description USE_AUTH_BASIC no When set to yes HTTP auth basic will be enabled. AUTH_BASIC_LOCATION sitewide Location (URL) of the sensitive resource. Use special value sitewide to enable everywhere. AUTH_BASIC_USER changeme The username required. AUTH_BASIC_PASSWORD changeme The password required. AUTH_BASIC_TEXT Restricted area Text to display in the auth prompt.","title":"Auth basic"},{"location":"security-tuning/#auth-request","text":"You can deploy complex authentification (e.g. SSO), by using the auth request settings (see here for more information on the feature). Please note that you will find Authelia and Authentik examples in the repository . Auth request settings are related to reverse proxy rules. Setting Default Context Multiple Description 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 signin 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).","title":"Auth request"},{"location":"settings/","text":"Settings Settings generator tool To help you tuning BunkerWeb we have made an easy to use settings generator tool available at config.bunkerweb.io . This section contains the full list of settings supported by BunkerWeb. If you are not familiar with BunkerWeb, you should first read the concepts section of the documentation. Please follow the instructions for your own integration on how to apply the settings. As a general rule when multisite mode is enabled, if you want to apply settings with multisite context to a specific server you will need to add the primary (first) server name as a prefix like www.example.com_USE_ANTIBOT=captcha or myapp.example.com_USE_GZIP=yes for example. When settings are considered as \"multiple\", it means that you can have multiple groups of settings for the same feature by adding numbers as suffix like REVERSE_PROXY_URL_1=/subdir , REVERSE_PROXY_HOST_1=http://myhost1 , REVERSE_PROXY_URL_2=/anotherdir , REVERSE_PROXY_HOST_2=http://myhost2 , ... for example. Global settings Setting Default Context Multiple Description TEMP_NGINX no global no internal-use 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. 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 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. Auth basic Setting Default Context Multiple Description USE_AUTH_BASIC no multisite no Use HTTP basic auth AUTH_BASIC_LOCATION sitewide multisite no URL of the protected resource or sitewide value. AUTH_BASIC_USER changeme multisite no Username AUTH_BASIC_PASSWORD changeme multisite no Password AUTH_BASIC_TEXT Restricted area multisite no Text to display Bad behavior Setting Default Context Multiple Description USE_BAD_BEHAVIOR yes multisite no Activate Bad behavior feature. 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 where 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_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. Brotli Setting Default Context Multiple Description USE_BROTLI no multisite no Use brotli BROTLI_TYPES application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml multisite no List of MIME types that will be compressed with brotli. BROTLI_MIN_LENGTH 1000 multisite no Minimum length for brotli compression. BROTLI_COMP_LEVEL 6 multisite no The compression level of the brotli algorithm. BunkerNet Setting Default Context Multiple Description USE_BUNKERNET yes multisite no Activate BunkerNet feature. BUNKERNET_SERVER https://api.bunkerweb.io global no Address of the BunkerNet API. 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. Country Setting Default Context Multiple Description BLACKLIST_COUNTRY multisite no Deny access if the country of the client is in the list (2 letters code). WHITELIST_COUNTRY multisite no Deny access if the country of the client is not in the list (2 letters code). 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. DNSBL Setting Default Context Multiple Description USE_DNSBL yes multisite no Activate DNSBL feature. DNSBL_LIST bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org global no List of DNSBL servers. 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 ...). Gzip Setting Default Context Multiple Description USE_GZIP no multisite no Use gzip GZIP_TYPES application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml multisite no List of MIME types that will be compressed with gzip. GZIP_MIN_LENGTH 1000 multisite no Minimum length for gzip compression. GZIP_COMP_LEVEL 5 multisite no The compression level of the gzip algorithm. HTML injection Setting Default Context Multiple Description INJECT_BODY multisite no The HTML code to inject. 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. Let's Encrypt Setting Default Context Multiple Description AUTO_LETS_ENCRYPT no multisite no Activate automatic Let's Encrypt mode. EMAIL_LETS_ENCRYPT multisite no Email used for Let's Encrypt notification and in certificate. USE_LETS_ENCRYPT_STAGING no multisite no Use the staging environment for Let\u2019s Encrypt certificate generation. Useful when you are testing your deployments to avoid being rate limited in the production environment. Limit Setting Default Context Multiple Description USE_LIMIT_REQ yes multisite no Activate limit requests feature. LIMIT_REQ_URL / multisite yes URL where the limit request will be applied. LIMIT_REQ_RATE 2r/s multisite yes Rate to apply to the URL (s for second, m for minute, h for hour and d for day). USE_LIMIT_CONN yes multisite no Activate limit connections feature. LIMIT_CONN_MAX_HTTP1 10 multisite no Maximum number of connections per IP when using HTTP/1.X protocol. LIMIT_CONN_MAX_HTTP2 100 multisite no Maximum number of streams per IP when using HTTP/2 protocol. Miscellaneous Setting Default Context Multiple Description 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. 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 (/opt/bunkerweb/www/{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. 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 OPEN_FILE_CACHE max=1000 inactive=20s multisite no Open file cache directive OPEN_FILE_CACHE_ERRORS yes multisite no Enable open file cache for errors OPEN_FILE_CACHE_MIN_USES 2 multisite no Enable open file cache minimum uses OPEN_FILE_CACHE_VALID 30s multisite no Open file cache valid time ModSecurity Setting Default Context Multiple Description USE_MODSECURITY yes multisite no Enable ModSecurity WAF. USE_MODSECURITY_CRS yes multisite no Enable OWASP Core Rule Set. MODSECURITY_SEC_AUDIT_ENGINE RelevantOnly multisite no SecAuditEngine directive of ModSecurity. PHP Setting Default Context Multiple Description REMOTE_PHP multisite no Hostname of the remote PHP-FPM instance. REMOTE_PHP_PATH multisite no Root folder containing files in the remote PHP-FPM instance. LOCAL_PHP multisite no Path to the PHP-FPM socket file. LOCAL_PHP_PATH multisite no Root folder containing files in the local PHP-FPM instance. 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. Redirect Setting Default Context Multiple Description 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. 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 signin 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 minimimum 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 dependending 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. 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_SUBJ /CN=www.example.com/ multisite no Self-signed certificate subject. UI Setting Default Context Multiple Description USE_UI no multisite no Use UI Whitelist Setting Default Context Multiple Description USE_WHITELIST yes multisite no Activate whitelist feature. 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 .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. WHITELIST_USER_AGENT_URLS global no List of URLs, separated with spaces, containing good User-Agent to whitelist. WHITELIST_URI multisite no List of URI, separated with spaces, to whitelist. WHITELIST_URI_URLS global no List of URLs, separated with spaces, containing bad URI to whitelist.","title":"Settings"},{"location":"settings/#settings","text":"Settings generator tool To help you tuning BunkerWeb we have made an easy to use settings generator tool available at config.bunkerweb.io . This section contains the full list of settings supported by BunkerWeb. If you are not familiar with BunkerWeb, you should first read the concepts section of the documentation. Please follow the instructions for your own integration on how to apply the settings. As a general rule when multisite mode is enabled, if you want to apply settings with multisite context to a specific server you will need to add the primary (first) server name as a prefix like www.example.com_USE_ANTIBOT=captcha or myapp.example.com_USE_GZIP=yes for example. When settings are considered as \"multiple\", it means that you can have multiple groups of settings for the same feature by adding numbers as suffix like REVERSE_PROXY_URL_1=/subdir , REVERSE_PROXY_HOST_1=http://myhost1 , REVERSE_PROXY_URL_2=/anotherdir , REVERSE_PROXY_HOST_2=http://myhost2 , ... for example.","title":"Settings"},{"location":"settings/#global-settings","text":"Setting Default Context Multiple Description TEMP_NGINX no global no internal-use 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.","title":"Global settings"},{"location":"settings/#core-settings","text":"","title":"Core settings"},{"location":"settings/#antibot","text":"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 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.","title":"Antibot"},{"location":"settings/#auth-basic","text":"Setting Default Context Multiple Description USE_AUTH_BASIC no multisite no Use HTTP basic auth AUTH_BASIC_LOCATION sitewide multisite no URL of the protected resource or sitewide value. AUTH_BASIC_USER changeme multisite no Username AUTH_BASIC_PASSWORD changeme multisite no Password AUTH_BASIC_TEXT Restricted area multisite no Text to display","title":"Auth basic"},{"location":"settings/#bad-behavior","text":"Setting Default Context Multiple Description USE_BAD_BEHAVIOR yes multisite no Activate Bad behavior feature. 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 where we count 'bad' HTTP status codes.","title":"Bad behavior"},{"location":"settings/#blacklist","text":"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_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.","title":"Blacklist"},{"location":"settings/#brotli","text":"Setting Default Context Multiple Description USE_BROTLI no multisite no Use brotli BROTLI_TYPES application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml multisite no List of MIME types that will be compressed with brotli. BROTLI_MIN_LENGTH 1000 multisite no Minimum length for brotli compression. BROTLI_COMP_LEVEL 6 multisite no The compression level of the brotli algorithm.","title":"Brotli"},{"location":"settings/#bunkernet","text":"Setting Default Context Multiple Description USE_BUNKERNET yes multisite no Activate BunkerNet feature. BUNKERNET_SERVER https://api.bunkerweb.io global no Address of the BunkerNet API.","title":"BunkerNet"},{"location":"settings/#client-cache","text":"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.","title":"Client cache"},{"location":"settings/#country","text":"Setting Default Context Multiple Description BLACKLIST_COUNTRY multisite no Deny access if the country of the client is in the list (2 letters code). WHITELIST_COUNTRY multisite no Deny access if the country of the client is not in the list (2 letters code).","title":"Country"},{"location":"settings/#custom-https-certificate","text":"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.","title":"Custom HTTPS certificate"},{"location":"settings/#dnsbl","text":"Setting Default Context Multiple Description USE_DNSBL yes multisite no Activate DNSBL feature. DNSBL_LIST bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org global no List of DNSBL servers.","title":"DNSBL"},{"location":"settings/#errors","text":"Setting Default Context Multiple Description ERRORS multisite no List of HTTP error code and corresponding error pages (404=/my404.html 403=/errors/403.html ...).","title":"Errors"},{"location":"settings/#gzip","text":"Setting Default Context Multiple Description USE_GZIP no multisite no Use gzip GZIP_TYPES application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml multisite no List of MIME types that will be compressed with gzip. GZIP_MIN_LENGTH 1000 multisite no Minimum length for gzip compression. GZIP_COMP_LEVEL 5 multisite no The compression level of the gzip algorithm.","title":"Gzip"},{"location":"settings/#html-injection","text":"Setting Default Context Multiple Description INJECT_BODY multisite no The HTML code to inject.","title":"HTML injection"},{"location":"settings/#headers","text":"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.","title":"Headers"},{"location":"settings/#lets-encrypt","text":"Setting Default Context Multiple Description AUTO_LETS_ENCRYPT no multisite no Activate automatic Let's Encrypt mode. EMAIL_LETS_ENCRYPT multisite no Email used for Let's Encrypt notification and in certificate. USE_LETS_ENCRYPT_STAGING no multisite no Use the staging environment for Let\u2019s Encrypt certificate generation. Useful when you are testing your deployments to avoid being rate limited in the production environment.","title":"Let's Encrypt"},{"location":"settings/#limit","text":"Setting Default Context Multiple Description USE_LIMIT_REQ yes multisite no Activate limit requests feature. LIMIT_REQ_URL / multisite yes URL where the limit request will be applied. LIMIT_REQ_RATE 2r/s multisite yes Rate to apply to the URL (s for second, m for minute, h for hour and d for day). USE_LIMIT_CONN yes multisite no Activate limit connections feature. LIMIT_CONN_MAX_HTTP1 10 multisite no Maximum number of connections per IP when using HTTP/1.X protocol. LIMIT_CONN_MAX_HTTP2 100 multisite no Maximum number of streams per IP when using HTTP/2 protocol.","title":"Limit"},{"location":"settings/#miscellaneous","text":"Setting Default Context Multiple Description 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. 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 (/opt/bunkerweb/www/{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. 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 OPEN_FILE_CACHE max=1000 inactive=20s multisite no Open file cache directive OPEN_FILE_CACHE_ERRORS yes multisite no Enable open file cache for errors OPEN_FILE_CACHE_MIN_USES 2 multisite no Enable open file cache minimum uses OPEN_FILE_CACHE_VALID 30s multisite no Open file cache valid time","title":"Miscellaneous"},{"location":"settings/#modsecurity","text":"Setting Default Context Multiple Description USE_MODSECURITY yes multisite no Enable ModSecurity WAF. USE_MODSECURITY_CRS yes multisite no Enable OWASP Core Rule Set. MODSECURITY_SEC_AUDIT_ENGINE RelevantOnly multisite no SecAuditEngine directive of ModSecurity.","title":"ModSecurity"},{"location":"settings/#php","text":"Setting Default Context Multiple Description REMOTE_PHP multisite no Hostname of the remote PHP-FPM instance. REMOTE_PHP_PATH multisite no Root folder containing files in the remote PHP-FPM instance. LOCAL_PHP multisite no Path to the PHP-FPM socket file. LOCAL_PHP_PATH multisite no Root folder containing files in the local PHP-FPM instance.","title":"PHP"},{"location":"settings/#real-ip","text":"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.","title":"Real IP"},{"location":"settings/#redirect","text":"Setting Default Context Multiple Description 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.","title":"Redirect"},{"location":"settings/#reverse-proxy","text":"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 signin 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 minimimum 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 dependending 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.","title":"Reverse proxy"},{"location":"settings/#self-signed-certificate","text":"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_SUBJ /CN=www.example.com/ multisite no Self-signed certificate subject.","title":"Self-signed certificate"},{"location":"settings/#ui","text":"Setting Default Context Multiple Description USE_UI no multisite no Use UI","title":"UI"},{"location":"settings/#whitelist","text":"Setting Default Context Multiple Description USE_WHITELIST yes multisite no Activate whitelist feature. 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 .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. WHITELIST_USER_AGENT_URLS global no List of URLs, separated with spaces, containing good User-Agent to whitelist. WHITELIST_URI multisite no List of URI, separated with spaces, to whitelist. WHITELIST_URI_URLS global no List of URLs, separated with spaces, containing bad URI to whitelist.","title":"Whitelist"},{"location":"troubleshooting/","text":"Troubleshooting Logs When troubleshooting, the logs are your best friends. We try our best to provide user-friendly logs to help you understand what's happening. Please note that you can set LOG_LEVEL setting to info (default : notice ) to increase the verbosity of BunkerWeb. Here is how you can access the logs depending on your integration : Docker Docker autoconf Swarm Kubernetes Linux List containers To list the running containers you can use the following command : docker ps You can use the docker logs command (replace mybunker with the name of your container) : docker logs mybunker Here is the docker-compose equivalent (replace mybunker with the name of the services declared in the docker-compose.yml file) : docker-compose logs mybunker List containers To list the running containers you can use the following command : docker ps You can use the docker logs command (replace mybunker and myautoconf with the name of your containers) : docker logs mybunker docker logs myautoconf Here is the docker-compose equivalent (replace mybunker and myautoconf with the name of the services declared in the docker-compose.yml file) : docker-compose logs mybunker docker-compose logs myautoconf List services To list the services you can use the following command : docker service ls You can use the docker service logs command (replace mybunker and myautoconf my with the name of your services) : docker service logs mybunker docker service logs myautoconf List pods To list the pods you can use the following command : kubectl get pods You can use the kubectl logs command (replace mybunker and myautoconf my with the name of your pods) : kubectl logs mybunker kubectl logs myautoconf For errors related to BunkerWeb services (e.g. not starting), you can use journalctl : journalctl -u bunkerweb --no-pager Common logs are located inside the /var/log/nginx directory : cat /var/log/nginx/error.log cat /var/log/nginx/access.log Permissions Don't forget that BunkerWeb runs as an unprivileged user for obvious security reasons. Double-check the permissions of files and folders used by BunkerWeb especially if you use custom configurations (more info here ). You will need to set at least RW rights on files and RWX on folders. ModSecurity The default BunkerWeb configuration of ModSecurity is to load the Core Rule Set in anomaly scoring mode with a paranoia level (PL) of 1 : Each matched rule will increase an anomaly score (so many rules can match a single request) PL1 include rules with fewer chances of false positives (but less security than PL4) the default threshold for anomaly score is 5 for requests and 4 for responses Let's take the following logs as an example of ModSecurity detection using default configuration (formatted for better readability) : 2022/04/26 12:01:10 [warn] 85#85: *11 ModSecurity: Warning. Matched \"Operator `PmFromFile' with parameter `lfi-os-files.data' against variable `ARGS:id' (Value: `/etc/passwd' ) [file \"/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf\"] [line \"78\"] [id \"930120\"] [rev \"\"] [msg \"OS File Access Attempt\"] [data \"Matched Data: etc/passwd found within ARGS:id: /etc/passwd\"] [severity \"2\"] [ver \"OWASP_CRS/3.3.2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-lfi\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/255/153/126\"] [tag \"PCI/6.5.4\"] [hostname \"172.17.0.2\"] [uri \"/\"] [unique_id \"165097447014.179282\"] [ref \"o1,10v9,11t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase\"], client: 172.17.0.1, server: localhost, request: \"GET /?id=/etc/passwd HTTP/1.1\", host: \"localhost\" 2022/04/26 12:01:10 [warn] 85#85: *11 ModSecurity: Warning. Matched \"Operator `PmFromFile' with parameter `unix-shell.data' against variable `ARGS:id' (Value: `/etc/passwd' ) [file \"/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf\"] [line \"480\"] [id \"932160\"] [rev \"\"] [msg \"Remote Command Execution: Unix Shell Code Found\"] [data \"Matched Data: etc/passwd found within ARGS:id: /etc/passwd\"] [severity \"2\"] [ver \"OWASP_CRS/3.3.2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-shell\"] [tag \"platform-unix\"] [tag \"attack-rce\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/152/248/88\"] [tag \"PCI/6.5.2\"] [hostname \"172.17.0.2\"] [uri \"/\"] [unique_id \"165097447014.179282\"] [ref \"o1,10v9,11t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase\"], client: 172.17.0.1, server: localhost, request: \"GET /?id=/etc/passwd HTTP/1.1\", host: \"localhost\" 2022/04/26 12:01:10 [error] 85#85: *11 [client 172.17.0.1] ModSecurity: Access denied with code 403 (phase 2). Matched \"Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `10' ) [file \"/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"80\"] [id \"949110\"] [rev \"\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 10)\"] [data \"\"] [severity \"2\"] [ver \"OWASP_CRS/3.3.2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"172.17.0.2\"] [uri \"/\"] [unique_id \"165097447014.179282\"] [ref \"\"], client: 172.17.0.1, server: localhost, request: \"GET /?id=/etc/passwd HTTP/1.1\", host: \"localhost\" As we can see there are 3 different logs : Rule 930120 matched Rule 932160 matched Access denied (rule 949110 ) One important thing to understand is that rule 949110 is not a \"real\" one : it's the one that will deny the request because the anomaly threshold is reached (which is 10 in this example). You should never remove the 949110 rule ! If it's a false-positive you should then focus on both 930120 and 932160 rules. ModSecurity and/or CRS tuning is out of the scope of this documentation but don't forget that you can apply custom configurations before and after the CRS is loaded (more info here ). Bad Behavior A common false-positive case is that the client is banned because of the \"bad behavior\" feature which means that too many suspicious HTTP status codes were generated within a time period (more info here ). You should start by reviewing the settings and edit them according to your web application(s) like removing a suspicious HTTP code, decreasing the count time, increasing the threshold, ... IP unban You can manually unban an IP which can be useful when doing some tests but it needs the setting USE_API set to yes (which is not the default) so you can contact the internal API of BunkerWeb (replace 1.2.3.4 with the IP address to unban) : Docker Docker autoconf Swarm Kubernetes Linux You can use the docker exec command (replace mybunker with the name of your container) : docker exec mybunker bwcli unban 1 .2.3.4 Here is the docker-compose equivalent (replace mybunker with the name of the services declared in the docker-compose.yml file) : docker-compose exec mybunker bwcli unban 1 .2.3.4 You can use the docker exec command (replace mya with the name of your container) : docker exec mybunker bwcli unban 1 .2.3.4 Here is the docker-compose equivalent (replace mybunker with the name of the services declared in the docker-compose.yml file) : docker-compose exec mybunker bwcli unban 1 .2.3.4 You can use the docker exec command (replace myautoconf with the name of your service) : docker exec $( docker ps -q -f name = myautoconf ) bwcli unban 1 .2.3.4 You can use the kubectl exec command (replace myautoconf with the name of your pod) : kubectl exec myautoconf bwcli unban 1 .2.3.4 You can use the bwcli command : bwcli unban 1 .2.3.4 Whitelisting If you have bots that need to access your website, the recommended way to avoid any false positive is to whitelist it using the whitelisting feature . We don't recommend using the WHITELIST_URI* or WHITELIST_USER_AGENT* settings unless they are set to secret and unpredictable values. Common use cases are : Healthcheck / status bot Callback like IPN or webhook Social media crawler","title":"Troubleshooting"},{"location":"troubleshooting/#troubleshooting","text":"","title":"Troubleshooting"},{"location":"troubleshooting/#logs","text":"When troubleshooting, the logs are your best friends. We try our best to provide user-friendly logs to help you understand what's happening. Please note that you can set LOG_LEVEL setting to info (default : notice ) to increase the verbosity of BunkerWeb. Here is how you can access the logs depending on your integration : Docker Docker autoconf Swarm Kubernetes Linux List containers To list the running containers you can use the following command : docker ps You can use the docker logs command (replace mybunker with the name of your container) : docker logs mybunker Here is the docker-compose equivalent (replace mybunker with the name of the services declared in the docker-compose.yml file) : docker-compose logs mybunker List containers To list the running containers you can use the following command : docker ps You can use the docker logs command (replace mybunker and myautoconf with the name of your containers) : docker logs mybunker docker logs myautoconf Here is the docker-compose equivalent (replace mybunker and myautoconf with the name of the services declared in the docker-compose.yml file) : docker-compose logs mybunker docker-compose logs myautoconf List services To list the services you can use the following command : docker service ls You can use the docker service logs command (replace mybunker and myautoconf my with the name of your services) : docker service logs mybunker docker service logs myautoconf List pods To list the pods you can use the following command : kubectl get pods You can use the kubectl logs command (replace mybunker and myautoconf my with the name of your pods) : kubectl logs mybunker kubectl logs myautoconf For errors related to BunkerWeb services (e.g. not starting), you can use journalctl : journalctl -u bunkerweb --no-pager Common logs are located inside the /var/log/nginx directory : cat /var/log/nginx/error.log cat /var/log/nginx/access.log","title":"Logs"},{"location":"troubleshooting/#permissions","text":"Don't forget that BunkerWeb runs as an unprivileged user for obvious security reasons. Double-check the permissions of files and folders used by BunkerWeb especially if you use custom configurations (more info here ). You will need to set at least RW rights on files and RWX on folders.","title":"Permissions"},{"location":"troubleshooting/#modsecurity","text":"The default BunkerWeb configuration of ModSecurity is to load the Core Rule Set in anomaly scoring mode with a paranoia level (PL) of 1 : Each matched rule will increase an anomaly score (so many rules can match a single request) PL1 include rules with fewer chances of false positives (but less security than PL4) the default threshold for anomaly score is 5 for requests and 4 for responses Let's take the following logs as an example of ModSecurity detection using default configuration (formatted for better readability) : 2022/04/26 12:01:10 [warn] 85#85: *11 ModSecurity: Warning. Matched \"Operator `PmFromFile' with parameter `lfi-os-files.data' against variable `ARGS:id' (Value: `/etc/passwd' ) [file \"/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf\"] [line \"78\"] [id \"930120\"] [rev \"\"] [msg \"OS File Access Attempt\"] [data \"Matched Data: etc/passwd found within ARGS:id: /etc/passwd\"] [severity \"2\"] [ver \"OWASP_CRS/3.3.2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-lfi\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/255/153/126\"] [tag \"PCI/6.5.4\"] [hostname \"172.17.0.2\"] [uri \"/\"] [unique_id \"165097447014.179282\"] [ref \"o1,10v9,11t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase\"], client: 172.17.0.1, server: localhost, request: \"GET /?id=/etc/passwd HTTP/1.1\", host: \"localhost\" 2022/04/26 12:01:10 [warn] 85#85: *11 ModSecurity: Warning. Matched \"Operator `PmFromFile' with parameter `unix-shell.data' against variable `ARGS:id' (Value: `/etc/passwd' ) [file \"/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf\"] [line \"480\"] [id \"932160\"] [rev \"\"] [msg \"Remote Command Execution: Unix Shell Code Found\"] [data \"Matched Data: etc/passwd found within ARGS:id: /etc/passwd\"] [severity \"2\"] [ver \"OWASP_CRS/3.3.2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-shell\"] [tag \"platform-unix\"] [tag \"attack-rce\"] [tag \"paranoia-level/1\"] [tag \"OWASP_CRS\"] [tag \"capec/1000/152/248/88\"] [tag \"PCI/6.5.2\"] [hostname \"172.17.0.2\"] [uri \"/\"] [unique_id \"165097447014.179282\"] [ref \"o1,10v9,11t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase\"], client: 172.17.0.1, server: localhost, request: \"GET /?id=/etc/passwd HTTP/1.1\", host: \"localhost\" 2022/04/26 12:01:10 [error] 85#85: *11 [client 172.17.0.1] ModSecurity: Access denied with code 403 (phase 2). Matched \"Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `10' ) [file \"/opt/bunkerweb/core/modsecurity/files/coreruleset/rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"80\"] [id \"949110\"] [rev \"\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 10)\"] [data \"\"] [severity \"2\"] [ver \"OWASP_CRS/3.3.2\"] [maturity \"0\"] [accuracy \"0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"172.17.0.2\"] [uri \"/\"] [unique_id \"165097447014.179282\"] [ref \"\"], client: 172.17.0.1, server: localhost, request: \"GET /?id=/etc/passwd HTTP/1.1\", host: \"localhost\" As we can see there are 3 different logs : Rule 930120 matched Rule 932160 matched Access denied (rule 949110 ) One important thing to understand is that rule 949110 is not a \"real\" one : it's the one that will deny the request because the anomaly threshold is reached (which is 10 in this example). You should never remove the 949110 rule ! If it's a false-positive you should then focus on both 930120 and 932160 rules. ModSecurity and/or CRS tuning is out of the scope of this documentation but don't forget that you can apply custom configurations before and after the CRS is loaded (more info here ).","title":"ModSecurity"},{"location":"troubleshooting/#bad-behavior","text":"A common false-positive case is that the client is banned because of the \"bad behavior\" feature which means that too many suspicious HTTP status codes were generated within a time period (more info here ). You should start by reviewing the settings and edit them according to your web application(s) like removing a suspicious HTTP code, decreasing the count time, increasing the threshold, ...","title":"Bad Behavior"},{"location":"troubleshooting/#ip-unban","text":"You can manually unban an IP which can be useful when doing some tests but it needs the setting USE_API set to yes (which is not the default) so you can contact the internal API of BunkerWeb (replace 1.2.3.4 with the IP address to unban) : Docker Docker autoconf Swarm Kubernetes Linux You can use the docker exec command (replace mybunker with the name of your container) : docker exec mybunker bwcli unban 1 .2.3.4 Here is the docker-compose equivalent (replace mybunker with the name of the services declared in the docker-compose.yml file) : docker-compose exec mybunker bwcli unban 1 .2.3.4 You can use the docker exec command (replace mya with the name of your container) : docker exec mybunker bwcli unban 1 .2.3.4 Here is the docker-compose equivalent (replace mybunker with the name of the services declared in the docker-compose.yml file) : docker-compose exec mybunker bwcli unban 1 .2.3.4 You can use the docker exec command (replace myautoconf with the name of your service) : docker exec $( docker ps -q -f name = myautoconf ) bwcli unban 1 .2.3.4 You can use the kubectl exec command (replace myautoconf with the name of your pod) : kubectl exec myautoconf bwcli unban 1 .2.3.4 You can use the bwcli command : bwcli unban 1 .2.3.4","title":"IP unban"},{"location":"troubleshooting/#whitelisting","text":"If you have bots that need to access your website, the recommended way to avoid any false positive is to whitelist it using the whitelisting feature . We don't recommend using the WHITELIST_URI* or WHITELIST_USER_AGENT* settings unless they are set to secret and unpredictable values. Common use cases are : Healthcheck / status bot Callback like IPN or webhook Social media crawler","title":"Whitelisting"},{"location":"web-ui/","text":"Web UI Supported integrations At the moment, the web UI is only supported with the Docker and Linux integrations. Please note that we plan to support more integrations as the project evolves. Overview Web UI demo The \"Web UI\" is a web application that helps you manage your BunkerWeb instance using a user-friendly interface instead of the command-line one. Features Start, stop, restart and reload your BunkerWeb instance Add, edit and delete settings for your web applications Add, edit and delete custom configurations for NGINX and ModSecurity Install and uninstall external plugins View the logs and search pattern Installation Because the web UI is a web application, the recommended installation procedure is to use BunkerWeb in front of it as a reverse proxy. Security considerations The security of the web UI is really important. If someone manages to gain access to the application, not only he will be able to edit your configurations but he could execute some code in the context of BunkerWeb (with a custom configuration containing LUA code for example). We highly recommend you to follow minimal security best practices like : Choose a strong password for the login Put the web UI under a \"hard to guess\" URI Do not open the web UI on the Internet without any further restrictions Apply settings listed in the security tuning section of the documentation Multisite mode The installation of the web UI implies enabling the multisite mode . 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. Docker Linux When using the Docker integration , 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 . Let's start by creating the networks (replace 10.20.30.0/24 with an unused network of your choice) : docker network create --subnet 10 .20.30.0/24 bw-ui && \\ 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 : docker volume create bw-data && \\ docker volume create bw-confs 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 : docker run -d \\ --name mybunker --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_HEADER=X-Script-Name /changeme\" \\ -e bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS = no \\ -l bunkerweb.UI \\ bunkerity/bunkerweb:1.4.1 && \\ docker network connect bw-ui mybunker 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 the /changeme URL with a custom one of your choice the bunkerweb.UI 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 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 : docker network create bw-docker Once the network is created, you can now create the docker socket proxy container : docker run -d \\ --name mydocker \\ --network bw-docker \\ --privileged \\ -v /var/run/docker.sock:/var/run/docker.sock:ro \\ tecnativa/docker-socket-proxy We can finally create the web UI container : docker run -d \\ --name myui \\ --network bw-ui \\ -v bw-data:/data \\ -v bw-confs:/etc/nginx \\ -e DOCKER_HOST = tcp://mydocker:2375 \\ -e ADMIN_USERNAME = admin \\ -e ADMIN_PASSWORD = changeme \\ -e ABSOLUTE_URI = http ( s ) ://bwadm.example.com/changeme/ bunkerity/bunkerweb-ui:1.4.1 && \\ docker network connect bw-docker myui Important things to note : 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 : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 networks : - bw-services - bw-ui ports : - 80:8080 volumes : - bw-data:/data - bw-confs:/etc/nginx environment : - SERVER_NAME=bwadm.example.com - MULTISITE=yes - API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24 - 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_HEADERS=X-Script-Name /changeme - bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS=no labels : - \"bunkerweb.UI\" myui : image : bunkerity/bunkerweb-ui:1.4.1 depends_on : - mydocker networks : - bw-ui - bw-docker volumes : - bw-data:/data - bw-confs:/etc/nginx environment : - DOCKER_HOST=tcp://mydocker:2375 - ADMIN_USERNAME=admin - ADMIN_PASSWORD=changeme - ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/ mydocker : image : tecnativa/docker-socket-proxy networks : - bw-docker volumes : - /var/run/docker.sock:/var/run/docker.sock:ro networks : bw-services : bw-ui : ipam : driver : default config : - subnet : 10.20.30.0/24 bw-docker : volumes : bw-data : bw-confs : The installation of the web UI using the Linux integration is pretty straightforward because it is installed with BunkerWeb. The first thing to do is to edit the BunkerWeb configuration located at /opt/bunkerweb/variables.env to add settings related to the web UI : HTTP_PORT=80 HTTPS_PORT=443 DNS_RESOLVERS=8.8.8.8 8.8.4.4 ... SERVER_NAME=bwadm.example.com MULTISITE=yes USE_API=yes API_WHITELIST_IP=127.0.0.0/8 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_HEADER=X-Script-Name /changeme bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS=no ... 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 Once the configuration file is edited, you will need to reload BunkerWeb : systemctl reload bunkerweb You can edit the /opt/bunkerweb/ui.env file containing the settings of the web UI : ADMIN_USERNAME=admin ADMIN_PASSWORD=changeme ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/ Important things to note : http(s)://bwadmin.example.com/changeme/ is the full base URL of the web UI (must match the sub(domain) and /changeme URL used in /opt/bunkerweb/variables.env ) replace the username admin and password changeme with strong ones Restart the BunkerWeb UI service and you are now ready to access it : systemctl restart bunkerweb-ui","title":"Web UI"},{"location":"web-ui/#web-ui","text":"Supported integrations At the moment, the web UI is only supported with the Docker and Linux integrations. Please note that we plan to support more integrations as the project evolves.","title":"Web UI"},{"location":"web-ui/#overview","text":"Web UI demo The \"Web UI\" is a web application that helps you manage your BunkerWeb instance using a user-friendly interface instead of the command-line one.","title":"Overview"},{"location":"web-ui/#features","text":"Start, stop, restart and reload your BunkerWeb instance Add, edit and delete settings for your web applications Add, edit and delete custom configurations for NGINX and ModSecurity Install and uninstall external plugins View the logs and search pattern","title":"Features"},{"location":"web-ui/#installation","text":"Because the web UI is a web application, the recommended installation procedure is to use BunkerWeb in front of it as a reverse proxy. Security considerations The security of the web UI is really important. If someone manages to gain access to the application, not only he will be able to edit your configurations but he could execute some code in the context of BunkerWeb (with a custom configuration containing LUA code for example). We highly recommend you to follow minimal security best practices like : Choose a strong password for the login Put the web UI under a \"hard to guess\" URI Do not open the web UI on the Internet without any further restrictions Apply settings listed in the security tuning section of the documentation Multisite mode The installation of the web UI implies enabling the multisite mode . 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. Docker Linux When using the Docker integration , 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 . Let's start by creating the networks (replace 10.20.30.0/24 with an unused network of your choice) : docker network create --subnet 10 .20.30.0/24 bw-ui && \\ 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 : docker volume create bw-data && \\ docker volume create bw-confs 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 : docker run -d \\ --name mybunker --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_HEADER=X-Script-Name /changeme\" \\ -e bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS = no \\ -l bunkerweb.UI \\ bunkerity/bunkerweb:1.4.1 && \\ docker network connect bw-ui mybunker 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 the /changeme URL with a custom one of your choice the bunkerweb.UI 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 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 : docker network create bw-docker Once the network is created, you can now create the docker socket proxy container : docker run -d \\ --name mydocker \\ --network bw-docker \\ --privileged \\ -v /var/run/docker.sock:/var/run/docker.sock:ro \\ tecnativa/docker-socket-proxy We can finally create the web UI container : docker run -d \\ --name myui \\ --network bw-ui \\ -v bw-data:/data \\ -v bw-confs:/etc/nginx \\ -e DOCKER_HOST = tcp://mydocker:2375 \\ -e ADMIN_USERNAME = admin \\ -e ADMIN_PASSWORD = changeme \\ -e ABSOLUTE_URI = http ( s ) ://bwadm.example.com/changeme/ bunkerity/bunkerweb-ui:1.4.1 && \\ docker network connect bw-docker myui Important things to note : 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 : version : '3' services : mybunker : image : bunkerity/bunkerweb:1.4.1 networks : - bw-services - bw-ui ports : - 80:8080 volumes : - bw-data:/data - bw-confs:/etc/nginx environment : - SERVER_NAME=bwadm.example.com - MULTISITE=yes - API_WHITELIST_IP=127.0.0.0/8 10.20.30.0/24 - 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_HEADERS=X-Script-Name /changeme - bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS=no labels : - \"bunkerweb.UI\" myui : image : bunkerity/bunkerweb-ui:1.4.1 depends_on : - mydocker networks : - bw-ui - bw-docker volumes : - bw-data:/data - bw-confs:/etc/nginx environment : - DOCKER_HOST=tcp://mydocker:2375 - ADMIN_USERNAME=admin - ADMIN_PASSWORD=changeme - ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/ mydocker : image : tecnativa/docker-socket-proxy networks : - bw-docker volumes : - /var/run/docker.sock:/var/run/docker.sock:ro networks : bw-services : bw-ui : ipam : driver : default config : - subnet : 10.20.30.0/24 bw-docker : volumes : bw-data : bw-confs : The installation of the web UI using the Linux integration is pretty straightforward because it is installed with BunkerWeb. The first thing to do is to edit the BunkerWeb configuration located at /opt/bunkerweb/variables.env to add settings related to the web UI : HTTP_PORT=80 HTTPS_PORT=443 DNS_RESOLVERS=8.8.8.8 8.8.4.4 ... SERVER_NAME=bwadm.example.com MULTISITE=yes USE_API=yes API_WHITELIST_IP=127.0.0.0/8 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_HEADER=X-Script-Name /changeme bwadm.example.com_REVERSE_PROXY_INTERCEPT_ERRORS=no ... 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 Once the configuration file is edited, you will need to reload BunkerWeb : systemctl reload bunkerweb You can edit the /opt/bunkerweb/ui.env file containing the settings of the web UI : ADMIN_USERNAME=admin ADMIN_PASSWORD=changeme ABSOLUTE_URI=http(s)://bwadm.example.com/changeme/ Important things to note : http(s)://bwadmin.example.com/changeme/ is the full base URL of the web UI (must match the sub(domain) and /changeme URL used in /opt/bunkerweb/variables.env ) replace the username admin and password changeme with strong ones Restart the BunkerWeb UI service and you are now ready to access it : systemctl restart bunkerweb-ui","title":"Installation"}]} |