<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Florian Pitance</title>
    <description>The latest articles on DEV Community by Florian Pitance (@bunkerity).</description>
    <link>https://dev.to/bunkerity</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F550769%2Faf51648e-59a7-4336-bba2-795e44318d20.png</url>
      <title>DEV Community: Florian Pitance</title>
      <link>https://dev.to/bunkerity</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bunkerity"/>
    <language>en</language>
    <item>
      <title>bunkerized-nginx - make your web apps and APIs secured by default</title>
      <dc:creator>Florian Pitance</dc:creator>
      <pubDate>Thu, 18 Mar 2021 20:31:23 +0000</pubDate>
      <link>https://dev.to/bunkerity/bunkerized-nginx-make-your-web-apps-and-apis-secured-by-default-2i4n</link>
      <guid>https://dev.to/bunkerity/bunkerized-nginx-make-your-web-apps-and-apis-secured-by-default-2i4n</guid>
      <description>&lt;h1&gt;
  
  
  Why bunkerized-nginx ?
&lt;/h1&gt;

&lt;p&gt;Avoid the hassle of following security best practices each time you need a web server or reverse proxy. &lt;a href="https://github.com/bunkerity/bunkerized-nginx" rel="noopener noreferrer"&gt;Bunkerized-nginx&lt;/a&gt; provides generic security configs, settings and tools so you don't need to do it yourself.&lt;/p&gt;

&lt;p&gt;Non-exhaustive list of features :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTPS support with transparent Let's Encrypt automation&lt;/li&gt;
&lt;li&gt;State-of-the-art web security : HTTP security headers, prevent leaks, TLS hardening, ...&lt;/li&gt;
&lt;li&gt;Integrated ModSecurity WAF with the OWASP Core Rule Set&lt;/li&gt;
&lt;li&gt;Automatic ban of strange behaviors with fail2ban&lt;/li&gt;
&lt;li&gt;Antibot challenge through cookie, javascript, captcha or recaptcha v3&lt;/li&gt;
&lt;li&gt;Block TOR, proxies, bad user-agents, countries, ...&lt;/li&gt;
&lt;li&gt;Block known bad IP with DNSBL and CrowdSec&lt;/li&gt;
&lt;li&gt;Prevent bruteforce attacks with rate limiting&lt;/li&gt;
&lt;li&gt;Detect bad files with ClamAV&lt;/li&gt;
&lt;li&gt;Easy to configure with environment variables or web UI&lt;/li&gt;
&lt;li&gt;Automatic configuration with container labels&lt;/li&gt;
&lt;li&gt;Docker Swarm support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fooling automated tools/scanners :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fbunkerity%2Fbunkerized-nginx%2Fblob%2Fmaster%2Fdemo.gif%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fbunkerity%2Fbunkerized-nginx%2Fblob%2Fmaster%2Fdemo.gif%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Quickstart guide
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Run HTTP server with default settings
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/web/files:/www:ro bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Web files are stored in the /www directory, the container will serve files from there. Please note that &lt;em&gt;bunkerized-nginx&lt;/em&gt; doesn't run as root but with an unprivileged user with UID/GID 101 therefore you should set the rights of &lt;em&gt;/path/to/web/files&lt;/em&gt; accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  In combination with PHP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create mynet
docker run &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/web/files:/www:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REMOTE_PHP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;myphp &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REMOTE_PHP_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
docker run &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;--name&lt;/span&gt; myphp &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/web/files:/app &lt;span class="se"&gt;\&lt;/span&gt;
           php:fpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;REMOTE_PHP&lt;/code&gt; environment variable lets you define the address of a remote PHP-FPM instance that will execute the .php files. &lt;code&gt;REMOTE_PHP_PATH&lt;/code&gt; must be set to the directory where the PHP container will find the files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run HTTPS server with automated Let's Encrypt
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-p&lt;/span&gt; 443:8443 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/web/files:/www:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/to/save/certificates:/etc/letsencrypt &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;www.yourdomain.com &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AUTO_LETS_ENCRYPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIRECT_HTTP_TO_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Certificates are stored in the /etc/letsencrypt directory, you should save it on your local drive. Please note that &lt;em&gt;bunkerized-nginx&lt;/em&gt; doesn't run as root but with an unprivileged user with UID/GID 101 therefore you should set the rights of &lt;em&gt;/where/to/save/certificates&lt;/em&gt; accordingly.&lt;/p&gt;

