<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[traefik - fe84]]></title><description><![CDATA[> notes to self _]]></description><link>https://blog.foureight84.com/</link><image><url>https://blog.foureight84.com/favicon.png</url><title>traefik - fe84</title><link>https://blog.foureight84.com/</link></image><generator>Ghost 4.8</generator><lastBuildDate>Sat, 11 Apr 2026 20:15:15 GMT</lastBuildDate><atom:link href="https://blog.foureight84.com/tag/traefik/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[DIY Home Automation (Part 1)]]></title><description><![CDATA[Home automation with Zigbee, MQTT, and Home Assistant using Docker.]]></description><link>https://blog.foureight84.com/home-automation/</link><guid isPermaLink="false">629f57d887242e000198048b</guid><category><![CDATA[automation]]></category><category><![CDATA[zigbee]]></category><category><![CDATA[traefik]]></category><category><![CDATA[docker]]></category><category><![CDATA[home assistant]]></category><category><![CDATA[tasmota]]></category><dc:creator><![CDATA[foureight84]]></dc:creator><pubDate>Thu, 09 Jun 2022 19:50:25 GMT</pubDate><media:content url="https://blog.foureight84.com/content/images/2022/06/ha-logo-pretty.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.foureight84.com/content/images/2022/06/ha-logo-pretty.svg" alt="DIY Home Automation (Part 1)"><p>I&apos;ve been using Philips Hue lightbulbs in my house for a few years. The hardware has been reliable. The software on the other hand is not the best. Being tied to a mobile app as the only source of control can be cumbersome. While my Philips Hue bulbs are also connected to Google Home, I don&apos;t have one set up in every room of the house. Plus, the Philips Hue app is lackluster when it comes to making automation rules. Most of the time the GPS-based triggers do not work properly.</p><p>I&apos;ve also been wanting to create more home automation &#x2013; especially with my lights. Being able to dim or turn off the lights completely when no one is in the room is extremely useful and can save a few dollars on the electricity bill. Buying a Philips Hue motion sensor is an option but they are quite expensive ($45-65USD). There are many other cheaper options available but that would require buying another gateway and maybe even a whole set of new lights since there&apos;s a lack of cross-brand support.</p><p>The IoT market is very segmented. At the lowest level, there are several competing wireless protocols available; Zigbee, Z-Wave, Lora, and WiFi to name a few. Sticking with one protocol also presents compatibility issues directly resulting from proprietary implementation across different brands. A Philips Hue hub/bridge will work with Hue lightbulbs and a handful of partnered brands. Even with partner brand support, there&apos;s a high chance of limited features when mixing. A typical off-the-shelf smart home today means multiple proprietary hardware and cloud services that do not guarantee direct integration with one another. This makes for a very expensive setup and requires looking for workarounds and expensive third-party services to connect them all, like Google Home and Samsung Smarthings. Luckily, Home Assistant falls into the cost effective solution if you&apos;re willing to put in the work to set it up. </p><p>With an underutilized thin-client acting as a <a href="https://blog.foureight84.com/swarm-your-pihole/">local DNS and Adblock (Pi-hole)</a> server, Home Assistant seems like the perfect solution to all of the above-mentioned issues by eliminating the need to buy into different IoT ecosystems. Home Assistant not only acts as a unifying abstraction layer, but it also has a large community-driven set of tools and plugins to accomplish tasks such as creating automation rules for supported devices.</p><h3 id="getting-started">Getting Started</h3><figure class="kg-card kg-image-card kg-card-hascaption"><a href="https://blog.foureight84.com/content/images/2022/06/Zigbee-Home-Assistant-2.svg"><img src="https://blog.foureight84.com/content/images/2022/06/Zigbee-Home-Assistant-2.svg" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1443" height="703"></a><figcaption>IoT stack typology</figcaption></figure><p><strong>Bill of Materials</strong></p><ul><li><strong>Zigbee enabled devices</strong> (pre-existing or just to test). e.g. Light bulbs, motion sensors, temperature sensors, etc.</li><li><strong>Zigbee coordinator</strong>. This could be a USB-dongle like the <a href="https://www.phoscon.de/en/conbee2">ConBee II</a>, or <a href="https://sonoff.tech/product/diy-smart-switch/sonoff-dongle-plus/">SONOFF Zigbee 3.0</a>. For this project, I chose the <a href="https://sonoff.tech/product/smart-home-security/zbbridge/">Sonoff ZBBridge</a>. At the time of writing, the <a href="https://itead.cc/product/sonoff-zigbee-bridge-pro/">Pro</a> version of the Sonoff ZBBridge was released a few weeks ago (it supports up to 128 devices). </li><li><strong>(Optional) <a href="https://www.amazon.com/gp/product/B07K76Q2DX">FTDI Programmer</a></strong>. Necessary if you want to use the Sonoff ZBBridge route to load a custom firmware called <a href="https://tasmota.github.io/docs/">Tasmota</a>.</li><li><strong>A dedicated server with Docker installed</strong>. This can be a Rapsberry Pi or an old computer. The idea is to reduce power consumption, so low-powered is important. The Dell Wyse 5070 thin client I am using has a Pentium Silver J5005 which only consumes roughly 10W max. If you are planning on using a Raspberry Pi, then the <a href="https://www.home-assistant.io/installation/raspberrypi/">Home Assistant Pi image</a> is better suited than a Docker setup (you can still use the configuration files in this guide).</li><li>If you&apos;re using an Intel based system, I highly recommend <a href="https://clearlinux.org/downloads">Intel Clear Linux Server</a>. It&apos;s highly optimized for Intel CPUs.</li><li><strong>Reference</strong>: <a href="https://zigbee.blakadder.com/">https://zigbee.blakadder.com/</a> is a great place to check device support for Zigbee2MQTT or ZHA (alternative Zigbee integration for Home Assistant).</li></ul><p>I chose to use the Sonoff ZBBridge instead of the USB Zigbee dongle because my server is sitting in a closet at one end of the house. While Zigbee is a mesh protocol, I wasn&apos;t too sure if there would be a strong signal to the first device. Plus, having an untethered coordinator makes it easier to place it almost anywhere in the house.</p><p>Sonoff ZBBridge is an ESP MCU based controller that&apos;s shipped with Sonoff&apos;s firmware for their IoT managed solution. Thankfully there are pin-outs on the board that allows for reflashing. You can either choose <a href="https://github.com/thegroove/esphome-zbbridge">ESPHome</a> or <a href="https://tasmota.github.io/docs/">Tasmota</a>. I went with Tasmota. </p><!--kg-card-begin: html--><br><!--kg-card-end: html--><p><strong>Follow the guides below to flash your Sonoff ZBBridge &#xA0;before proceeding:</strong></p><ul><li><strong>Sonoff ZBBridge</strong> <a href="https://zigbee.blakadder.com/Sonoff_ZBBridge.html">Tasmota flashing guide</a></li><li><strong>Sonoff ZBBridge Pro</strong> <a href="https://notenoughtech.com/home-automation/tasmota-on-sonoff-zb-bridge-pro/">Tasmota flashing guide</a> (source via <a href="https://github.com/arendst/Tasmota/discussions/14419">Github</a>)</li></ul><!--kg-card-begin: markdown--><blockquote>
<p>Tasmota flashing and setup are required before proceeding.</p>
</blockquote>
<!--kg-card-end: markdown--><p>Flashing will be a two step process: 1) Flash the ESP MCU with Tasmota 2) Flash a custom Zigbee module firmware once Tasmota is up and running. Lastly, remember to follow the guide&apos;s configuration template to set it up for <strong>Zigbee2Tasmota</strong>. ZHA (Home Assistant Zigbee plugin) is another alternative that provides a direct connection without requiring an MQTT broker such as Eclipse Mosquitto. However, from my experience, ZHA has less device support and a bit complicated to custom add new devices.</p><!--kg-card-begin: html--><br><!--kg-card-end: html--><p>Once you&apos;ve completed the step above:</p><ul><li>Make note of your Tasmota Sonoff ZBBridge&apos;s IP address.</li><li>Update your router&apos;s DHCP settings to make the IP address static for the Tasmota Sonoff ZBBridge. Without this configuration, your setup will break when Tasmota&apos;s IP address changes.</li></ul><!--kg-card-begin: html--><br><!--kg-card-end: html--><p>On your server, clone the project template:</p><pre><code class="language-bash">git clone https://github.com/foureight84/ha_zigbee_docker.git &amp;&amp; cd ha_zigbee_docker</code></pre><!--kg-card-begin: markdown--><h4 id="docker">Docker</h4>
<!--kg-card-end: markdown--><p>Templates repository is located here: <a href="https://github.com/foureight84/ha_zigbee_docker">https://github.com/foureight84/ha_zigbee_docker</a></p><p>If you are already using Traefik then modifications will need to be made before running the docker-compose.yaml / docker-swarm.yaml. The same applies to importing the templates into Portainer.</p><p>The scaffold Docker volumes folders adhere to &quot;iot&quot; as the service name for the docker instances. If you wish to use a different name, make sure to edit the foler name prefix accordingly.</p><!--kg-card-begin: markdown--><h4 id="docker-swarm-setup">Docker Swarm Setup</h4>
<!--kg-card-end: markdown--><p><a href="#docker-standalone-setup">Skip to the next section if you&apos;re using standalone Docker.</a></p><ul><li>Create &quot;traefik&quot; overlay network</li></ul><pre><code>docker network create --driver=overlay --attachable --subnet=48.84.0.0/16 --gateway=48.84.0.1 traefik</code></pre><!--kg-card-begin: markdown--><blockquote>
<p>Make sure to update <code>iot_homeassistant\_data\configuration.yaml</code> if you set a different subnet for the &quot;traefik&quot; network. This is necessary to access Home Assistant&apos;s web UI.</p>
</blockquote>
<!--kg-card-end: markdown--><ul><li>Update <code>iot_zigbee2mqtt\_data\configuration.yaml</code> with your Tasmota Sonoff ZBBridge&apos;s IP address</li></ul><pre><code class="language-yaml">serial:
  port: tcp://&lt;&lt;tasmota ip address&gt;&gt;:8888 #update to match your static ip for Tasmota Sonoff ZBBridge
  adapter: ezsp</code></pre><ul><li>Copy configuration to docker volumes storage location:</li></ul><pre><code class="language-bash">sudo cp -a iot_* /var/lib/docker/volumes/</code></pre><ul><li>Run the Home Assistant stack:</li></ul><pre><code>docker stack deploy -c docker-swarm.yaml iot</code></pre><!--kg-card-begin: markdown--><blockquote>
