{"id":29633821,"url":"https://github.com/kaczmar2/pihole-unbound","last_synced_at":"2025-07-21T15:01:56.834Z","repository":{"id":279546600,"uuid":"939137360","full_name":"kaczmar2/pihole-unbound","owner":"kaczmar2","description":"Pi-hole v6 + Unbound in Docker: A simple Docker Compose setup for Pi-hole v6 and Unbound running in separate containers. Unbound acts as a recursive DNS server for improved privacy and security.","archived":false,"fork":false,"pushed_at":"2025-07-18T23:24:58.000Z","size":34,"stargazers_count":61,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-19T03:57:56.291Z","etag":null,"topics":["docker","docker-compose","pihole","pihole-configuration","unbound","unbound-dns"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kaczmar2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-26T03:45:09.000Z","updated_at":"2025-07-18T23:24:54.000Z","dependencies_parsed_at":"2025-02-26T06:25:30.491Z","dependency_job_id":"45acacc6-805a-408e-ab94-c93428b18204","html_url":"https://github.com/kaczmar2/pihole-unbound","commit_stats":null,"previous_names":["kaczmar2/pihole-unbound"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kaczmar2/pihole-unbound","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fpihole-unbound","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fpihole-unbound/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fpihole-unbound/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fpihole-unbound/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kaczmar2","download_url":"https://codeload.github.com/kaczmar2/pihole-unbound/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaczmar2%2Fpihole-unbound/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266324141,"owners_count":23911224,"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","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["docker","docker-compose","pihole","pihole-configuration","unbound","unbound-dns"],"created_at":"2025-07-21T15:00:46.161Z","updated_at":"2025-07-21T15:01:56.772Z","avatar_url":"https://github.com/kaczmar2.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pi-hole v6 + Unbound in Docker\n\n## Summary\nThis is a **baseline setup of Pi-hole and Unbound** using Docker. It assumes that you already have a gateway/router with a **separate DHCP and NTP server**. If you want Pi-hole to handle DHCP, additional configuration is needed.\n\nThis setup follows the official **[Pi-hole Unbound guide](https://docs.pi-hole.net/guides/dns/unbound/)** but adapts it for **Pihole v6 and Docker Compose**.\n\nIn this setup, **Unbound does not have its own network interface**; instead, it runs using **Pi-hole’s network stack** (`network_mode: service:pihole`). This means:\n- **Unbound is not exposed to the host network** but can still resolve recursive DNS queries.\n- **Pi-hole forwards all upstream DNS queries** to `127.0.0.1#5335`, where Unbound handles recursive lookups.\n- **No additional networking configurations are needed** for Unbound.\n\n---\n\n## Prerequisites\nBefore you begin, ensure you are running:\n- A **Debian or Debian-based Linux distribution** (Ubuntu, Raspberry Pi OS, etc.)\n- [**Docker** installed](https://docs.docker.com/engine/install/)\n\n---\n\n## Quick Start\n\n```bash\n# Create directories\nmkdir -p ~/docker/pihole-unbound\nsudo mkdir -p /srv/docker/pihole-unbound/{pihole/{etc-pihole,etc-dnsmasq.d},unbound/etc-unbound}\nsudo chown -R $USER:$USER /srv/docker \u0026\u0026 chmod -R 755 /srv/docker\ntouch /srv/docker/pihole-unbound/unbound/etc-unbound/unbound.log\ncd ~/docker/pihole-unbound\n\n# Download and start\nwget https://github.com/kaczmar2/pihole-unbound/archive/refs/heads/main.tar.gz\ntar -xzf main.tar.gz --strip-components=1 \u0026\u0026 rm main.tar.gz\ndocker compose up -d\n```\n\nFor detailed setup instructions, continue reading below.\n\n---\n\n## Step 1: Create the Directory Structure for Bind Mounts\nBefore downloading the repository, set up the necessary directories for your **bind mounts**.\n\nRun the following commands:\n\n```bash\nmkdir -p ~/docker/pihole-unbound\nsudo mkdir -p /srv/docker/pihole-unbound/pihole/etc-pihole\nsudo mkdir -p /srv/docker/pihole-unbound/pihole/etc-dnsmasq.d\nsudo mkdir -p /srv/docker/pihole-unbound/unbound/etc-unbound\nsudo chown -R $USER:$USER /srv/docker\nchmod -R 755 /srv/docker\ntouch /srv/docker/pihole-unbound/unbound/etc-unbound/unbound.log\ncd ~/docker/pihole-unbound\n```\n### **What These Commands Do**\n- `mkdir -p ~/docker/pihole-unbound`: Creates a working directory in your home folder.\n- `sudo mkdir -p /srv/docker/...`: Creates **bind mounts** for Pi-hole and Unbound.\n- `sudo chown -R $USER:$USER /srv/docker`: Ensures **your user owns the folders**.\n- `chmod -R 755 /srv/docker`: Sets **read/write permissions** for better access.\n- `touch unbound.log`: Prepares the **log file for Unbound**.\n\n---\n\n## Step 2: Download the Repository\n\nYou can download the latest version of this repository using **`wget`** or **`curl`**:\n\n**Option 1: Using `wget`**\n```bash\nwget https://github.com/kaczmar2/pihole-unbound/archive/refs/heads/main.tar.gz\ntar -xzf main.tar.gz --strip-components=1\n```\n\n**Option 2: Using `curl`**\n```bash\ncurl -L -o main.tar.gz https://github.com/kaczmar2/pihole-unbound/archive/refs/heads/main.tar.gz\ntar -xzf main.tar.gz --strip-components=1\n```\n\nThe `--strip-components=1` flag ensures the contents are extracted directly into `~/docker/pihole-unbound` instead of creating an extra subdirectory.\n\n**Note for Raspberry Pi users**: If you're running this on a Raspberry Pi, you'll need to modify the Unbound image in `docker-compose.yml` from `mvance/unbound` to `mvance/unbound-rpi`.\n\n**Optional: Remove the archive after extraction**\n```sh\nrm main.tar.gz\n```\n\n---\n\n## Step 3: Start the Pi-hole + Unbound Containers\nNow, deploy the Pi-hole and Unbound services using:\n\n```bash\ndocker compose up -d\n```\n\n---\n\n## Step 4: Verify Unbound is Working\n\nTo confirm Unbound is resolving queries correctly, run the following commands **in the pihole container**:\n\nOpen a `bash` shell in the container:\n```bash\ndocker exec -it pihole /bin/bash\n```\n\nTest that Unbound is operational:\n\n```bash\ndig pi-hole.net @127.0.0.1 -p 5335\n```\n\nThe first query may be quite slow, but subsequent queries should be fairly quick.\n\n**Test validation**\n\n```bash\ndig fail01.dnssec.works @127.0.0.1 -p 5335\ndig dnssec.works @127.0.0.1 -p 5335\n```\n\nThe first command should give a status report of SERVFAIL and no IP address. The second should give NOERROR plus an IP address.\n\n---\n\n## Step 5: Set the Pi-hole Admin Password\n\nTo set the pihole web admin password, run the following commands **in the pihole container**, if you're not already there from the previous step (`docker exec -it pihole /bin/bash`):\n\n```bash\npihole setpassword 'mypassword'\n```\n\nGet the hashed password from `pihole.toml`:\n```bash\ncat /etc/pihole/pihole.toml | grep -w pwhash\n```\n\n`exit` the container and copy the hashed password into your `.env` file on the host.\n\nMake sure to enclose the value in single quotes (`''`).\n```bash\nWEB_PWHASH='$BALLOON-SHA256$v=1$s=1024,t=32$pZCbBIUH/Ew2n144eLn3vw==$vgej+obQip4DvSmNlywD0LUHlsHcqgLdbQLvDscZs78='\n```\n\nUncomment the `FTLCONF_webserver_api_pwhash` environment variable in `docker-compose.yml`:\n```bash\nFTLCONF_webserver_api_pwhash: ${WEB_PWHASH}\n```\n\nRestart the containers:\n```bash\ndocker compose down\ndocker compose up -d\n```\n\n## Step 6: Access the Pi-hole Web Interface\nOnce running, open your web browser and go to:\n\n```\nhttp://\u003cyour-server-ip\u003e/admin/\n```\n\nLogin using the password you set.\n\n---\n\n## Common Issues \u0026 Troubleshooting\n\n### Fix `so-rcvbuf` warning in Unbound (Optional)\n\nThe configuration in `pi-hole.conf` sets the **socket receive buffer size** for incoming DNS queries to a higher-than-default value in order to handle high query rates. \n\nYou may see this warning in unbound logs:\n```bash\nso-rcvbuf 1048576 was not granted. Got 425984. To fix: start with root permissions(linux) or sysctl bigger net.core.rmem_max(linux) or kern.ipc.maxsockbuf(bsd) values.\n```\n\nTo fix it:\n\n1. Check the current limit. This will show something like `net.core.rmem_max = 425984`:\n```bash\nsudo sysctl net.core.rmem_max\n```\n\n2. Temporarily increase the limit to match Unbound's request:\n```bash\nsudo sysctl -w net.core.rmem_max=1048576\n```\n\n3. Make it permanent. Edit `/etc/sysctl.conf` and add or edit the line:\n```bash\nnet.core.rmem_max=1048576\n```\n\n4. Save and apply:\n```bash\nsudo sysctl -p\n```\n\n## Step 8: Secure with SSL (Optional)\nFor enhanced security, see my other guides on **configuring SSL encryption** for the Pi-hole web interface.\n- [Pi-hole v6 + Docker: Automating Let's Encrypt SSL Renewal with Cloudflare DNS](https://gist.github.com/kaczmar2/027fd6f64f4e4e7ebbb0c75cb3409787#file-pihole-v6-docker-le-cf-md)\n---\n\n## Check Docker logs\nThis will **show live logs** for both the `pihole` and `unbound` containers.\n```bash\ndocker logs -f pihole\ndocker logs -f unbound\n```\n\n## Unbound Custom Configuration\n\nThe `unbound.conf.d/` directory contains custom configuration settings for Unbound.\n\n### Configuration Files:\n- **`unbound.conf.d/`** _(Custom Unbound settings, automatically included via a wildcard in `unbound.conf`.)_\n  - **`10-pi-hole.conf`** – Configures Unbound for use with Pi-hole following the [Pi-hole Unbound guide](https://docs.pi-hole.net/guides/dns/unbound/).\n  - **`20-private-domains.conf`** – Adds exceptions for domains that resolve private IPs from public DNS servers.\n    - Includes an entry for `plex.direct`, required for Plex clients to connect to the local server.\n    - Additional entries may be needed for other services that rely on domain-based local resolution.\n\n### Notes:\n- All files in `unbound.conf.d/` are automatically read by Unbound via a **wildcard include** directive in `unbound.conf`.\n- Modify `20-private-domains.conf` as needed to allow other trusted services that require resolving private IPs.\n- The following files have been **removed from the configuration** as they are not required for the Pi-hole + Unbound setup:\n  - `forward-records.conf`: This setup uses Unbound as a recursive resolver so forwarding is unnecessary.\n  - `a-records.conf`: Pi-hole can handle local hostname resolution instead.\n  - `srv-records.conf`: Most home networks don’t need this, unless you are doing things running Active Directory or doing service discovery.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaczmar2%2Fpihole-unbound","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkaczmar2%2Fpihole-unbound","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaczmar2%2Fpihole-unbound/lists"}