&lt;p&gt;If you don't want your webserver to listen on HTTP add the environment variable &lt;code&gt;LISTEN_HTTP&lt;/code&gt; with a &lt;em&gt;no&lt;/em&gt; value (e.g. HTTPS only). But Let's Encrypt needs the port 80 to be opened so redirecting the port is mandatory.&lt;/p&gt;

&lt;p&gt;Here you have three environment variables :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SERVER_NAME&lt;/code&gt; : define the FQDN of your webserver, this is mandatory for Let's Encrypt (&lt;a href="http://www.yourdomain.com" rel="noopener noreferrer"&gt;www.yourdomain.com&lt;/a&gt; should point to your IP address)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AUTO_LETS_ENCRYPT&lt;/code&gt; : enable automatic Let's Encrypt creation and renewal of certificates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;REDIRECT_HTTP_TO_HTTPS&lt;/code&gt; : enable HTTP to HTTPS redirection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  As a reverse proxy
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;USE_REVERSE_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REVERSE_PROXY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REVERSE_PROXY_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://myserver:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple reverse proxy to a unique application. If you have more than one application you can add more REVERSE_PROXY_URL/REVERSE_PROXY_HOST by appending a suffix number like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;USE_REVERSE_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REVERSE_PROXY_URL_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app1/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REVERSE_PROXY_HOST_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://myapp1:3000/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REVERSE_PROXY_URL_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app2/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REVERSE_PROXY_HOST_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://myapp2:3000/ &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Behind a reverse proxy
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/web/files:/www &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PROXY_REAL_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;PROXY_REAL_IP&lt;/code&gt; environment variable, when set to &lt;em&gt;yes&lt;/em&gt;, activates the &lt;a href="https://nginx.org/en/docs/http/ngx_http_realip_module.html" rel="noopener noreferrer"&gt;ngx_http_realip_module&lt;/a&gt; to get the real client IP from the reverse proxy.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://github.com/bunkerity/bunkerized-nginx#reverse-proxy" rel="noopener noreferrer"&gt;this section&lt;/a&gt; if you need to tweak some values (trusted ip/network, header, ...).&lt;/p&gt;

&lt;h2&gt;
  
  
  Multisite
&lt;/h2&gt;

&lt;p&gt;By default, bunkerized-nginx will only create one server block. When setting the &lt;code&gt;MULTISITE&lt;/code&gt; environment variable to &lt;em&gt;yes&lt;/em&gt;, one server block will be created for each host defined in the &lt;code&gt;SERVER_NAME&lt;/code&gt; environment variable.&lt;br&gt;&lt;br&gt;
You can set/override values for a specific server by prefixing the environment variable with one of the server name previously defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-p&lt;/span&gt; 443:8443 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/to/save/certificates:/etc/letsencrypt &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;app1.domain.com app2.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MULTISITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AUTO_LETS_ENCRYPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIRECT_HTTP_TO_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;USE_REVERSE_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app1.domain.com_REVERSE_PROXY_URL&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app1.domain.com_REVERSE_PROXY_HOST&lt;span class="o"&gt;=&lt;/span&gt;http://myapp1:8000 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app2.domain.com_REVERSE_PROXY_URL&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app2.domain.com_REVERSE_PROXY_HOST&lt;span class="o"&gt;=&lt;/span&gt;http://myapp2:8000 &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;USE_REVERSE_PROXY&lt;/code&gt; is a &lt;em&gt;global&lt;/em&gt; variable that will be applied to each server block. Whereas the &lt;code&gt;app1.domain.com_*&lt;/code&gt; and &lt;code&gt;app2.domain.com_*&lt;/code&gt; will only be applied to the app1.domain.com and app2.domain.com server block respectively.&lt;/p&gt;