<p>Stack name needs to match volumes folders&apos; prefix &quot;iot_&quot;. Rename volumes folder if you wish to use a different stack name.</p>
</blockquote>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h4 id="docker-standalone-setup">Docker Standalone Setup</h4>
<!--kg-card-end: markdown--><p><a href="#dns">Ignore this step if you are using Docker Swarm.</a></p><ul><li>Update <code>iot_zigbee2mqtt\_data\configuration.yaml</code> with your Tasmota Sonoff ZBBridge&apos;s IP address</li></ul><pre><code class="language-yaml">serial:
  port: tcp://&lt;&lt;tasmota ip address&gt;&gt;:8888 #update to match your static ip for Tasmota Sonoff ZBBridge
  adapter: ezsp</code></pre><ul><li>Copy configuration to docker volumes storage location:</li></ul><pre><code class="language-bash">sudo cp -a iot_* /var/lib/docker/volumes/</code></pre><ul><li>Run the Home Assistant stack:</li></ul><pre><code class="language-bash">docker-compose -p iot up -d</code></pre><!--kg-card-begin: markdown--><h4 id="dns">DNS</h4>
<!--kg-card-end: markdown--><p>You will need to create DNS entries in your router to access the running services. For my instance, 192.168.1.2 is my Docker server and these are my router DNS records:</p><pre><code class="language-hosts">192.168.1.2 traefik.home
192.168.1.2 home-assistant.home
192.168.1.2 node-red.home
192.168.1.2 zigbee2mqtt.home</code></pre><!--kg-card-begin: markdown--><h4 id="home-assistant-initial-setup">Home Assistant Initial Setup</h4>
<!--kg-card-end: markdown--><ul><li>Browse to <code>http://home-assistant.home</code> and create your account. At the end of the account creation wizard, you should see a screen similar similar to this:</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="468" height="354"></figure><ul><li>Click on <code>mqtt</code> and <code>mosquitto</code> as the broker and submit. You should get a &quot;Success&quot; confirmation. Instead of using the Docker IP for the Eclipse Mosquitto container, we are providing it with the hostname instead.</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-1.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="486" height="439"></figure><!--kg-card-begin: markdown--><h4 id="installing-hacs-home-assistant-community-store">Installing HACS (Home Assistant Community Store)</h4>
<!--kg-card-end: markdown--><p>HACS (Home Assistant Community Store) as the name suggests, this is a repository of community developed plugins for Home Assistant. While there are well maintained plugins, they are unofficially supported. Be aware of this when installing any plugin as it may cause unwanted behaviors with Home Assistant.</p><!--kg-card-begin: html--><br><!--kg-card-end: html--><p>We will need HACS in order to complete the Node-RED integration.</p><!--kg-card-begin: markdown--><blockquote>
<p>A <a href="https://github.com">Github</a> account is required to install HACS.</p>
<p><strong>Why?</strong></p>
<p>HACS uses the GitHub API to gather information about all available and downloaded repositories. This API is rate limited to 60 requsets every hour for unauthenticated requests, which is not enough. So HACS needs to make authenticated requests to that API. (<a href="https://hacs.xyz/docs/faq/github_account#:~:text=HACS%20uses%20the%20GitHub%20API,authenticated%20requests%20to%20that%20API.">source</a>)</p>
</blockquote>
<!--kg-card-end: markdown--><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://hacs.xyz/docs/setup/download"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Download | HACS</div><div class="kg-bookmark-description">HACS download steps</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://hacs.xyz/favicon.ico" alt="DIY Home Automation (Part 1)"><span class="kg-bookmark-author">HACS</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://assets.hacs.xyz/logo.svg" alt="DIY Home Automation (Part 1)"></div></a></figure><ul><li>You&apos;ll need to go inside the Home Assistant container:</li></ul><pre><code class="language-bash">docker exec -it $(docker ps -q -f name=iot_homeassistant) bash</code></pre><ul><li>Once inside the Home Assistant container:</li></ul><pre><code class="language-bash">wget -O - https://get.hacs.xyz | bash -</code></pre><ul><li>Restart Home Assistant from the web UI (http://home-assistant.home) by going to <code>Settings &gt; System &gt; Restart</code>.</li></ul><!--kg-card-begin: html--><br><!--kg-card-end: html--><ul><li>After Home Assistant restarts, complete the installation by adding the HACS integration. To do so, go to <code>Settings &gt; Device &amp; Services &gt; + Add Integration</code> and type <code>HACS</code>. You will need to acknowledge all the checkboxes and follow the instruction to add HACS to your Github account.</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-2.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="626" height="467" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-2.png 600w, https://blog.foureight84.com/content/images/2022/06/image-2.png 626w"></figure><p>You will see <code>HACS</code> as one of the left-menu items in the Home Assistant web UI.</p><!--kg-card-begin: markdown--><h4 id="setting-up-node-red-for-creating-automation-rules">Setting up Node-RED for creating Automation Rules</h4>
<!--kg-card-end: markdown--><p>Node-RED is a flow-based development tool for visual programming. We will be installing specific a community developed &quot;Palette&quot; for Home Assistant.</p><ul><li>From the left-menu in the Home Assistant web UI, click on <code>Node Red</code>.</li></ul><!--kg-card-begin: markdown--><blockquote>
<p>Node Red and Zigbee2MQTT menu items are custom added via the Home Assistant <code>configuration.yaml</code>. <a href="https://www.home-assistant.io/integrations/panel_iframe/">iframe Panel documentation</a><br>
These are essentially iframe links to our Node-RED and Zigbee2MQTT web UI instances.</p>
</blockquote>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-3.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1177" height="686" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-3.png 600w, https://blog.foureight84.com/content/images/size/w1000/2022/06/image-3.png 1000w, https://blog.foureight84.com/content/images/2022/06/image-3.png 1177w" sizes="(min-width: 720px) 720px"></figure><ul><li>Access the &quot;Palette Manager&quot; by pressing <code>alt + shift + p</code> or go to the hamburger menu on the top right of the iframe then choose <code>Manage palette</code>.</li><li>Click on the <code>Install</code> tab and search for <code>home-assistant</code> and look for <code>node-red-contrib-home-assistant-websocket</code>.</li><li>After the palette installs, scroll to the bottom of the Node-RED nodes list on the left and you should see the <code>home assistant</code> section with all of the associated nodes.</li><li>Drag the &apos;API&apos; node into the flow workspace and double-click to edit its properties.</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-4.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1398" height="696" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-4.png 600w, https://blog.foureight84.com/content/images/size/w1000/2022/06/image-4.png 1000w, https://blog.foureight84.com/content/images/2022/06/image-4.png 1398w" sizes="(min-width: 720px) 720px"></figure><ul><li>Open a new browser tab and head to your Home Assistant web UI (http://home-assistant.home). We will be creating a long-lived token for Node-RED to connect with HA. Click on your profile on the left-menu and scroll to the bottom. Click <code>Create Token</code> and call it <code>Node RED</code>. Copy the entire token string that should look like this: <code>eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJlNmY1Nzk5YjAzNjg0MjY1ODRkYTc5Yjc0YTVhMTI1ZCIsImlhdCI6MTY1NDgwMTM4NiwiZXhwIjoxOTcwMTYxMzg2fQ.vjbD8T378Da7nMzgAKotVbzMd-77pAVGI6c7wfcKf6U</code></li><li>Go back to the HA tab with Node-RED opened with the API node properties menu. Click to add new server. Fill in <code>http://home-assistant:8123</code> for Base URL field and paste your access token.</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-5.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1151" height="704" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-5.png 600w, https://blog.foureight84.com/content/images/size/w1000/2022/06/image-5.png 1000w, https://blog.foureight84.com/content/images/2022/06/image-5.png 1151w" sizes="(min-width: 720px) 720px"></figure><ul><li>After the server has been added, the API node can be deleted. Make sure to click <code>Deploy</code> to save your configuration.</li></ul><!--kg-card-begin: html--><br><!--kg-card-end: html--><p>You&apos;re all set to create automation rules.</p><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-8.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1339" height="1005" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-8.png 600w, https://blog.foureight84.com/content/images/size/w1000/2022/06/image-8.png 1000w, https://blog.foureight84.com/content/images/2022/06/image-8.png 1339w" sizes="(min-width: 720px) 720px"></figure><!--kg-card-begin: markdown--><h4 id="pairing-new-zigbee-devices">Pairing New Zigbee Devices</h4>
<!--kg-card-end: markdown--><ul><li>In your HA web UI, click on the <code>Zigbee2MQTT</code>. By default via the <code>iot_zigbee2mqtt\_data\configuration.yaml</code> all Zigbee devices in pairing mode will be allowed to join. This can disabled from the Zigbee2MQTT (top-right button).</li><li>Put your device into pairing Mode. Depending on the device, it will either be holding down the <code>reset</code> button on the device or turning a switch on and off in combination for light bulbs. See manufacturer instructions for details.</li></ul><!--kg-card-begin: html--><br><!--kg-card-end: html--><p>You will see the device show up in Zigbee2MQTT after a few seconds after entering pairing mode. You&apos;ll want to name the device appropriately.</p><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-6.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1333" height="793" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-6.png 600w, https://blog.foureight84.com/content/images/size/w1000/2022/06/image-6.png 1000w, https://blog.foureight84.com/content/images/2022/06/image-6.png 1333w" sizes="(min-width: 720px) 720px"></figure><p>These devices should also appear in Home Assistant under the <code>Settings &gt; Devices &amp; Services &gt; mosquitto MQTT</code>.</p><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2022/06/image-7.png" class="kg-image" alt="DIY Home Automation (Part 1)" loading="lazy" width="1335" height="794" srcset="https://blog.foureight84.com/content/images/size/w600/2022/06/image-7.png 600w, https://blog.foureight84.com/content/images/size/w1000/2022/06/image-7.png 1000w, https://blog.foureight84.com/content/images/2022/06/image-7.png 1335w" sizes="(min-width: 720px) 720px"></figure><p></p><p>Home Assistant also has an Android and iOS companion app that provides additional tracking such as your location. All of this data is fed to your local instance allowing for GPS based automation rules such as turn the lights on when coming home at night, or setting up motion and time based light triggering.</p><p>In the next guides, I&apos;ll walk through WireGuard VPN setup to maintain a tunnel to your home network to access Home Assistant without exposing it to the public internet. </p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Pi-Hole Recursive DNS with Unbound]]></title><description><![CDATA[Deploying Unbound recursive DNS server locally with Pi-Hole using Docker]]></description><link>https://blog.foureight84.com/pi-hole-recursive-dns/</link><guid isPermaLink="false">61bb93cf0a679a00014c664d</guid><category><![CDATA[adblocking]]></category><category><![CDATA[pihole]]></category><category><![CDATA[unbound]]></category><category><![CDATA[recursive dns]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[swarm]]></category><category><![CDATA[traefik]]></category><dc:creator><![CDATA[foureight84]]></dc:creator><pubDate>Thu, 16 Dec 2021 20:42:08 GMT</pubDate><media:content url="https://blog.foureight84.com/content/images/2021/12/Unbound_FC_Shaded_cropped.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.foureight84.com/content/images/2021/12/Unbound_FC_Shaded_cropped.svg" alt="Pi-Hole Recursive DNS with Unbound"><p>In the previous post, I wrote an extensive guide on <a href="https://blog.foureight84.com/swarm-your-pihole">deploying Cloudflare as the upstream DNS for Pi-Hole over HTTPS</a>. This is a follow-up where Cloudflare is replaced with <a href="https://www.nlnetlabs.nl/projects/unbound/about/">Unbound</a> as the upstream DNS server. </p><p>Unbound is a recursive DNS that sits between Pi-Hole and authoritative DNS servers. Cloudflare&apos;s 1.1.1.1 and Google&apos;s 8.8.8.8 are examples of recursive DNS services. By making Unbound the upstream DNS server for Pi-Hole, you&apos;re cutting out other third parties from tracking your web presence. A more detailed read-up of this setup can be found on the official <a href="https://docs.pi-hole.net/guides/dns/unbound/">Pi-Hole Unbound guide</a>.</p><p>Back on June 11, 2021, Cloudflare DNS experienced outages in the Los Angeles and Chicago area. The result was over an hour of downtime with its DNS service. I was able to avoid that outage by switching over to Unbound and letting it handle domain resolution directly with authoritative DNS servers. This method can be a little slow but DNS caching in Pi-Hole becomes beneficial on subsequent lookups.</p><h2 id="deploying-unbound-with-pi-hole">Deploying Unbound with Pi-Hole</h2><p>In the previous post, Pi-Hole and Cloudflare DNS were deployed using Docker Swarm and managed through Portainer with Traefik as the reverse proxy. This will follow the previous guide closely. Let&apos;s start by cloning the project:</p><pre><code class="language-bash">git clone https://github.com/foureight84/traefik-pihole-doh.git &amp;&amp; cd traefik-pihole-doh</code></pre><p>This guide assumes that your Docker Swarm, Portainer, and Traefik have been properly configured. If not, <a href="https://blog.foureight84.com/swarm-your-pihole/#getting-started">follow this guide</a>.</p><p>Go to your Portainer web portal and click on App Templates -&gt; Custom Templates and click on the &quot;+ Add Custom Template&quot; button.</p><!--kg-card-begin: markdown--><blockquote>
<p>This stack uses Unbound Docker image created by Kyle Harding (<a href="https://github.com/klutchell">https://github.com/klutchell</a>)<br>
Image: <a href="https://hub.docker.com/r/klutchell/unbound">https://hub.docker.com/r/klutchell/unbound</a><br>
Github: <a href="https://github.com/klutchell/unbound-docker">https://github.com/klutchell/unbound-docker</a></p>
</blockquote>
<!--kg-card-end: markdown--><p>You&apos;ll need to fill in a relevant title for the template. I called mine <code>recursive_dns</code>. Add a description - <code>Pi-hole and Unbound</code>. Make sure the template Type is set to <code>Swarm</code>. Then click on the Upload option and choose the <code>docker-compose.yaml</code> in the <code>dns-unbound</code> folder in the cloned project.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/12/Pi-hole-Unbound-Portainer.PNG" class="kg-image" alt="Pi-Hole Recursive DNS with Unbound" loading="lazy" width="1406" height="1002" srcset="https://blog.foureight84.com/content/images/size/w600/2021/12/Pi-hole-Unbound-Portainer.PNG 600w, https://blog.foureight84.com/content/images/size/w1000/2021/12/Pi-hole-Unbound-Portainer.PNG 1000w, https://blog.foureight84.com/content/images/2021/12/Pi-hole-Unbound-Portainer.PNG 1406w" sizes="(min-width: 720px) 720px"><figcaption>Uploading dns-unbound/docker-compose.yaml as a Swarm template</figcaption></figure><!--kg-card-begin: markdown--><p><s>After it has been uploaded, find the newly created custom template in the list of templates and click edit.<br>
We will need to check that <code>PIHOLE_DNS_=172.18.0.1#5053</code> environment variable matches your <code>docker_gwbridge</code> IPV4 IPAM Gateway address. Once verified, deploy the stack. That&apos;s it!</s></p>
<p>Deploy the stack once the custom template has been uploaded. The <code>klutchell/unbound</code> Docker image now listens on port 53 by default. Setting the <code>PIHOLE_DNS</code> environment variable to the <code>unbound</code> service name is all that&apos;s needed.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: html--><aside class="note">Make sure you&apos;re only running one instance of Pi-Hole. If you are running Pi-Hole with Cloudflare from the previous guide, be sure to remove that stack before deploying this stack.</aside><!--kg-card-end: html--><p>While uncached DNS queries may be slower than using Google&apos;s public DNS (8.8.8.8) we can see that Pi-Hole&apos;s caching outpaces all other public DNS services by far. Plus the millisecond differences in uncached queries are not noticeable in a real use case scenario. It&apos;s actually faster than using Cloudflare!</p><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2021/12/image.png" class="kg-image" alt="Pi-Hole Recursive DNS with Unbound" loading="lazy" width="596" height="928"></figure><pre><code>  192.168.  1.  4 |  Min  |  Avg  |  Max  |Std.Dev|Reliab%|
  ----------------+-------+-------+-------+-------+-------+
  + Cached Name   | 0.000 | 0.001 | 0.001 | 0.000 | 100.0 |
  + Uncached Name | 0.015 | 0.060 | 0.187 | 0.052 | 100.0 |
  + DotCom Lookup | 0.015 | 0.049 | 0.081 | 0.022 | 100.0 |
  ---&lt;O-OO----&gt;---+-------+-------+-------+-------+-------+
                     pihole.home
                Local Network Nameserver


    1.  1.  1.  1 |  Min  |  Avg  |  Max  |Std.Dev|Reliab%|
  ----------------+-------+-------+-------+-------+-------+
  - Cached Name   | 0.012 | 0.013 | 0.018 | 0.001 | 100.0 |
  - Uncached Name | 0.014 | 0.069 | 0.355 | 0.077 | 100.0 |
  - DotCom Lookup | 0.014 | 0.022 | 0.048 | 0.009 | 100.0 |
  ---&lt;--------&gt;---+-------+-------+-------+-------+-------+
                     one.one.one.one
                    CLOUDFLARENET, US
                    
    8.  8.  8.  8 |  Min  |  Avg  |  Max  |Std.Dev|Reliab%|
  ----------------+-------+-------+-------+-------+-------+
  - Cached Name   | 0.012 | 0.015 | 0.023 | 0.002 | 100.0 |
  - Uncached Name | 0.014 | 0.038 | 0.158 | 0.040 | 100.0 |
  - DotCom Lookup | 0.014 | 0.016 | 0.025 | 0.002 | 100.0 |
  ---&lt;--------&gt;---+-------+-------+-------+-------+-------+
                       dns.google
                       GOOGLE, US</code></pre>]]></content:encoded></item><item><title><![CDATA[Swarm Your Pi-hole]]></title><description><![CDATA[Deploy Pi-hole with DNS-over-HTTPS using Docker Swarm and load balance using Traefik]]></description><link>https://blog.foureight84.com/swarm-your-pihole/</link><guid isPermaLink="false">60ef44ce941c380001abbe8c</guid><category><![CDATA[docker]]></category><category><![CDATA[swarm]]></category><category><![CDATA[pihole]]></category><category><![CDATA[adblocking]]></category><category><![CDATA[dns-over-https]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[traefik]]></category><category><![CDATA[load balance]]></category><dc:creator><![CDATA[foureight84]]></dc:creator><pubDate>Fri, 16 Jul 2021 20:20:22 GMT</pubDate><media:content url="https://blog.foureight84.com/content/images/2021/07/91841822-4a3a5900-ec53-11ea-92fe-4bde2acccac4-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.foureight84.com/content/images/2021/07/91841822-4a3a5900-ec53-11ea-92fe-4bde2acccac4-1.png" alt="Swarm Your Pi-hole"><p>I&apos;ve been using Pi-hole as a whole network ad blocker for a while now and it&apos;s been great. The only mistake I made the first time was using it as a standalone docker instance. Whenever I perform a manual update to a newer release, there would be a few minutes of internet downtime. Personally, it&apos;s not a big deal and I could just force a DHCP-renew. But I share my internet connection with my parents living next door and an internet outage immediately leads to a phone call.</p><p>There are various ways to update a running Docker container and minimize downtime, and I&apos;ve chosen to update my stack to use Docker Swarm to accomplish this goal. Yes, the setup is overkill for a home network, but making things causal is always better down the road when you need to make changes.</p><p>I am currently using a J5005 Dell Wyse 5070 thin client as my server, but this article should apply to a Raspberry Pi. You should take a look at the Docker images used and swap them for ARM-compatible.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/dns_stack_topology.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="2000" height="732" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/dns_stack_topology.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/dns_stack_topology.png 1000w, https://blog.foureight84.com/content/images/size/w1600/2021/07/dns_stack_topology.png 1600w, https://blog.foureight84.com/content/images/2021/07/dns_stack_topology.png 2220w" sizes="(min-width: 720px) 720px"><figcaption>DNS Typology</figcaption></figure><!--kg-card-begin: markdown--><blockquote>
