diff --git a/README.md b/README.md index 8509ceb..a72b3b4 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,16 @@
-
+
+
+
@@ -18,13 +20,13 @@
nginx Docker image secure by default.
-Avoid the hassle of following security best practices each time you need a web server or reverse proxy. Bunkerized-nginx provides generic security configs, settings and tools so you don't need to do it yourself.
+Avoid the hassle of following security best practices "by hand" each time you need a web server or reverse proxy. Bunkerized-nginx provides generic security configs, settings and tools so you don't need to do it yourself.
Non-exhaustive list of 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 with fail2ban
+- Automatic ban of strange behaviors
- Antibot challenge through cookie, javascript, captcha or recaptcha v3
- Block TOR, proxies, bad user-agents, countries, ...
- Block known bad IP with DNSBL and CrowdSec
@@ -55,44 +57,8 @@ You can find a live demo at https://demo-nginx.bunkerity.com, feel free to do so
* [Automatic configuration](#automatic-configuration)
* [Swarm mode](#swarm-mode)
* [Web UI](#web-ui)
- * [Antibot challenge](#antibot-challenge)
- * [Hardening](#hardening)
-- [Tutorials and examples](#tutorials-and-examples)
-- [Include custom configurations](#include-custom-configurations)
-- [Cache data](#cache-data)
-- [List of environment variables](#list-of-environment-variables)
- * [nginx](#nginx)
- + [Misc](#misc)
- + [Information leak](#information-leak)
- + [Custom error pages](#custom-error-pages)
- + [HTTP basic authentication](#http-basic-authentication)
- + [Reverse proxy](#reverse-proxy)
- + [Compression](#compression)
- + [Cache](#cache)
- * [HTTPS](#https)
- + [Let's Encrypt](#lets-encrypt)
- + [HTTP](#http)
- + [Custom certificate](#custom-certificate)
- + [Self-signed certificate](#self-signed-certificate)
- + [Misc](#misc-1)
- * [ModSecurity](#modsecurity)
- * [Security headers](#security-headers)
- * [Blocking](#blocking)
- + [Antibot](#antibot)
- + [External blacklists](#external-blacklists)
- + [DNSBL](#dnsbl)
- + [CrowdSec](#crowdsec)
- + [Custom whitelisting](#custom-whitelisting)
- + [Custom blacklisting](#custom-blacklisting)
- + [Requests limiting](#requests-limiting)
- + [Connections limiting](#connections-limiting)
- + [Countries](#countries)
- * [PHP](#php)
- * [Fail2ban](#fail2ban)
- * [ClamAV](#clamav)
- * [Logrotate](#logrotate)
- * [Cron jobs](#cron-jobs)
- * [Misc](#misc-2)
+- [Security tuning](#security-tuning)
+- [Going further](#going-further)
# Quickstart guide
@@ -103,18 +69,24 @@ You can find a live demo at https://demo-nginx.bunkerity.com, feel free to do so
docker run -p 80:8080 -v /path/to/web/files:/www:ro bunkerity/bunkerized-nginx
```
-Web files are stored in the /www directory, the container will serve files from there. Please note that *bunkerized-nginx* doesn't run as root but with an unprivileged user with UID/GID 101 therefore you should set the rights of */path/to/web/files* accordingly.
+Web files are stored in the /www directory, the container will serve files from there. Please note that *bunkerized-nginx* doesn't run as root but as an unprivileged user with UID/GID 101 therefore you should set the rights of */path/to/web/files* accordingly.
## In combination with PHP
```shell
docker network create mynet
+```
+
+```shell
docker run --network mynet \
-p 80:8080 \
-v /path/to/web/files:/www:ro \
-e REMOTE_PHP=myphp \
-e REMOTE_PHP_PATH=/app \
bunkerity/bunkerized-nginx
+```
+
+```shell
docker run --network mynet \
--name myphp \
-v /path/to/web/files:/app \
@@ -136,7 +108,7 @@ docker run -p 80:8080 \
bunkerity/bunkerized-nginx
```
-Certificates are stored in the /etc/letsencrypt directory, you should save it on your local drive. Please note that *bunkerized-nginx* doesn't run as root but with an unprivileged user with UID/GID 101 therefore you should set the rights of */where/to/save/certificates* accordingly.
+Certificates are stored in the /etc/letsencrypt directory, you should save it on your local drive. Please note that *bunkerized-nginx* doesn't run as root but as an unprivileged user with UID/GID 101 therefore you should set the rights of */where/to/save/certificates* accordingly.
If you don't want your webserver to listen on HTTP add the environment variable `LISTEN_HTTP` with a *no* value (e.g. HTTPS only). But Let's Encrypt needs the port 80 to be opened so redirecting the port is mandatory.
@@ -178,7 +150,7 @@ docker run -p 80:8080 \
The `PROXY_REAL_IP` environment variable, when set to *yes*, activates the [ngx_http_realip_module](https://nginx.org/en/docs/http/ngx_http_realip_module.html) to get the real client IP from the reverse proxy.
-See [this section](#reverse-proxy) if you need to tweak some values (trusted ip/network, header, ...).
+See [this section](https://bunkerized-nginx.readthedocs.io/en/latest/environment_variables.html#reverse-proxy) if you need to tweak some values (trusted ip/network, header, ...).
## Multisite
@@ -226,8 +198,8 @@ The */where/are/web/files* directory should have a structure like this :
```shell
/where/are/web/files
├── app1.domain.com
-│ └── index.php
-│ └── ...
+│ └── index.php
+│ └── ...
└── app2.domain.com
└── index.php
└── ...
@@ -258,7 +230,7 @@ docker run -p 80:8080 \
-e MULTISITE=yes \
-e AUTO_LETS_ENCRYPT=yes \
-e REDIRECT_HTTP_TO_HTTPS=yes \
- -l bunkerized-nginx.AUTOCONF \
+ -l bunkerized.nginx.AUTOCONF \
bunkerity/bunkerized-nginx
```
@@ -436,1068 +408,12 @@ docker run --network mynet \
After that, the web UI should be accessible from https://admin.domain.com/webui/.
-## Antibot challenge
+# Security tuning
-```shell
-docker run -p 80:8080 -v /path/to/web/files:/www -e USE_ANTIBOT=captcha bunkerity/bunkerized-nginx
-```
+bunkerized-nginx comes with a set of predefined security settings that you can (and you should) tune to meet your own use case. We recommend you to read the [security tuning](https://bunkerized-nginx.readthedocs.io/en/latest/security_tuning.html) section of the documentation.
-When `USE_ANTIBOT` is set to *captcha*, every users visiting your website must complete a captcha before accessing the pages. Others challenges are also available : *cookie*, *javascript* or *recaptcha* (more info [here](#antibot)).
+# Going further
-## Hardening
-
-### Drop capabilities
-By default, *bunkerized-nginx* runs as non-root user inside the container and should not use any of the default [capabilities](https://docs.docker.com/engine/security/#linux-kernel-capabilities) allowed by Docker. You can safely remove all capabilities to harden the container :
-
-```shell
-docker run ... --drop-cap=all ... bunkerity/bunkerized-nginx
-```
-
-### User namespace remap
-Another hardening trick is [user namespace remapping](https://docs.docker.com/engine/security/userns-remap/) : it allows you to map the UID/GID of users inside a container to another UID/GID on the host. For example, you can map the user nginx with UID/GID 101 inside the container to a non-existent user with UID/GID 100101 on the host.
-
-Let's assume you have the /etc/subuid and /etc/subgid files like this :
-```
-user:100000:65536
-```
-It means that everything done inside the container will be remapped to UID/GID 100101 (100000 + 101) on the host.
-
-Please note that you must set the rights on the volumes (e.g. : /etc/letsencrypt, /www, ...) according to the remapped UID/GID :
-```shell
-$ chown root:100101 /path/to/letsencrypt
-$ chmod 770 /path/to/letsencrypt
-$ docker run ... -v /path/to/letsencrypt:/etc/letsencrypt ... bunkerity/bunkerized-nginx
-```
-
-# Tutorials and examples
-
-You will find some docker-compose examples in the [examples directory](https://github.com/bunkerity/bunkerized-nginx/tree/master/examples) and tutorials on our [blog](https://www.bunkerity.com/blog).
-
-# Include custom configurations
-Custom configurations files (ending with .conf suffix) can be added in some directory inside the container :
- - /http-confs : http context
- - /server-confs : server context
- - /pre-server-confs : before server context (add map or upstream config for example)
-
-You just need to use a volume like this :
-```shell
-docker run ... -v /path/to/http/confs:/http-confs:ro ... -v /path/to/server/confs:/server-confs:ro ... bunkerity/bunkerized-nginx
-```
-
-When `MULTISITE` is set to *yes*, .conf files inside the /server-confs directory are loaded by all the server blocks. You can also set custom configuration for a specific server block by adding files in a subdirectory named as the host defined in the `SERVER_NAME` environment variable. Here is an example :
-
-```shell
-docker run ... -v /path/to/server/confs:/server-confs:ro ... -e MULTISITE=yes -e "SERVER_NAME=app1.domain.com app2.domain.com" ... bunkerity/bunkerized-nginx
-```
-
-The */path/to/server/confs* directory should have a structure like this :
-```
-/path/to/server/confs
-├── app1.domain.com
-│ └── custom.conf
-│ └── ...
-└── app2.domain.com
- └── custom.conf
- └── ...
-```
-
-# Cache data
-
-You can store cached data (blacklists, geoip DB, ...) to avoid downloading them again after a container deletion by mounting a volume on the /cache directory :
-
-```shell
-docker run ... -v /path/to/cache:/cache ... bunkerity/bunkerized-nginx
-```
-
-# List of environment variables
-
-## nginx
-
-### Misc
-
-`MULTISITE`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*
-When set to *no*, only one server block will be generated. Otherwise one server per host defined in the `SERVER_NAME` environment variable will be generated.
-Any environment variable tagged as *multisite* context can be used for a specific server block with the following format : *host_VARIABLE=value*. If the variable is used without the host prefix it will be applied to all the server blocks (but still can be overriden).
-
-`SERVER_NAME`
-Values : *<first name> <second name> ...*
-Default value : *www.bunkerity.com*
-Context : *global*
-Sets the host names of the webserver separated with spaces. This must match the Host header sent by clients.
-Useful when used with `MULTISITE=yes` and/or `AUTO_LETSENCRYPT=yes` and/or `DISABLE_DEFAULT_SERVER=yes`.
-
-`MAX_CLIENT_SIZE`
-Values : *0* | *Xm*
-Default value : *10m*
-Context : *global*, *multisite*
-Sets the maximum body size before nginx returns a 413 error code.
-Setting to 0 means "infinite" body size.
-
-`ALLOWED_METHODS`
-Values : *allowed HTTP methods separated with | char*
-Default value : *GET|POST|HEAD*
-Context : *global*, *multisite*
-Only the HTTP methods listed here will be accepted by nginx. If not listed, nginx will close the connection.
-
-`DISABLE_DEFAULT_SERVER`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*
-If set to yes, nginx will only respond to HTTP request when the Host header match a FQDN specified in the `SERVER_NAME` environment variable.
-For example, it will close the connection if a bot access the site with direct ip.
-
-`SERVE_FILES`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to yes, nginx will serve files from /www directory within the container.
-A use case to not serving files is when you setup bunkerized-nginx as a reverse proxy.
-
-`DNS_RESOLVERS`
-Values : *\
*
-Default value :
-Context : *global*, *multisite*
-Only valid when `USE_REVERSE_PROXY` is set to *yes*.
-You can set multiple url/host by adding a suffix number to the variable name like this : `REVERSE_PROXY_HEADERS_1`, `REVERSE_PROXY_HEADERS_2`, `REVERSE_PROXY_HEADERS_3`, ...
-
-`PROXY_REAL_IP`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-Set this environment variable to *yes* if you're using bunkerized-nginx behind a reverse proxy. This means you will see the real client address instead of the proxy one inside your logs. Modsecurity, fail2ban and others security tools will also then work correctly.
-
-`PROXY_REAL_IP_FROM`
-Values : *\
*
-Default value : *192.168.0.0/16 172.16.0.0/12 10.0.0.0/8*
-Context : *global*, *multisite*
-When `PROXY_REAL_IP` is set to *yes*, lets you define the trusted IPs/networks allowed to send the correct client address.
-
-`PROXY_REAL_IP_HEADER`
-Values : *X-Forwarded-For* | *X-Real-IP* | *custom header*
-Default value : *X-Forwarded-For*
-Context : *global*, *multisite*
-When `PROXY_REAL_IP` is set to *yes*, lets you define the header that contains the real client IP address.
-
-`PROXY_REAL_IP_RECURSIVE`
-Values : *on* | *off*
-Default value : *on*
-Context : *global*, *multisite*
-When `PROXY_REAL_IP` is set to *yes*, setting this to *on* avoid spoofing attacks using the header defined in `PROXY_REAL_IP_HEADER`.
-
-### Compression
-
-`USE_GZIP`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-When set to *yes*, nginx will use the gzip algorithm to compress responses sent to clients.
-
-`GZIP_COMP_LEVEL`
-Values : \<*any integer between 1 and 9*\>
-Default value : *5*
-Context : *global*, *multisite*
-The gzip compression level to use when `USE_GZIP` is set to *yes*.
-
-`GZIP_MIN_LENGTH`
-Values : \<*any positive integer*\>
-Default value : *1000*
-Context : *global*, *multisite*
-The minimum size (in bytes) of a response required to compress when `USE_GZIP` is set to *yes*.
-
-`GZIP_TYPES`
-Values : \<*list of mime types separated with space*\>
-Default value : *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*
-Context : *global*, *multisite*
-List of response MIME type required to compress when `USE_GZIP` is set to *yes*.
-
-`USE_BROTLI`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-When set to *yes*, nginx will use the brotli algorithm to compress responses sent to clients.
-
-`BROTLI_COMP_LEVEL`
-Values : \<*any integer between 1 and 9*\>
-Default value : *5*
-Context : *global*, *multisite*
-The brotli compression level to use when `USE_BROTLI` is set to *yes*.
-
-`BROTLI_MIN_LENGTH`
-Values : \<*any positive integer*\>
-Default value : *1000*
-Context : *global*, *multisite*
-The minimum size (in bytes) of a response required to compress when `USE_BROTLI` is set to *yes*.
-
-`BROTLI_TYPES`
-Values : \<*list of mime types separated with space*\>
-Default value : *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*
-Context : *global*, *multisite*
-List of response MIME type required to compress when `USE_BROTLI` is set to *yes*.
-
-### Cache
-
-`USE_CLIENT_CACHE`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-When set to *yes*, clients will be told to cache some files locally.
-
-`CLIENT_CACHE_EXTENSIONS`
-Values : \<*list of extensions separated with |*\>
-Default value : *jpg|jpeg|png|bmp|ico|svg|tif|css|js|otf|ttf|eot|woff|woff2*
-Context : *global*, *multisite*
-List of file extensions that clients should cache when `USE_CLIENT_CACHE` is set to *yes*.
-
-`CLIENT_CACHE_CONTROL`
-Values : \<*Cache-Control header value*\>
-Default value : *public, max-age=15552000*
-Context : *global*, *multisite*
-Content of the [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) header to send when `USE_CLIENT_CACHE` is set to *yes*.
-
-`CLIENT_CACHE_ETAG`
-Values : *on* | *off*
-Default value : *on*
-Context : *global*, *multisite*
-Whether or not nginx will send the [ETag](https://en.wikipedia.org/wiki/HTTP_ETag) header when `USE_CLIENT_CACHE` is set to *yes*.
-
-`USE_OPEN_FILE_CACHE`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-When set to *yes*, nginx will cache open fd, existence of directories, ... See [open_file_cache](http://nginx.org/en/docs/http/ngx_http_core_module.html#open_file_cache).
-
-`OPEN_FILE_CACHE`
-Values : \<*any valid open_file_cache parameters*\>
-Default value : *max=1000 inactive=20s*
-Context : *global*, *multisite*
-Parameters to use with open_file_cache when `USE_OPEN_FILE_CACHE` is set to *yes*.
-
-`OPEN_FILE_CACHE_ERRORS`
-Values : *on* | *off*
-Default value : *on*
-Context : *global*, *multisite*
-Whether or not nginx should cache file lookup errors when `USE_OPEN_FILE_CACHE` is set to *yes*.
-
-`OPEN_FILE_CACHE_MIN_USES`
-Values : \<*any valid integer *\>
-Default value : *2*
-Context : *global*, *multisite*
-The minimum number of file accesses required to cache the fd when `USE_OPEN_FILE_CACHE` is set to *yes*.
-
-`OPEN_FILE_CACHE_VALID`
-Values : \<*any time value like Xs, Xm, Xh, ...*\>
-Default value : *30s*
-Context : *global*, *multisite*
-The time after which cached elements should be validated when `USE_OPEN_FILE_CACHE` is set to *yes*.
-
-`USE_PROXY_CACHE`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-When set to *yes*, nginx will cache responses from proxied applications. See [proxy_cache](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache).
-
-`PROXY_CACHE_PATH_ZONE_SIZE`
-Values : \<*any valid size like Xk, Xm, Xg, ...*\>
-Default value : *10m*
-Context : *global*, *multisite*
-Maximum size of cached metadata when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_CACHE_PATH_PARAMS`
-Values : \<*any valid parameters to proxy_cache_path directive*\>
-Default value : *max_size=100m*
-Context : *global*, *multisite*
-Parameters to use for [proxy_cache_path](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_path) directive when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_CACHE_METHODS`
-Values : \<*list of HTTP methods separated with space*\>
-Default value : *GET HEAD*
-Context : *global*, *multisite*
-The HTTP methods that should trigger a cache operation when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_CACHE_MIN_USES`
-Values : \<*any positive integer*\>
-Default value : *2*
-Context : *global*, *multisite*
-The minimum number of requests before the response is cached when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_CACHE_KEY`
-Values : \<*list of variables*\>
-Default value : *$scheme$host$request_uri*
-Context : *global*, *multisite*
-The key used to uniquely identify a cached response when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_CACHE_VALID`
-Values : \<*status=time list separated with space*\>
-Default value : *200=10m 301=10m 302=1h*
-Context : *global*, *multisite*
-Define the caching time depending on the HTTP status code (list of status=time separated with space) when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_NO_CACHE`
-Values : \<*list of variables*\>
-Default value : *$http_authorization*
-Context : *global*, *multisite*
-Conditions that must be met to disable caching of the response when `USE_PROXY_CACHE` is set to *yes*.
-
-`PROXY_CACHE_BYPASS`
-Values : \<*list of variables*\>
-Default value : *$http_authorization*
-Context : *global*, *multisite*
-Conditions that must be met to bypass the cache when `USE_PROXY_CACHE` is set to *yes*.
-
-## HTTPS
-
-### Let's Encrypt
-
-`AUTO_LETS_ENCRYPT`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-If set to yes, automatic certificate generation and renewal will be setup through Let's Encrypt. This will enable HTTPS on your website for free.
-You will need to redirect the 80 port to 8080 port inside container and also set the `SERVER_NAME` environment variable.
-
-`EMAIL_LETS_ENCRYPT`
-Values : *contact@yourdomain.com*
-Default value : *contact@yourdomain.com*
-Context : *global*, *multisite*
-Define the contact email address declare in the certificate.
-
-### HTTP
-
-`LISTEN_HTTP`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to no, nginx will not in listen on HTTP (port 80).
-Useful if you only want HTTPS access to your website.
-
-`REDIRECT_HTTP_TO_HTTPS`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-If set to yes, nginx will redirect all HTTP requests to HTTPS.
-
-### Custom certificate
-
-`USE_CUSTOM_HTTPS`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-If set to yes, HTTPS will be enabled with certificate/key of your choice.
-
-`CUSTOM_HTTPS_CERT`
-Values : *\
*
-Default value : *bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org*
-Context : *global*
-The list of DNSBL zones to query when `USE_DNSBL` is set to *yes*.
-
-### CrowdSec
-
-`USE_CROWDSEC`
-Values : *yes* | *no*
-Default value : *no*
-Context : *global*, *multisite*
-If set to *yes*, [CrowdSec](https://github.com/crowdsecurity/crowdsec) will be enabled. Please note that you need a CrowdSec instance running see example [here](https://github.com/bunkerity/bunkerized-nginx/tree/master/examples/crowdsec).
-
-`CROWDSEC_HOST`
-Values : *\
*
-Default value : *23.21.227.69 40.88.21.235 50.16.241.113 50.16.241.114 50.16.241.117 50.16.247.234 52.204.97.54 52.5.190.19 54.197.234.188 54.208.100.253 54.208.102.37 107.21.1.8*
-Context : *global*
-The list of IP addresses and/or network CIDR blocks to whitelist when `USE_WHITELIST_IP` is set to *yes*. The default list contains IP addresses of the [DuckDuckGo crawler](https://help.duckduckgo.com/duckduckgo-help-pages/results/duckduckbot/).
-
-`USE_WHITELIST_REVERSE`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to *yes*, lets you define custom reverse DNS suffixes to be whitelisted through the `WHITELIST_REVERSE_LIST` environment variable.
-
-`WHITELIST_REVERSE_LIST`
-Values : *\
*
-Default value : *.googlebot.com .google.com .search.msn.com .crawl.yahoot.net .crawl.baidu.jp .crawl.baidu.com .yandex.com .yandex.ru .yandex.net*
-Context : *global*
-The list of reverse DNS suffixes to whitelist when `USE_WHITELIST_REVERSE` is set to *yes*. The default list contains suffixes of major search engines.
-
-`WHITELIST_USER_AGENT`
-Values : *\
*
-Default value :
-Context : *global*, *multisite*
-Whitelist user agent from being blocked by `BLOCK_USER_AGENT`.
-
-`WHITELIST_URI`
-Values : *\
*
-Default value :
-Context : *global*, *multisite*
-URI listed here have security checks like bad user-agents, bad IP, ... disabled. Useful when using callbacks for example.
-
-### Custom blacklisting
-
-`USE_BLACKLIST_IP`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to *yes*, lets you define custom IP addresses to be blacklisted through the `BLACKLIST_IP_LIST` environment variable.
-
-`BLACKLIST_IP_LIST`
-Values : *\
*
-Default value :
-Context : *global*
-The list of IP addresses and/or network CIDR blocks to blacklist when `USE_BLACKLIST_IP` is set to *yes*.
-
-`USE_BLACKLIST_REVERSE`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to *yes*, lets you define custom reverse DNS suffixes to be blacklisted through the `BLACKLIST_REVERSE_LIST` environment variable.
-
-`BLACKLIST_REVERSE_LIST`
-Values : *\
*
-Default value : *.shodan.io*
-Context : *global*
-The list of reverse DNS suffixes to blacklist when `USE_BLACKLIST_REVERSE` is set to *yes*.
-
-### Requests limiting
-
-`USE_LIMIT_REQ`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to yes, the amount of HTTP requests made by a user for a given resource will be limited during a period of time.
-More info rate limiting [here](https://www.nginx.com/blog/rate-limiting-nginx/) (the key used is $binary_remote_addr$uri).
-
-`LIMIT_REQ_RATE`
-Values : *Xr/s* | *Xr/m*
-Default value : *1r/s*
-Context : *global*, *multisite*
-The rate limit to apply when `USE_LIMIT_REQ` is set to *yes*. Default is 1 request to the same URI and from the same IP per second.
-
-`LIMIT_REQ_BURST`
-Values : *
*
-Default value : 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
-Context : *global*
-IPs or subnet which should never be ban by fail2ban.
-
-## ClamAV
-
-`USE_CLAMAV_UPLOAD`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*, *multisite*
-If set to yes, ClamAV will scan every file uploads and block the upload if the file is detected.
-
-`USE_CLAMAV_SCAN`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*
-If set to yes, ClamAV will scan all the files inside the container every day.
-
-`CLAMAV_SCAN_REMOVE`
-Values : *yes* | *no*
-Default value : *yes*
-Context : *global*
-If set to yes, ClamAV will automatically remove the detected files.
-
-## Syslog
-
-`REMOTE_SYSLOG`
-Values : *\
*
-Default value : *192.168.0.0/16 172.16.0.0/12 10.0.0.0/8*
-Context : *global*
-List of IP/CIDR block allowed to send API order using the `API_URI` uri.
+- [Official documentation](https://bunkerized-nginx.readthedocs.io/)
+- [Full concrete examples](https://github.com/bunkerity/bunkerized-nginx/tree/master/examples)
+- [Tutorials in our blog](https://www.bunkerity.com/blog)
diff --git a/docs/introduction.md b/docs/introduction.md
index 5312a65..79f8af9 100644
--- a/docs/introduction.md
+++ b/docs/introduction.md
@@ -6,13 +6,13 @@
nginx Docker image secure by default.
-Avoid the hassle of following security best practices each time you need a web server or reverse proxy. Bunkerized-nginx provides generic security configs, settings and tools so you don't need to do it yourself.
+Avoid the hassle of following security best practices "by hand" each time you need a web server or reverse proxy. Bunkerized-nginx provides generic security configs, settings and tools so you don't need to do it yourself.
Non-exhaustive list of 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 with fail2ban
+- Automatic ban of strange behaviors
- Antibot challenge through cookie, javascript, captcha or recaptcha v3
- Block TOR, proxies, bad user-agents, countries, ...
- Block known bad IP with DNSBL and CrowdSec
diff --git a/docs/quickstart_guide.md b/docs/quickstart_guide.md
index 2932ec2..61230e1 100644
--- a/docs/quickstart_guide.md
+++ b/docs/quickstart_guide.md
@@ -6,18 +6,24 @@
docker run -p 80:8080 -v /path/to/web/files:/www:ro bunkerity/bunkerized-nginx
```
-Web files are stored in the /www directory, the container will serve files from there. Please note that *bunkerized-nginx* doesn't run as root but with an unprivileged user with UID/GID 101 therefore you should set the rights of */path/to/web/files* accordingly.
+Web files are stored in the /www directory, the container will serve files from there. Please note that *bunkerized-nginx* doesn't run as root but as an unprivileged user with UID/GID 101 therefore you should set the rights of */path/to/web/files* accordingly.
## In combination with PHP
```shell
docker network create mynet
+```
+
+```shell
docker run --network mynet \
-p 80:8080 \
-v /path/to/web/files:/www:ro \
-e REMOTE_PHP=myphp \
-e REMOTE_PHP_PATH=/app \
bunkerity/bunkerized-nginx
+```
+
+```shell
docker run --network mynet \
--name myphp \
-v /path/to/web/files:/app \
@@ -39,7 +45,7 @@ docker run -p 80:8080 \
bunkerity/bunkerized-nginx
```
-Certificates are stored in the /etc/letsencrypt directory, you should save it on your local drive. Please note that *bunkerized-nginx* doesn't run as root but with an unprivileged user with UID/GID 101 therefore you should set the rights of */where/to/save/certificates* accordingly.
+Certificates are stored in the /etc/letsencrypt directory, you should save it on your local drive. Please note that *bunkerized-nginx* doesn't run as root but as an unprivileged user with UID/GID 101 therefore you should set the rights of */where/to/save/certificates* accordingly.
If you don't want your webserver to listen on HTTP add the environment variable `LISTEN_HTTP` with a *no* value (e.g. HTTPS only). But Let's Encrypt needs the port 80 to be opened so redirecting the port is mandatory.
@@ -81,7 +87,7 @@ docker run -p 80:8080 \
The `PROXY_REAL_IP` environment variable, when set to *yes*, activates the [ngx_http_realip_module](https://nginx.org/en/docs/http/ngx_http_realip_module.html) to get the real client IP from the reverse proxy.
-See [this section](#reverse-proxy) if you need to tweak some values (trusted ip/network, header, ...).
+See [this section](https://bunkerized-nginx.readthedocs.io/en/latest/environment_variables.html#reverse-proxy) if you need to tweak some values (trusted ip/network, header, ...).
## Multisite
@@ -197,7 +203,7 @@ docker run --network mynet \
-l bunkerized-nginx.SERVER_NAME=app2.domain.com \
-l bunkerized-nginx.USE_REVERSE_PROXY=yes \
-l bunkerized-nginx.REVERSE_PROXY_URL=/ \
- -l bunkerized-nginx.REVERSE_PROXY_HOST=http://anotherapp
+ -l bunkerized-nginx.REVERSE_PROXY_HOST=http://anotherapp \
tutum/hello-world
```
diff --git a/docs/security_tuning.md b/docs/security_tuning.md
index cc18c52..faf59c3 100644
--- a/docs/security_tuning.md
+++ b/docs/security_tuning.md
@@ -35,11 +35,12 @@ If you have security constraints (e.g : local network, custom PKI, ...) you can
- `CUSTOM_HTTPS_CERT=/path/inside/container/to/cert.pem`
- `CUSTOM_HTTPS_KEY=/path/inside/container/to/key.pem`
-Here is a dummy example on how to use custom certificates :
+Here is a an example on how to use custom certificates :
```shell
$ ls /etc/ssl/my-web-app
cert.pem key.pem
+
$ docker run -p 80:8080 \
-p 443:8443 \
-v /etc/ssl/my-web-app:/certs:ro \
@@ -63,7 +64,7 @@ $ docker run -p 80:8080 \
## Headers
-Some important HTTP headers related to client security are sent with a default value. Sometimes it can break a web application or can be tuned to provide even more security. The complete list is available [here](#TODO).
+Some important HTTP headers related to client security are sent with a default value. Sometimes it can break a web application or can be tuned to provide even more security. The complete list is available [here](https://bunkerized-nginx.readthedocs.io/en/latest/environment_variables.html#security-headers).
You can also remove headers (e.g. : too verbose ones) by using the `REMOVE_HEADERS` environment variable which takes a list of header name separated with space (default value = `Server X-Powered-By X-AspNet-Version X-AspNetMvc-Version`).
@@ -115,7 +116,7 @@ That kind of security measure is implemented and enabled by default in bunkerize
Attackers will certainly use automated tools to exploit/find some vulnerabilities on your web service. One countermeasure is to challenge the users to detect if it looks like a bot. It might be effective against script kiddies or "lazy" attackers.
-You can use the `USE_ANTIBOT` environment variable to add that kind of checks whenever a new client is connecting. The available challenges are : `cookie`, `javascript`, `captcha` and `recaptcha`. More info [here](#TODO).
+You can use the `USE_ANTIBOT` environment variable to add that kind of checks whenever a new client is connecting. The available challenges are : `cookie`, `javascript`, `captcha` and `recaptcha`. More info [here](https://bunkerized-nginx.readthedocs.io/en/latest/environment_variables.html#antibot).
## External blacklists
@@ -136,7 +137,7 @@ If you want to give it a try, you have a concrete example on how to use CrowdSec
Sometimes script kiddies or lazy attackers don't put a "legitimate" value inside the **User-Agent** HTTP header so we can block them. This is controlled with the `BLOCK_USER_AGENT=yes` environment variable. The blacklist is composed of two files from [here](https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/_generator_lists/bad-user-agents.list) and [here](https://raw.githubusercontent.com/JayBizzle/Crawler-Detect/master/raw/Crawlers.txt).
-If a legitimate User-Agent is blacklisted, you can use the `WHITELIST_USER_AGENT` while still keeping the `BLOCK_USER_AGENT=yes` (more info [here](#TODO)).
+If a legitimate User-Agent is blacklisted, you can use the `WHITELIST_USER_AGENT` while still keeping the `BLOCK_USER_AGENT=yes` (more info [here](https://bunkerized-nginx.readthedocs.io/en/latest/environment_variables.html#custom-whitelisting)).
### TOR exit nodes
@@ -194,9 +195,9 @@ Adding extra security can sometimes trigger false positives. Also, it might be n
Here is the list of related environment variables and their default value :
- `USE_WHITELIST_IP=yes` : enable/disable whitelisting by IP address
-- `WHITELIST_IP_LIST=23.21.227.69 40.88.21.235 50.16.241.113 50.16.241.114 50.16.241.117 50.16.247.234 52.204.97.54 52.5.190.19 54.197.234.188 54.208.100.253 54.208.102.37 107.21.1.8` : list of IP addresses and/or network CIDR blocks to whitelist (default contains the IP addresses of the [DuckDuckGo crawler](https://help.duckduckgo.com/duckduckgo-help-pages/results/duckduckbot/)).
+- `WHITELIST_IP_LIST=23.21.227.69 40.88.21.235 50.16.241.113 50.16.241.114 50.16.241.117 50.16.247.234 52.204.97.54 52.5.190.19 54.197.234.188 54.208.100.253 54.208.102.37 107.21.1.8` : list of IP addresses and/or network CIDR blocks to whitelist (default contains the IP addresses of the [DuckDuckGo crawler](https://help.duckduckgo.com/duckduckgo-help-pages/results/duckduckbot/))
- `USE_WHITELIST_REVERSE=yes` : enable/disable whitelisting by reverse DNS
-- `WHITELIST_REVERSE_LIST=.googlebot.com .google.com .search.msn.com .crawl.yahoot.net .crawl.baidu.jp .crawl.baidu.com .yandex.com .yandex.ru .yandex.net` : the list of reverse DNS suffixes to trust (default contains the list of major search engines crawlers).
+- `WHITELIST_REVERSE_LIST=.googlebot.com .google.com .search.msn.com .crawl.yahoot.net .crawl.baidu.jp .crawl.baidu.com .yandex.com .yandex.ru .yandex.net` : the list of reverse DNS suffixes to trust (default contains the list of major search engines crawlers)
## Blacklisting
@@ -206,7 +207,7 @@ Here is the list of related environment variables and their default value :
- `USE_BLACKLIST_IP=yes` : enable/disable blacklisting by IP address
- `BLACKLIST_IP_LIST=` : list of IP addresses and/or network CIDR blocks to blacklist
- `USE_BLACKLIST_REVERSE=yes` : enable/disable blacklisting by reverse DNS
-- `BLACKLIST_REVERSE_LIST=.shodan.io` : the list of reverse DNS suffixes to never trust.
+- `BLACKLIST_REVERSE_LIST=.shodan.io` : the list of reverse DNS suffixes to never trust
## Container hardening
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index 15b6fcf..74ae77f 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -6,7 +6,7 @@ When troubleshooting, the logs are your best friends. We try our best to provide
## Permissions
-Don't forget that bunkerized-nginx runs as an unprivileged user with UID/GID 101. Double check the permissions of files and folders for each volumes (see the [volumes list](#TODO)).
+Don't forget that bunkerized-nginx runs as an unprivileged user with UID/GID 101. Double check the permissions of files and folders for each volumes (see the [volumes list](https://bunkerized-nginx.readthedocs.io/en/latest/volumes.html)).
## ModSecurity
@@ -29,5 +29,5 @@ It's a common case that a bot gets flagged as suspicious and can't access your w
- `WHITELIST_URI`
- `WHITELIST_USER_AGENT`
-More information [here](#).
+More information [here](https://bunkerized-nginx.readthedocs.io/en/latest/environment_variables.html#custom-whitelisting).