&lt;p&gt;When serving files, the web root directory should contains subdirectories named as the servers defined in the &lt;code&gt;SERVER_NAME&lt;/code&gt; environment variable. Here is an example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-p&lt;/span&gt; 443:8443 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/to/save/certificates:/etc/letsencrypt &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/are/web/files:/www:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;app1.domain.com app2.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MULTISITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AUTO_LETS_ENCRYPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIRECT_HTTP_TO_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app1.domain.com_REMOTE_PHP&lt;span class="o"&gt;=&lt;/span&gt;php1 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app1.domain.com_REMOTE_PHP_PATH&lt;span class="o"&gt;=&lt;/span&gt;/app &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app2.domain.com_REMOTE_PHP&lt;span class="o"&gt;=&lt;/span&gt;php2 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; app2.domain.com_REMOTE_PHP_PATH&lt;span class="o"&gt;=&lt;/span&gt;/app &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;/where/are/web/files&lt;/em&gt; directory should have a structure like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/where/are/web/files
├── app1.domain.com
│   └── index.php
│   └── ...
└── app2.domain.com
    └── index.php
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automatic configuration
&lt;/h2&gt;

&lt;p&gt;The downside of using environment variables is that you need to recreate a new container each time you want to add or remove a web service. An alternative is to use the &lt;em&gt;bunkerized-nginx-autoconf&lt;/em&gt; image which listens for Docker events and "automagically" generates the configuration.&lt;/p&gt;