<p><strong>Disclaimer</strong>: This is meant for home use only. DO NOT deploy this in a Production environment. Pi-hole uses SQLite and concurrent write is not supported. While DNS resolution and blocking won&apos;t have issues, there will be loss of log data if two or more swarm nodes are writing to DB at the same time. Also, make sure your router is properly configured to not expose your DNS to the public internet. It will crash and burn.</p>
</blockquote>
<!--kg-card-end: markdown--><h3 id="stack-overview">Stack Overview</h3><!--kg-card-begin: markdown--><ul>
<li>Management Stack (mgmt)
<ul>
<li>Traefik - reverse proxy and load balancer</li>
<li>Portainer - Web UI Docker management tool</li>
<li>Whoami - Tiny Go webserver that prints os information and HTTP request to output</li>
</ul>
</li>
<li>DNS Stack (dns)
<ul>
<li>Cloudflared DoH Proxy</li>
<li>Pi-hole DNS adblocker and DHCP server</li>
</ul>
</li>
</ul>
<!--kg-card-end: markdown--><h3 id="a-few-details">A few Details</h3><p><a href="https://doc.traefik.io/traefik/">Traefik</a> is a GoLang reverse proxy and load-balancer with built-in support for Let&apos;s Encrypt. In my earlier post about using <a href="https://blog.foureight84.com/deploying-ghost-on-linode-with-cheap-remote-backup-using-terraform/">Terraform to deploy this Ghost blog</a>, I used <a href="https://hub.docker.com/r/jwilder/nginx-proxy">jwilder/nginx-proxy</a> along with <a href="https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion/">jrcs/letsencrypt-nginx-proxy-companion</a> to serve as a reverse-proxy and automatic SSL certificate handling. However, that setup is on a Docker standalone deployment using Docker Compose. While it is possible to use an Nginx reverse-proxy with Docker Swarm, Traefik is a much better fit with Docker Swarm with fewer configurations involved.</p><p><a href="https://www.portainer.io/products/community-edition">Portainer</a> is a container management tool with a web UI. It&apos;s used in this project to manage the DNS swarm, which makes scaling and service updates more casual. I personally prefer this to keep the project simple and doesn&apos;t require looking up Docker CLI commands.</p><p><a href="https://pi-hole.net/">Pi-hole</a>, the main reason for this project, is a Linux based DNS server with built-in DHCP support. The main use for Pi-hole is to block advertisement domains, but it also has additional benefits in blocking known malware and phishing domains as well. As it is a DNS server, it can be used to apply to an entire network.</p><h3 id="getting-started">Getting Started</h3><p>We&apos;ll first need to clone the project</p><pre><code class="language-bash">git clone https://github.com/foureight84/traefik-pihole-doh.git &amp;&amp; cd traefik-pihole-doh</code></pre><p>You&apos;ll need to enable Docker swarm on your host if not already.</p><pre><code class="language-bash">docker swarm init</code></pre><p>We will need to create a Docker overlay network called <code>traefik</code>. Additional Docker services you choose to add later that require the use of Traefik will need to be attached to this network. </p><pre><code class="language-bash">docker network create --driver=overlay --attachable traefik</code></pre><p>Now we spawn the <code>mgmt</code> stack and use Portainer to deploy and maintain swarms from here on out.</p><pre><code class="language-bash">docker stack deploy -c mgmt/docker-compose.yaml mgmt</code></pre><p>If your server is running Ubuntu &gt;= 18.04, chances are, systemd-resolved is probably occupying port 53. <a href="#q-how-do-i-deal-with-the-port-53-conflict-error-with-traefik-container">We&apos;ll need to turn that off.</a></p><!--kg-card-begin: html--><aside class="note">Hostnames are tagged under the &apos;label:&apos; properties in the docker-compose files.</aside><!--kg-card-end: html--><p>Update your <code>hosts</code> file with the hostnames for the running web services. Windows: <code>C:\Windows\System32\drivers\etc\hosts</code>, Linux/Mac: <code>/etc/hosts/</code>. For my setup, my home network has the domain of <code>.home</code>. You will need to change this for your setup. <code>192.x.x.x</code> denotes the server this docker stack is currently running on.</p><figure class="kg-card kg-code-card"><pre><code>192.x.x.x	portainer.home
192.x.x.x	traefik.home
192.x.x.x	whoami.home
192.x.x.x	pihole.home</code></pre><figcaption>Add these static hostnames to your router once verified that everything is working</figcaption></figure><p>Traekfik dashboard is available via <code>http://traefik.home/local/dashboard/</code> don&apos;t forget the <code>/</code> at the end. You should see entry points for port 80 as well as 53 tcp and udp.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-3.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1402" height="1058" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-3.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-3.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-3.png 1402w" sizes="(min-width: 720px) 720px"><figcaption>Traefik dashboard</figcaption></figure><p>Go to Portainer via <code>http://portainer.home</code> and create your admin account. Once logged in, we will need to create a Docker Secret that will hold the web password for Pi-Hole web ui. The secret needs to be named <em><code>pihole_webpw</code>.</em></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/portainer_secrets.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="988" height="743" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/portainer_secrets.png 600w, https://blog.foureight84.com/content/images/2021/07/portainer_secrets.png 988w" sizes="(min-width: 720px) 720px"><figcaption>Create a Docker Secret named pihole_webpw with your Pi-hole web password.</figcaption></figure><p>Make note of the <code>docker_gwbridge</code> network&apos;s gateway IPV4. This is used to forward DNS requests to the upstream Cloudflared DoH docker container. We can&apos;t use the IP the container gets assigned on the traefik network since that is not static.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/portainer_network_list.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1203" height="747" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/portainer_network_list.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/portainer_network_list.png 1000w, https://blog.foureight84.com/content/images/2021/07/portainer_network_list.png 1203w" sizes="(min-width: 720px) 720px"><figcaption>Portainer network list</figcaption></figure><p>Open the <code>docker-compose.yaml</code> in the <code>dns</code> folder with a text editor and update the <code>DNS1</code> field with your <code>docker_gwbridge</code>&apos;s IP address.</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">environment:
      - TZ=America/Los_Angeles
      - DNS1=172.18.0.1#5054 #replace with docker_gwbridge&apos;s gateway ip
      - DNS2=no
      - REV_SERVER=true
      - REV_SERVER_CIDR=192.168.1.0/24 #Update these fields to match your environment
      - REV_SERVER_TARGET=192.168.1.1
      - REV_SERVER_DOMAIN=home
      - WEBPASSWORD_FILE=/run/secrets/pihole_webpw</code></pre><figcaption>dns/docker-compose.yaml pihole service environment variables</figcaption></figure><p>The <code>REV_*</code> environment variables should also be updated to match your setup as well. <code>REV_SERVER</code> and related fields allow Pi-Hole to perform a reverse DNS lookup against the router. I&apos;m currently using my router&apos;s DHCP server (<code>REV_SERVER_TARGET</code>). Static ip and hostnames are kept on the router. Requests for my local NAS for example, will go through Pi-Hole and that will get forwarded to my router.</p><p>After making changes to the dns/docker-compose.yaml file, we will need to upload this to Portainer as a docker-swarm template and deploy the swarm.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/portainer_custom_template.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1209" height="1050" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/portainer_custom_template.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/portainer_custom_template.png 1000w, https://blog.foureight84.com/content/images/2021/07/portainer_custom_template.png 1209w" sizes="(min-width: 720px) 720px"><figcaption>Uploading dns/docker-compose.yaml as a Swarm template</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2021/07/portainer_custom_template_uploaded.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1215" height="531" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/portainer_custom_template_uploaded.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/portainer_custom_template_uploaded.png 1000w, https://blog.foureight84.com/content/images/2021/07/portainer_custom_template_uploaded.png 1215w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/portianer_deploy_pihole.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1210" height="894" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/portianer_deploy_pihole.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/portianer_deploy_pihole.png 1000w, https://blog.foureight84.com/content/images/2021/07/portianer_deploy_pihole.png 1210w" sizes="(min-width: 720px) 720px"><figcaption>Deploying dns stack</figcaption></figure><p>It should take a few minutes for Pi-Hole deployment to complete. Update the DNS on your computer with your server&apos;s IP and test before applying it as the DNS to use on your router. To check if DoH is working properly, head to <a href="https://1.1.1.1/help">https://1.1.1.1/help</a></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-2.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="529" height="828"><figcaption><a href="https://1.1.1.1/help">https://1.1.1.1/help</a></figcaption></figure><h3 id="update-services">Update Services</h3><p>Since we are running in Docker Swarm mode, we can take advantage of rolling updates to minimize downtime. Of course, you need more than one instance of a service running in order to perform a rolling update. </p><p>We first need to change the <code>--update-delay</code> flag on the following services (or any that you want to apply a rolling update):</p><ul><li>Traefik</li><li>Pi-hole</li><li>Cloudflared</li></ul><p>We will use <code>120s</code> (2 minutes) as the delay from one service instance to the next. Pi-Hole and Cloudflare services can take up to 30 seconds to reach ready-state and process new requests. 120 seconds should give us ample time for a new Docker image to download and update the first instance while the other instances remain unchanged and continue to process new requests.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-10.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1252" height="822" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-10.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-10.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-10.png 1252w" sizes="(min-width: 720px) 720px"><figcaption>Service list view. Click on a service to view details and update behavior</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-11.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1255" height="820" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-11.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-11.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-11.png 1255w" sizes="(min-width: 720px) 720px"><figcaption>Service details / Update Configuration section. Change &apos;Update Delay&apos; to 2m or 120s</figcaption></figure><p>In the Service details view, click on <code>Update configuration</code> on the right-hand menu to scroll to the section shown in the image above. <code>Update Delay</code> should be entered as <code>2m</code> or <code>120s</code>.</p><p>To update a service, scroll to the top and click on <code>Update the service</code> and toggle <code>Pull latest image version</code> on the confirmation screen. Now Docker will update each running instance one-by-one 120 seconds apart.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-12.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1250" height="821" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-12.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-12.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-12.png 1250w" sizes="(min-width: 720px) 720px"><figcaption>Updating service</figcaption></figure><p>If you&apos;ve noticed from the Service list view screenshot, I am only running 1 instance for all my services since it&apos;s a home network and I don&apos;t need the redundancy or load balancing at the moment (although I might scale Pi-hole and Cloudflared to 2 instances each as these containers have halted in the past). These services will be scaled to 2 or 3 before performing a service update in order to utilize the rolling update. Once all instances are updated, I will downscale them back to the initial scale.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-13.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1251" height="822" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-13.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-13.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-13.png 1251w" sizes="(min-width: 720px) 720px"><figcaption>Scaling services on the fly before performing a service update in order to take advantage of the rolling update feature of Docker Swarm.</figcaption></figure><p></p><p>Happy adblocking!</p><h2 id="faq">FAQ</h2><h3 id="q-where-can-get-more-blocklists">Q: Where can get more blocklists?</h3><p>Filterlists is a good place to start (<a href="https://filterlists.com/">https://filterlists.com/</a>)</p><!--kg-card-begin: html--><br><!--kg-card-end: html--><h3 id="q-what-the-hell-are-you-on-about">Q: What the hell are you on about?</h3><p>For anyone starting from scratch, the initial steps not mentioned in this guide are:</p><ol><li>Installing Ubuntu server (<a href="https://ubuntu.com/download/server">https://ubuntu.com/download/server</a>), for Raspberry Pi (<a href="https://ubuntu.com/download/raspberry-pi">https://ubuntu.com/download/raspberry-pi</a>)</li><li>Enable SSH after booting into Ubuntu: <code>sudo apt install openssh-server</code>. This will allow remote terminal login to your server via ssh. e.g. <code>ssh your-username@your-server-ip-address</code> from another computer with an SSH client. Windows 10 has SSH built-in or you can use <a href="https://www.putty.org/">PuTTY</a>.</li><li>Installing Docker-CE: <a href="https://docs.docker.com/engine/install/ubuntu/">https://docs.docker.com/engine/install/ubuntu/</a></li></ol><p>You do not need to install Ubuntu for the Rasberry Pi, there&apos;s also Raspian OS. Just make sure to do steps 2 and 3.</p><!--kg-card-begin: html--><br><!--kg-card-end: html--><h3 id="q-how-do-i-deal-with-the-port-53-conflict-error-with-the-traefik-container">Q: How do I deal with the port 53 conflict error with the Traefik container?</h3><p>There are two approaches to this. I will guide based on Ubuntu. You can use this as a guide for your system.<br>First, we need to find out what&apos;s using port 53 and determine if we can stop, or disable it. If you can&apos;t then read further for the alternative.</p><pre><code class="language-bash">sudo netstat -pna | grep 53</code></pre><p>If you&apos;re on Ubuntu 18.04 (I believe) and newer, it will most likely be caused by systemd-resolved.</p><p>If it is then:</p><!--kg-card-begin: markdown--><ol>
