{"id":15148262,"url":"https://github.com/patrickfav/pihole-unbound-docker","last_synced_at":"2025-10-24T03:31:27.980Z","repository":{"id":158704620,"uuid":"634140445","full_name":"patrickfav/pihole-unbound-docker","owner":"patrickfav","description":"A docker-compose setup that maintaines a Pi-hole DNS with an with an upstream Unbound recursive DNS all hosted locally.","archived":false,"fork":false,"pushed_at":"2024-02-17T04:41:46.000Z","size":38,"stargazers_count":110,"open_issues_count":1,"forks_count":17,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-30T22:42:03.187Z","etag":null,"topics":["adblock","dns","docker","docker-compose","homelab","pihole","privacy","unbound"],"latest_commit_sha":null,"homepage":"https://favr.dev/opensource/pihole-unbound-docker","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/patrickfav.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-04-29T07:06:40.000Z","updated_at":"2024-12-30T19:07:56.000Z","dependencies_parsed_at":"2023-06-15T02:15:38.050Z","dependency_job_id":null,"html_url":"https://github.com/patrickfav/pihole-unbound-docker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fpihole-unbound-docker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fpihole-unbound-docker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fpihole-unbound-docker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickfav%2Fpihole-unbound-docker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrickfav","download_url":"https://codeload.github.com/patrickfav/pihole-unbound-docker/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237910078,"owners_count":19385829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adblock","dns","docker","docker-compose","homelab","pihole","privacy","unbound"],"created_at":"2024-09-26T13:01:59.096Z","updated_at":"2025-10-24T03:31:27.706Z","avatar_url":"https://github.com/patrickfav.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pi-hole \u0026 Unbound DNS Docker Setup\n\nThis is a docker compose setup which starts a [Pi-hole](https://pi-hole.net/) and [nlnetlab's Unbound](https://nlnetlabs.nl/projects/unbound/about/) as upstream recursive DNS using official (or ready-to-use) images. The main idea here is to add security, [privacy](https://www.cloudflare.com/learning/dns/what-is-recursive-dns/) and have ad and malware protection, everything hosted locally.\n\nIf you want to learn more about why you want to have exactly this setup, read a [detailed explanation here](https://docs.pi-hole.net/guides/dns/unbound/).\n\n## Prepare\n\n### Understand the Setup\n\nThis setup works on a machine that does not itself already has DNS running (i.e. port 53 is already used). If you have a setup like that (e.g. running on a Synology NAS with a Directory Server), you would need a setup that creates a [Mac VLAN](https://docs.docker.com/network/macvlan/) so the container appears with a different IP. In this [case check out this example here](https://github.com/chriscrowe/docker-pihole-unbound/tree/main/two-container).\n\nIt is designed to have 2 containers running next to each other and do not aim to combine both programs in one. The idea is to minimize the work needed to adapt provided containerized versions of Pi-hole and Unbound, i.e. use the official images, therefore making it easier to upgrade each.\n\n### Prerequisites\n\nFirst you need a recent version of [Docker installed](https://docs.docker.com/get-docker/) which at least supports Docker compose v2.\nFurther you may want to have a [server or IoT device](https://docs.pi-hole.net/main/prerequisites/) where this stack can run on, since this should be reachable by every other client 24/7.\nFinally, don't forget to change your [default DNS server to the server IPs address of your server](https://docs.pi-hole.net/main/post-install/).\n\n### Configuration\n\nThe main configuration can be set in the `.env` file which overwrites the ENV variables in the `docker-compose.yml` - change it to your liking:\n\n```properties\nWEBPASSWORD= # set the password to use in the Web Admin UI\nHOST_IP_V4_ADDRESS= # the IP of the host the Pi-hole runs on - defaults to localhost\nTIMEZONE= # set your timezone (used to schedule cron jobs e.g.)\n```\n\n## Deploy Containers\n\n[![asciicast](https://asciinema.org/a/581383.svg)](https://asciinema.org/a/581383)\n\nStart the stack with going to the root of the repo and do:\n\n```bash\n docker compose up --build -d --remove-orphans\n```\n\nTo stop everything:\n\n```bash\n docker compose down\n```\n\nPro-Tip, if you want to directly deploy to a remote you can do\n\n```bash\n docker compose -H \"ssh://your-remote-host\" up --build -d --remove-orphans\n```\n\n## Use Web UI\n\nIf you didn't change anything and start this on your local machine you can access the Pi-hole web ui with\n\n```\nhttp://localhost:8080/admin/\n```\n\nThe default password is `changeMeNow`.\n\n## Test Setup\n\nTo test if Pi-Hole with unbound is working correctly you can use the test domain `unboundpiholetestdomain.org` I set up in Unbound.\nIn your terminal (you might [need to install `nslookup`](https://www.tecmint.com/install-dig-and-nslookup-in-linux/)) do:\n\n```\nnslookup unboundpiholetestdomain.org localhost\n```\nThis command will use localhost as DNS, if you are running it on a different machine, use the appropriate IP.\n\nThis should return the IP `192.168.123.123`:\n```\nServer:         localhost\nAddress:        ::1#53\n\nName:   unboundpiholetestdomain.org\nAddress: 192.168.123.123\n```\n\nif setup correctly it should also work without forcing DNS\n\n```\nnslookup unboundpiholetestdomain.org\n```\n\n## Advanced\n\n### Persistence after Restart\n\nBy default, Pi-hole will forget everything after a restart of the docker container. To change that you need to set\na docker volume to show Pi-hole where to save the configuration. You need to map `/etc/Pi-hole/` and `/etc/dnsmasq.d/` to\na directory on the server. [Read here if you want to learn more about volumes](https://stackoverflow.com/questions/68647242/define-volumes-in-docker-compose-yaml).\n\nThere is an example in the `docker-compose.yml`:\n\n```yaml\nservices:\n  Pi-hole:\n    container_name: ...\n# RECOMMENDED: Uncomment and adapt if you want to persist Pi-hole configurations after restart\n#    volumes:\n#      - \"/var/lib/docker/volumes/pihole/pihole:/etc/pihole/\"\n#      - \"/var/lib/docker/volumes/pihole/dnsmasq.d:/etc/dnsmasq.d/\"\n```\n\n### Pi-hole Configurations\n\nIn the `docker-compose.yml` you can add or change the Pi-hole Docker standard configuration variables in\n\n```yaml\nservices:\n  Pi-hole:\n    container_name: ...\n    environment:\n      # here\n```\nCheck out [possible configurations here](https://github.com/pi-hole/docker-pi-hole).\n\nAdditionally, you can change various settings in your Pi-hole instance (e.g. the used ad-list) through the web ui. I won't\nget into detail here apart from recommending `https://v.firebog.net/hosts/lists.php` as a good default starting list.\n\n\n### Upgrade Base Images\n\nIn the `docker-compose.yml` change the used Pi-hole version by changing\n\n```yaml\nservices:\n  Pi-hole:\n    container_name: ...\n    image: Pi-hole/Pi-hole:2023.03.1 # \u003c- update image version here, see: https://github.com/pi-hole/docker-pi-hole/releases\n    hostname: ...\n```\n\nand Unbound by changing the `FROM` in `./unbound/Dockerfile` \n\n```dockerfile\n# Update the version here, I use the docker build from https://github.com/MatthewVance/unbound-docker\nFROM mvance/unbound:1.17.1\n...\n```\n\n### Define Local A-Records \n\nIf you want to resolve certain domains locally you can set A-Records in `./unbound/conf/a-records.conf`. There are already examples, but to add a new record do:\n\n```\n# Example: Resolve all *.mysite.com addresses to the same ip of the main reverse proxy / router\n\nlocal-zone: \"mysite.com.\" redirect\nlocal-data: \"mysite.com. 86400 IN A 192.168.1.1\"\n```\n\nCheck here the [full documentation](https://unbound.docs.nlnetlabs.nl/_/downloads/en/latest/pdf/) or [tutorial](https://calomel.org/unbound_dns.html) to learn more.\n\n### Unbound, Forwarders and Manual Configuration\n\nUnbound is set as a recursive DNS, because all forwarders in `./unbound/conf/a-records.conf` are commented out. If you prefer to use cloudflare or any other public DNS as upstream instead of having the slight performance impact of directly asking the nameservers, then you can enable the respective server by removing the comment (but then using Unbound at all has little value.\n\nIf you want to fine-tune the Unbound configuration, you can add the file `./unbound/conf/unbound.conf` (see an [example here](https://github.com/MatthewVance/unbound-docker/blob/master/unbound.conf)) and Unbound will use it.\n\n## Limitations\n\n### Supported Platforms\n\nCurrently, this setup will only support platform type `amd64`, that means it will not run on machines that e.g. have an [ARM architecture](https://en.wikipedia.org/wiki/ARM_architecture_family) like the [Raspberry Pi](https://www.raspberrypi.com/documentation/computers/processors.html). While the official Pi-hole image supports [multi-arch](https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/), MatthewVance's unbound image does not. There is, however, a solution: there is a specific build for `arm/v7` which can be found on [Docker hub](https://hub.docker.com/r/mvance/unbound-rpi/tags). Just update the `Dockerfile` in `./unbound/Dockerfile`:\n\n```dockerfile\nFROM mvance/unbound-rpi:1.17.1\n...\n```\n\n### Watchtower\n\nIf you use tools like [Watchtower](https://github.com/containrrr/watchtower) to be notified about image updates - this will not work with Unbound here since we re-build it to create a self-contained, stateless image. It is possible to use the image `mvance/unbound` directly in the `docker-compose` and mount the configuration files to unbound instead of pre-building it. See [MatthewVance readme](https://github.com/MatthewVance/unbound-docker) on how to do that.\n\n# Links\n\n## Credits\n\n* [nlnetlabs Unbound](https://nlnetlabs.nl/projects/unbound/about/) (BSD license)\n* [MatthewVance's Unbound Docker Image](https://github.com/MatthewVance/unbound-docker) (MIT License)\n* [Pi-hole](https://github.com/pi-hole/pi-hole) (European Union Public License)\n* [Official Pi-hole Docker Image](https://github.com/pi-hole/docker-pi-hole) (unknown license)\n\n## Similar Projects\n\n* [chriscrowe's Mac Vlan Setup](https://github.com/chriscrowe/docker-pihole-unbound)\n* [origamiofficial's One Container Solution](https://github.com/origamiofficial/docker-pihole-unbound)\n* [JD10NN3's Solution](https://github.com/JD10NN3/docker-pihole-unbound)\n\n## Further Information\n\n* [Pi-hole Documentation](https://docs.pi-hole.net/)\n* [Unbound Documentation](https://unbound.docs.nlnetlabs.nl/_/downloads/en/latest/pdf/)\n* [Pi-hole + Unbound Details](https://docs.pi-hole.net/guides/dns/unbound/)\n* [How to run docker-compose on remote host?](https://stackoverflow.com/questions/35433147/how-to-run-docker-compose-on-remote-host) \n\n# License\n\nCopyright 2023 Patrick Favre-Bulle\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\n```\nhttps://www.apache.org/licenses/LICENSE-2.0\n```\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfav%2Fpihole-unbound-docker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrickfav%2Fpihole-unbound-docker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickfav%2Fpihole-unbound-docker/lists"}