&lt;p&gt;First we need a volume that will store the configurations :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create nginx_conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we run bunkerized-nginx with the &lt;code&gt;bunkerized-nginx.AUTOCONF&lt;/code&gt; label, mount the created volume at /etc/nginx and set some default configurations for our services (e.g. : automatic Let's Encrypt and HTTP to HTTPS redirect) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create mynet

docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-p&lt;/span&gt; 443:8443 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/to/save/certificates:/etc/letsencrypt &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/are/web/files:/www:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; nginx_conf:/etc/nginx &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MULTISITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AUTO_LETS_ENCRYPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIRECT_HTTP_TO_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized.nginx.AUTOCONF &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When setting &lt;code&gt;SERVER_NAME&lt;/code&gt; to nothing bunkerized-nginx won't create any server block (in case we only want automatic configuration). &lt;/p&gt;

&lt;p&gt;Once bunkerized-nginx is created, let's setup the autoconf container :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; nginx_conf:/etc/nginx &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx-autoconf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create a new container and use labels to dynamically configure bunkerized-nginx. Labels for automatic configuration are the same as environment variables but with the "bunkerized-nginx." prefix.&lt;/p&gt;

&lt;p&gt;Here is a PHP example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;--name&lt;/span&gt; myapp &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/are/web/files/app.domain.com:/app &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.SERVER_NAME&lt;span class="o"&gt;=&lt;/span&gt;app.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REMOTE_PHP&lt;span class="o"&gt;=&lt;/span&gt;myapp &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REMOTE_PHP_PATH&lt;span class="o"&gt;=&lt;/span&gt;/app &lt;span class="se"&gt;\&lt;/span&gt;
           php:fpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a reverse proxy example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;--name&lt;/span&gt; anotherapp &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.SERVER_NAME&lt;span class="o"&gt;=&lt;/span&gt;app2.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.USE_REVERSE_PROXY&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REVERSE_PROXY_URL&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REVERSE_PROXY_HOST&lt;span class="o"&gt;=&lt;/span&gt;http://anotherapp
           tutum/hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Swarm mode
&lt;/h2&gt;

&lt;p&gt;Automatic configuration through labels is also supported in swarm mode. The &lt;em&gt;bunkerized-nginx-autoconf&lt;/em&gt; is used to listen for Swarm events (e.g. service create/rm) and "automagically" edit configurations files and reload nginx.&lt;/p&gt;

&lt;p&gt;As a use case we will assume the following :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some managers are also workers (they will only run the &lt;em&gt;autoconf&lt;/em&gt; container for obvious security reasons)&lt;/li&gt;
&lt;li&gt;The bunkerized-nginx service will be deployed on all workers (global mode) so clients can connect to each of them (e.g. load balancing, CDN, edge proxy, ...)&lt;/li&gt;
&lt;li&gt;There is a shared folder mounted on managers and workers (e.g. NFS, GlusterFS, CephFS, ...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start by creating the network to allow communications between our services :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create &lt;span class="nt"&gt;-d&lt;/span&gt; overlay mynet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create the &lt;em&gt;autoconf&lt;/em&gt; service that will listen to swarm events :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker service create &lt;span class="nt"&gt;--name&lt;/span&gt; autoconf &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/var/run/docker.sock,destination&lt;span class="o"&gt;=&lt;/span&gt;/var/run/docker.sock,ro &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/confs,destination&lt;span class="o"&gt;=&lt;/span&gt;/etc/nginx &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/letsencrypt,destination&lt;span class="o"&gt;=&lt;/span&gt;/etc/letsencrypt &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/acme-challenge,destination&lt;span class="o"&gt;=&lt;/span&gt;/acme-challenge &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SWARM_MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;API_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/ChangeMeToSomethingHardToGuess &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--replicas&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--constraint&lt;/span&gt; node.role&lt;span class="o"&gt;==&lt;/span&gt;manager &lt;span class="se"&gt;\&lt;/span&gt;
                      bunkerity/bunkerized-nginx-autoconf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You need to change &lt;code&gt;API_URI&lt;/code&gt; to something hard to guess since there is no other security mechanism to protect the API at the moment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When &lt;em&gt;autoconf&lt;/em&gt; is created, it's time for the &lt;em&gt;bunkerized-nginx&lt;/em&gt; service to be up :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker service create &lt;span class="nt"&gt;--name&lt;/span&gt; nginx &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;published&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80,target&lt;span class="o"&gt;=&lt;/span&gt;8080,mode&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;published&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;443,target&lt;span class="o"&gt;=&lt;/span&gt;8443,mode&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/confs,destination&lt;span class="o"&gt;=&lt;/span&gt;/etc/nginx &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/letsencrypt,destination&lt;span class="o"&gt;=&lt;/span&gt;/etc/letsencrypt,ro &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/acme-challenge,destination&lt;span class="o"&gt;=&lt;/span&gt;/acme-challenge,ro &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/www,destination&lt;span class="o"&gt;=&lt;/span&gt;/www,ro &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SWARM_MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;USE_API&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;API_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/ChangeMeToSomethingHardToGuess &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MULTISITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AUTO_LETS_ENCRYPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIRECT_HTTP_TO_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.AUTOCONF &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mode&lt;/span&gt; global &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--constraint&lt;/span&gt; node.role&lt;span class="o"&gt;==&lt;/span&gt;worker &lt;span class="se"&gt;\&lt;/span&gt;
                      bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;API_URI&lt;/code&gt; value must be the same as the one specified for the &lt;em&gt;autoconf&lt;/em&gt; service.&lt;/p&gt;

&lt;p&gt;We can now create a new service and use labels to dynamically configure bunkerized-nginx. Labels for automatic configuration are the same as environment variables but with the "bunkerized-nginx." prefix.&lt;/p&gt;

&lt;p&gt;Here is a PHP example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker service create &lt;span class="nt"&gt;--name&lt;/span&gt; myapp &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--mount&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bind&lt;/span&gt;,source&lt;span class="o"&gt;=&lt;/span&gt;/shared/www/app.domain.com,destination&lt;span class="o"&gt;=&lt;/span&gt;/app &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.SERVER_NAME&lt;span class="o"&gt;=&lt;/span&gt;app.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REMOTE_PHP&lt;span class="o"&gt;=&lt;/span&gt;myapp &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REMOTE_PHP_PATH&lt;span class="o"&gt;=&lt;/span&gt;/app &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--constraint&lt;/span&gt; node.role&lt;span class="o"&gt;==&lt;/span&gt;worker &lt;span class="se"&gt;\&lt;/span&gt;
                      php:fpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a reverse proxy example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker service create &lt;span class="nt"&gt;--name&lt;/span&gt; anotherapp &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.SERVER_NAME&lt;span class="o"&gt;=&lt;/span&gt;app2.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.USE_REVERSE_PROXY&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REVERSE_PROXY_URL&lt;span class="o"&gt;=&lt;/span&gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.REVERSE_PROXY_HOST&lt;span class="o"&gt;=&lt;/span&gt;http://anotherapp &lt;span class="se"&gt;\&lt;/span&gt;
                      &lt;span class="nt"&gt;--constraint&lt;/span&gt; node.role&lt;span class="o"&gt;==&lt;/span&gt;worker &lt;span class="se"&gt;\&lt;/span&gt;
                      tutum/hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Web UI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This feature exposes, for now, a security risk because you need to mount the docker socket inside a container exposing a web application. You can test it but you should not use it in servers facing the internet.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;A dedicated image, &lt;em&gt;bunkerized-nginx-ui&lt;/em&gt;, lets you manage bunkerized-nginx instances and services configurations through a web user interface. This feature is still in beta, feel free to open a new issue if you find a bug and/or you have an idea to improve it. &lt;/p&gt;

&lt;p&gt;First we need a volume that will store the configurations :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create nginx_conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can create the bunkerized-nginx instance with the &lt;code&gt;bunkerized-nginx.UI&lt;/code&gt; label and a reverse proxy configuration for our web UI :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create mynet

docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-p&lt;/span&gt; 443:8443 &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; nginx_conf:/etc/nginx &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/are/web/files:/www:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /where/to/save/certificates:/etc/letsencrypt &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SERVER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin.domain.com &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MULTISITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;AUTO_LETS_ENCRYPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIRECT_HTTP_TO_HTTPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DISABLE_DEFAULT_SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_SERVE_FILES&lt;span class="o"&gt;=&lt;/span&gt;no &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_USE_AUTH_BASIC&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_AUTH_BASIC_USER&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_AUTH_BASIC_PASSWORD&lt;span class="o"&gt;=&lt;/span&gt;password &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_USE_REVERSE_PROXY&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_REVERSE_PROXY_URL&lt;span class="o"&gt;=&lt;/span&gt;/webui/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; admin.domain.com_REVERSE_PROXY_HOST&lt;span class="o"&gt;=&lt;/span&gt;http://myui:5000/ &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-l&lt;/span&gt; bunkerized-nginx.UI &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;AUTH_BASIC&lt;/code&gt; environment variables let you define a login/password that must be provided before accessing to the web UI. At the moment, there is no authentication mechanism integrated into bunkerized-nginx-ui.&lt;/p&gt;

&lt;p&gt;We can now create the bunkerized-nginx-ui container that will host the web UI behind bunkerized-nginx :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--network&lt;/span&gt; mynet &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock:ro &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-v&lt;/span&gt; nginx_conf:/etc/nginx &lt;span class="se"&gt;\&lt;/span&gt;
           &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ABSOLUTE_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://admin.domain.com/webui/ &lt;span class="se"&gt;\&lt;/span&gt;
           bunkerity/bunkerized-nginx-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, the web UI should be accessible from &lt;a href="https://admin.domain.com/webui/" rel="noopener noreferrer"&gt;https://admin.domain.com/webui/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Antibot challenge
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 80:8080 &lt;span class="nt"&gt;-v&lt;/span&gt; /path/to/web/files:/www &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;USE_ANTIBOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;captcha bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;USE_ANTIBOT&lt;/code&gt; is set to &lt;em&gt;captcha&lt;/em&gt;, every users visiting your website must complete a captcha before accessing the pages. Others challenges are also available : &lt;em&gt;cookie&lt;/em&gt;, &lt;em&gt;javascript&lt;/em&gt; or &lt;em&gt;recaptcha&lt;/em&gt; (more info &lt;a href="https://github.com/bunkerity/bunkerized-nginx#antibot" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardening
&lt;/h2&gt;

&lt;p&gt;By default, &lt;em&gt;bunkerized-nginx&lt;/em&gt; runs as non-root user inside the container and should not use any of the default &lt;a href="https://docs.docker.com/engine/security/#linux-kernel-capabilities" rel="noopener noreferrer"&gt;capabilities&lt;/a&gt; allowed by Docker. You can safely remove all capabilities to harden the container :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run ... &lt;span class="nt"&gt;--drop-cap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;all ... bunkerity/bunkerized-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Going further
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;More info about the project on &lt;a href="https://github.com/bunkerity/bunkerized-nginx" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Have a look at the &lt;a href="https://github.com/bunkerity/bunkerized-nginx/tree/master/examples" rel="noopener noreferrer"&gt;compose examples&lt;/a&gt; that may meet your use case&lt;/li&gt;
&lt;li&gt;Discover all the &lt;a href="https://github.com/bunkerity/bunkerized-nginx#list-of-environment-variables" rel="noopener noreferrer"&gt;environment variables&lt;/a&gt; to tweak bunkerized-nginx according to your needs&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>showdev</category>
      <category>security</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
