{"id":188,"date":"2022-03-17T20:24:00","date_gmt":"2022-03-18T03:24:00","guid":{"rendered":"https:\/\/jasonsblog.access.ly\/?p=188"},"modified":"2024-01-21T10:00:18","modified_gmt":"2024-01-21T17:00:18","slug":"run-pi-hole-with-unbound-in-docker-on-a-raspberry-pi","status":"publish","type":"post","link":"https:\/\/jasonsblog.ddns.net\/index.php\/2022\/03\/17\/run-pi-hole-with-unbound-in-docker-on-a-raspberry-pi\/","title":{"rendered":"Run Pi-hole with Unbound in Docker on a Raspberry Pi"},"content":{"rendered":"\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/pi-hole.net\/\" data-type=\"URL\" data-id=\"https:\/\/pi-hole.net\/\" target=\"_blank\">Pi-hole<\/a> has to be one of the best things you could run on your home network to protect your privacy and enable advertisement, tracking, and malware site blocking for all the devices on the local network. This is especially helpful for Android phones and tablets where Google makes it difficult to use ad blockers not to mention other network and streaming devices. <\/p>\n\n\n\n<p>And if you add <a href=\"https:\/\/github.com\/NLnetLabs\/unbound\/blob\/master\/README.md\" data-type=\"URL\" data-id=\"https:\/\/github.com\/NLnetLabs\/unbound\/blob\/master\/README.md\" target=\"_blank\" rel=\"noreferrer noopener\">Unbound<\/a> for your upstream validating, recursive, and caching DNS server you get the added protection of privacy from upstream DNS servers that could be logging and tracking every site you visit (<a href=\"https:\/\/jasonsblog.ddns.net\/index.php\/2022\/03\/07\/internet-service-providers-are-logging-everything-you-do-online\/\" target=\"_blank\" rel=\"noreferrer noopener\">See previous post on ISP tracking<\/a>). As a recursive DNS server, Unbound will look for the authoritative DNS server responsible for the site you&#8217;re visiting, giving you added protection from DNS injection attacks on large DNS servers. This makes the first lookup just slightly slower, but it will cache the result making future lookups fast. The <a href=\"https:\/\/docs.pi-hole.net\/guides\/dns\/unbound\/\" data-type=\"URL\" data-id=\"https:\/\/docs.pi-hole.net\/guides\/dns\/unbound\/\" target=\"_blank\" rel=\"noreferrer noopener\">Pi-hole documentation on Unbound<\/a> has a much more detailed explanation to familiarize yourself with.<\/p>\n\n\n\n<p>If you&#8217;re unfamiliar with Docker, it&#8217;s a virtualization container system for easily adding software. It adds chroot, namespace, file, and network isolation from the host operating system giving you protection (note that Docker does share the host OS kernel). <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install Docker<\/h2>\n\n\n\n<p>To install Docker on your Raspberry PI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -fsSL https:\/\/get.docker.com -o get-docker.sh<\/code><\/pre>\n\n\n\n<p>Then run the installation script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo sh get-docker.sh<\/code><\/pre>\n\n\n\n<p>Then append a non root user to the docker group to run docker commands. The default pi user is below, but you can change to the user you&#8217;ve setup on your Raspberry Pi.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo usermod -aG docker pi<\/code><\/pre>\n\n\n\n<p>To test the install:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker version<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"978\" height=\"857\" src=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_12-58-54.png\" alt=\"\" class=\"wp-image-1752\" srcset=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_12-58-54.png 978w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_12-58-54-300x263.png 300w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_12-58-54-768x673.png 768w\" sizes=\"auto, (max-width: 978px) 100vw, 978px\" \/><\/figure>\n\n\n\n<p>Now you&#8217;ll want to make sure docker starts on reboot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl enable docker<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Install Docker-Compose<\/h2>\n\n\n\n<p>For installing docker-compose, you&#8217;ll need python and pip3:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install libffi-dev libssl-dev\nsudo apt install python3-dev\nsudo apt install -y python3 python3-pip<\/code><\/pre>\n\n\n\n<p>Then install docker-compose:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo pip3 install docker-compose<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Install Pi-hole and Unbound Docker images<\/h2>\n\n\n\n<p>Inspiration: <a rel=\"noreferrer noopener\" href=\"https:\/\/www.xfelix.com\/2020\/09\/pihole-unbound-docker-setup-on-raspberry-pi\/\" data-type=\"URL\" data-id=\"https:\/\/www.xfelix.com\/2020\/09\/pihole-unbound-docker-setup-on-raspberry-pi\/\" target=\"_blank\">https:\/\/www.xfelix.com\/2020\/09\/pihole-unbound-docker-setup-on-raspberry-pi\/<\/a><\/p>\n\n\n\n<p>Make a directory for Pi-hole and unbound:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir pihole\nmkdir unbound<\/code><\/pre>\n\n\n\n<p>In the unbound directory create the following file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>touch a-records.conf<\/code><\/pre>\n\n\n\n<p>Then add unbound.conf with the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server:\n# If no logfile is specified, syslog is used\n# logfile: \"\/var\/log\/unbound\/unbound.log\"\nverbosity: 0\n \naccess-control: 172.16.0.0\/12 allow\naccess-control: 127.0.0.0\/8 allow\naccess-control: 10.0.0.0\/8 allow\naccess-control: 192.168.0.0\/16 allow\ninterface: 0.0.0.0\nport: 5053\ndo-ip4: yes\ndo-udp: yes\ndo-tcp: yes\n \n# May be set to yes if you have IPv6 connectivity\ndo-ip6: no\n \n# You want to leave this to no unless you have *native* IPv6. With 6to4 and\n# Terredo tunnels your web browser should favor IPv4 for the same reasons\nprefer-ip6: no\n \n# Use this only when you downloaded the list of primary root servers!\n# If you use the default dns-root-data package, unbound will find it automatically\n# I have to quote out this root-hints, as it causing container endless restarting for a new installation. You can add root-hints back after first run. \n#root-hints: \u201c\/opt\/unbound\/etc\/unbound\/root.hints\u201d\n \n# Trust glue only if it is within the server's authority\nharden-glue: yes\n \n# Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS\nharden-dnssec-stripped: yes\n \n# Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes\n# see https:\/\/discourse.pi-hole.net\/t\/unbound-stubby-or-dnscrypt-proxy\/9378 for further details\nuse-caps-for-id: no\n \n# Reduce EDNS reassembly buffer size.\n# Suggested by the unbound man page to reduce fragmentation reassembly problems\nedns-buffer-size: 1472\n \n# Perform prefetching of close to expired message cache entries\n# This only applies to domains that have been frequently queried\nprefetch: yes\n \n# One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads above 1.\nnum-threads: 1\n \n# Ensure kernel buffer is large enough to not lose messages in traffic spikes\nso-rcvbuf: 1m\n \n# Ensure privacy of local IP ranges\nprivate-address: 192.168.0.0\/16\nprivate-address: 169.254.0.0\/16\nprivate-address: 172.16.0.0\/12\nprivate-address: 10.0.0.0\/8\nprivate-address: fd00::\/8\nprivate-address: fe80::\/10\n \n#plex\nprivate-domain: plex.direct<\/code><\/pre>\n\n\n\n<p>Then edit the file docker-compose.yml  in the pihole directory and add the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>version: '3'\n \nnetworks:\n  dns_net:\n    driver: bridge\n    ipam:\n        config:\n        - subnet: 172.20.0.0\/16\n \nservices:\n  pihole:\n    container_name: pihole\n    hostname: pihole\n    image: pihole\/pihole:latest\n    networks:\n      dns_net:\n        ipv4_address: 172.20.0.6\n    ports:\n    - \"53:53\/tcp\"\n    - \"53:53\/udp\"\n    - \"8888:80\/tcp\"\n    - \"8443:443\/tcp\"\n    environment:\n    - 'TZ=America\/Denver'\n    - 'WEBPASSWORD=passw0rd'  #set your password for dashboard here\n    - 'DNS1=172.20.0.7#5053'\n    - 'DNS2=no'\n    volumes:\n    - '\/home\/pi\/pihole\/etc-pihole\/:\/etc\/pihole\/'\n    - '\/home\/pi\/pihole\/etc-dnsmasq.d\/:\/etc\/dnsmasq.d\/'\n    restart: unless-stopped\n  unbound:\n    container_name: unbound\n    image: mvance\/unbound-rpi:latest\n    networks:\n      dns_net:\n        ipv4_address: 172.20.0.7\n    volumes:\n    - \/home\/pi\/unbound:\/opt\/unbound\/etc\/unbound\n    ports:\n    - \"5053:5053\/tcp\"\n    - \"5053:5053\/udp\"\n    healthcheck:\n      disable: true\n    restart: unless-stopped<\/code><\/pre>\n\n\n\n<p>Once created it&#8217;s time to run the docker containers by executing the following in the pihole directory where you docker-compose.yml file is located:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker-compose up -d<\/code><\/pre>\n\n\n\n<p>This tells docker-compose to process your yml file and activate the containers (up) and run in the background (-d). You should see that docker downloaded and ran the Pihole and Unbound containers:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"978\" height=\"857\" src=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-44-09.png\" alt=\"\" class=\"wp-image-1751\" srcset=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-44-09.png 978w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-44-09-300x263.png 300w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-44-09-768x673.png 768w\" sizes=\"auto, (max-width: 978px) 100vw, 978px\" \/><\/figure>\n\n\n\n<p>Now you should be able to verify it&#8217;s running by issuing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker stats<\/code><\/pre>\n\n\n\n<p>And you can visit the webpage from the IP of the Raspberry Pi with port :8888\/admin added to the IP address:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"832\" src=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-52-46-1024x832.png\" alt=\"\" class=\"wp-image-1749\" srcset=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-52-46-1024x832.png 1024w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-52-46-300x244.png 300w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-52-46-768x624.png 768w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-52-46.png 1284w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Login using your password you set in the docker-compose.yml file, go into Settings, and select the DNS tab to double check that unbound is configured as your DNS server on port 5053:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"832\" src=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-56-10-1024x832.png\" alt=\"\" class=\"wp-image-1748\" srcset=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-56-10-1024x832.png 1024w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-56-10-300x244.png 300w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-56-10-768x624.png 768w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_13-56-10.png 1284w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>You&#8217;ll then want to add the Pi-hole server address to your router\/firewall to be assigned to devices through DHCP. In my case this Pi-hole install is the backup for a Raspberry Pi 2 that is my primary Pi-hole and Unbound server where I installed them natively without docker, but I have to say this docker method is easier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Adding Additional Blocklists<\/h2>\n\n\n\n<p>The default install only has one blocklist active, but there are several more curated lists you can add. Go into Group Management and select Adlists for the screen where you can add more lists. And <a rel=\"noreferrer noopener\" href=\"https:\/\/firebog.net\/\" data-type=\"URL\" data-id=\"https:\/\/firebog.net\/\" target=\"_blank\">Firebog<\/a> has a collection of lists. Those in green are safe, and in blue with no line through them should be safe in not interfering with websites and requiring you to intervene. I&#8217;ve added all of them except the Facebook one as the wife still uses Facebook in a limited capacity. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"832\" src=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-04-43-1024x832.png\" alt=\"\" class=\"wp-image-1747\" srcset=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-04-43-1024x832.png 1024w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-04-43-300x244.png 300w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-04-43-768x624.png 768w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-04-43.png 1284w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The site I linked above who I used has some additional instructions and how to update the docker containers. I&#8217;m still a very new Docker user, but I do see why it&#8217;s so popular. Handier than using the command line for managing docker is a docker container called <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.portainer.io\/v\/ce-2.9\/start\/install\/server\/docker\/linux\" data-type=\"URL\" data-id=\"https:\/\/docs.portainer.io\/v\/ce-2.9\/start\/install\/server\/docker\/linux\" target=\"_blank\">Portainer<\/a>. Enjoy and I&#8217;ll give a Portainer screenshot below that should motivate you to install it too.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"832\" src=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-17-30-1024x832.png\" alt=\"\" class=\"wp-image-1746\" srcset=\"https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-17-30-1024x832.png 1024w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-17-30-300x244.png 300w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-17-30-768x624.png 768w, https:\/\/jasonsblog.ddns.net\/wp-content\/uploads\/2022\/11\/Screenshot_2022-03-17_14-17-30.png 1284w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Pi-hole has to be one of the best things you could run on your home network to protect your privacy and enable advertisement, tracking, and malware site blocking for all the devices on the local network. This is especially helpful for Android phones and tablets where Google makes it difficult to use ad blockers not [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-188","post","type-post","status-publish","format-standard","hentry","category-tech"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"featured_image_src":null,"author_info":{"display_name":"Jason","author_link":"https:\/\/jasonsblog.ddns.net\/index.php\/author\/jturning\/"},"_links":{"self":[{"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/posts\/188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/comments?post=188"}],"version-history":[{"count":5,"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/posts\/188\/revisions"}],"predecessor-version":[{"id":6248,"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/posts\/188\/revisions\/6248"}],"wp:attachment":[{"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/media?parent=188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/categories?post=188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jasonsblog.ddns.net\/index.php\/wp-json\/wp\/v2\/tags?post=188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}