<li><code>sudo systemctl stop systemd-resolved</code> to stop the service</li>
<li><code>sudo nano /etc/systemd/resolved.conf</code></li>
<li>Uncomment <code>#DNS=</code> and replace it with our DNS of choice. It shouldn&apos;t matter as this is for your host. I chose cloudflare. It should then look like this <code>DNS=1.1.1.1</code></li>
<li>Uncomment <code>#DNSStubListener=no</code> or add the line if it&apos;s not there.</li>
<li>Save and exit the text editor.</li>
<li><code>sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf</code> creates a symbolic link and replaces the current link in the existing path.</li>
<li>Check that DNS still works by doing a <code>ping github.com</code></li>
<li>If you see an error about <code>sudo: unable to resolve host ubuntu: Name or service not known</code> then edit your <code>hosts</code> file and add <code>127.0.0.1 your-machine-name</code> below <code>127.0.0.1 localhost</code>.</li>
</ol>
<!--kg-card-end: markdown--><p>If you cannot stop the service that&apos;s currently using port 53 then you can update the mgmt stack docker-compose.yaml to use docker&apos;s loopback.</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">traefik:
  image: traefik:latest
  ports:
    - target: 53
      published: 53
      protocol: tcp
      mode: host
    - target: 53
      published: 53
      protocol: udp
      mode: host
    - target: 80
      published: 80
      protocol: tcp
      mode: host</code></pre><figcaption>mgmt/docker-compose.yaml ports expressed in long format</figcaption></figure><p>Unfortunately, IP address format is not supported in long-form port declaration. It will need to change to:</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">traefik:
  image: traefik:latest
  ports:
    - 0.0.0.0:53:53/udp
    - 0.0.0.0:53:53/tcp
    - target: 80
      published: 80
      protocol: tcp
      mode: host</code></pre><figcaption>mgmt/docker-compose.yaml updated ports to listen on docker&apos;s loopback</figcaption></figure><p>A caveat of using this method is that Traefik won&apos;t be able to forward the real IP of the requestor in the request header for <code>X-Forwarded-For</code> and <code>X-Real-Ip</code>. That IP will be a docker NAT IP (test this out using <code>http://whoami.test.local</code>). It&apos;s not important for our purpose, but if you were to deploy another web service that utilizes this then it could be an issue.</p><!--kg-card-begin: html--><br><!--kg-card-end: html--><h3 id="q-pi-hole-client-id-in-the-query-log-only-shows-traefiks-hostname">Q: Pi-Hole client id in the query log only shows Traefik&apos;s hostname</h3><p>When a request comes in through a reverse proxy via HTTP, the request&apos;s originating IP is passed along in the request headers as <code>X-Forwarded-For</code> and <code>X-Real-Ip</code>. However, with DNS, there&apos;s no such flag. There&apos;s been a proposal for DNS <code>X-Proxied-For</code> but that&apos;s not a standard. <a href="https://tools.ietf.org/id/draft-bellis-dnsop-xpf-03.html">https://tools.ietf.org/id/draft-bellis-dnsop-xpf-03.html</a><br>Pi-hole only makes notes of which immediate client sent the request, and in this case, it&apos;s Traefik. If you really want to make this work then you can implement a <a href="https://docs.docker.com/network/macvlan/">macvlan</a> network and attach your Pi-Hole instance(s). This would allow a Docker container to receive an IP on your router&apos;s subnet and allow direct communication.<br>If pi-hole was not in swarm mode then this would not be an issue (this was my previous setup). In swarm mode and behind a load balancer, you would need to allocate a block of IPs to dedicate to the swarm (IP assignment is not supported in swarm mode) while the load balancer would only apply to port 80 traffic to pi-hole&apos;s web UI.</p><p></p><h3 id="q-how-do-i-test-my-adblocking-capability">Q: How do I test my adblocking capability?</h3><p><a href="https://d3ward.github.io/toolz/src/adblock.html"><a href="https://d3ward.github.io/toolz/src/adblock.html">https://d3ward.github.io/toolz/src/adblock.html</a></a> is a good place to start. It should show you whether you are blocking major players on the DNS level.</p><figure class="kg-card kg-image-card"><img src="https://blog.foureight84.com/content/images/2021/07/image-4.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1387" height="1020" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-4.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-4.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-4.png 1387w" sizes="(min-width: 720px) 720px"></figure><p>You could also turn off your browser ad block extension and go to a known site with embedded ads. <a href="https://tweaktown.com">https://tweaktown.com</a> is a good place to test.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-5.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1386" height="1055" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-5.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-5.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-5.png 1386w" sizes="(min-width: 720px) 720px"><figcaption>Without Pi-hole and browser adblocker extension</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-6.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1389" height="1057" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-6.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-6.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-6.png 1389w" sizes="(min-width: 720px) 720px"><figcaption>After Pi-hole is enabled with proper blocklists added</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.foureight84.com/content/images/2021/07/image-7.png" class="kg-image" alt="Swarm Your Pi-hole" loading="lazy" width="1390" height="891" srcset="https://blog.foureight84.com/content/images/size/w600/2021/07/image-7.png 600w, https://blog.foureight84.com/content/images/size/w1000/2021/07/image-7.png 1000w, https://blog.foureight84.com/content/images/2021/07/image-7.png 1390w" sizes="(min-width: 720px) 720px"><figcaption>Pi-hole DNS blocking with browser adblocking extension</figcaption></figure><p>Without a browser Adblock extension, it doesn&apos;t look pretty but it saves on your bandwidth usage since ads do not load at all. Use this in combination with a browser-based adblocker to remove those HTML elements. Without Pi-Hole ads will be hidden with browser adblockers but they would still load.</p>]]></content:encoded></item></channel></rss>