{"id":13587456,"url":"https://github.com/rakheshster/docker-stubby-unbound","last_synced_at":"2025-04-22T09:31:16.684Z","repository":{"id":40476035,"uuid":"285063631","full_name":"rakheshster/docker-stubby-unbound","owner":"rakheshster","description":"Stubby+Unbound Docker image for DNS-over-TLS.","archived":false,"fork":false,"pushed_at":"2023-01-31T00:00:46.000Z","size":147,"stargazers_count":8,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-02-14T21:50:07.833Z","etag":null,"topics":["dns","dns-over-tls","dns-privacy","dns-resolver","dns-server","nextdns","stubby","unbound","unbound-dns"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rakheshster.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}},"created_at":"2020-08-04T18:21:54.000Z","updated_at":"2023-01-29T09:55:43.000Z","dependencies_parsed_at":"2023-02-16T13:01:09.320Z","dependency_job_id":null,"html_url":"https://github.com/rakheshster/docker-stubby-unbound","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rakheshster%2Fdocker-stubby-unbound","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rakheshster%2Fdocker-stubby-unbound/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rakheshster%2Fdocker-stubby-unbound/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rakheshster%2Fdocker-stubby-unbound/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rakheshster","download_url":"https://codeload.github.com/rakheshster/docker-stubby-unbound/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223893164,"owners_count":17220834,"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":["dns","dns-over-tls","dns-privacy","dns-resolver","dns-server","nextdns","stubby","unbound","unbound-dns"],"created_at":"2024-08-01T15:06:13.236Z","updated_at":"2024-11-09T23:05:06.631Z","avatar_url":"https://github.com/rakheshster.png","language":"Shell","funding_links":[],"categories":["Shell"],"sub_categories":[],"readme":"# Stubby + Unbound + Docker\n![Buildx \u0026 Push to DockerHub](https://github.com/rakheshster/docker-stubby-unbound/workflows/Docker%20Build%20\u0026%20Push/badge.svg)\n\n## What is this?\nThis is a Docker image containing Stubby and Unbound. \n\nFrom the [Stubby documentation](https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Daemon+-+Stubby):\n\u003e Stubby is an application that acts as a local DNS Privacy stub resolver (using DNS-over-TLS). Stubby encrypts DNS queries sent from a client machine (desktop or laptop) to a DNS Privacy resolver increasing end user privacy.\n\nAs of version 0.3 Stubby also supports DNS-over-HTTPs.\n\nFrom the [Unbound documentation](https://nlnetlabs.nl/projects/unbound/about/):\n\u003e Unbound is a validating, recursive, caching DNS resolver. It is designed to be fast and lean and incorporates modern features based on open standards. To help increase online privacy, Unbound supports DNS-over-TLS which allows clients to encrypt their communication. \n\nUnbound is both a DNS server and a resolver. It is useful if you want a DNS server for home DNS resolution for instance (which was my use case, for my home lab).\n\nFrom the [DNS Privacy Project](https://dnsprivacy.org/wiki/display/DP/About+Stubby):\n\u003e Unbound can be configured as a local forwarder using DNS-over-TLS to forward queries. However at the moment Unbound does not have all the TCP/ TLC features that Stubby has for example, it cannot support ‘Strict’ mode, it cannot pad queries to hide query size and it opens a separate connection for /every/ DNS query (Stubby will re-use connections). However, Unbound is a mature and stable daemon and many people already use it as a local resolver. \n\nIt is possible to combine both together though - i.e. use Unbound as your DNS resolver, forwarding to Stubby running on a different port that does the actual DNS resolution using DNS-over-TLS. A sample config for this scenario can be found on [this page](https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Clients#DNSPrivacyClients-Unbound/Stubbycombination). \n\nThis Stubby + Unbound Docker image packages the two together. It sets up Stubby listening on port 8053 with Unbound listening on port 53 and forwarding to Stubby port 8053.  \n\n## Getting this\nIt is best to target a specific release when pulling this repo. Either switch to the correct tag after downloading, or download a zip of the latest release from the [Releases](https://github.com/rakheshster/docker-stubby-unbound/releases) page. \n\nVersion numbers are of the format `\u003cstubby version\u003e-\u003cunbound version\u003e-\u003cpatch\u003e` where `\u003cpatch\u003e` will be increments due to changes introduced by me (maybe a change to the Dockerfile or underlying Alpine/ s6 base). \n\nYou can download this from Docker Hub as [rakheshster/stubby-unbound:version](https://hub.docker.com/repository/docker/rakheshster/stubby-unbound). \n\n## s6-overlay\nI also took the opportunity to setup an [s6-overlay](https://github.com/just-containers/s6-overlay). I like their philosophy of a Docker container being “one thing” rather than “one process per container”. This is why I chose to create one image for both Stubby \u0026 Docker instead of separate images. It was surprisingly easy to setup. \n\nThe `etc` folder contains a `services.d` folder that holds the service definitions for Stubby and Unbound. Unbound is set to depend on Stubby via a `dependencies` file so they start in the correct order. The config files and service definitions are intentionally set to run Stubby and Unbound in the foreground. That’s because s6 expects them to run in the foreground. Moreover, each service runs under a separate non-root user account. \n\n\n## Configuring\nThe `root` folder has the following structure. \n\n```\nroot\n├── etc\n│   ├── services.d\n│   │   ├── stubby\n│   │   │   └── run\n│   │   └── unbound\n│   │       ├── dependencies\n│   │       └── run\n│   ├── stubby\n│   │   ├── stubby.orig.yml\n│   │   └── stubby.yml\n│   ├── unbound\n│   │   └── unbound.conf\n│   └── unbound.d\n│       ├── README.txt\n│       └── unbound.conf.orig\n└── usr\n    └── sbin\n        └── unbound-reload\n```\n\n### Unbound\nThe `unbound.d` folder is of interest if you want to tweak the Unbound config or add zones etc. All it currently has is a README file and the original `unbound.conf`. When the image is built the contents of this folder are copied into it at `/etc/unbound.d`, but during runtime a new docker volume and mapped to this location *within the container*. Since the new docker volume is empty upon creation, the first time the container is run the contents of `/etc/unbound.d` are copied from the container to this volume. If you then make any changes to this folder from within the container it will be stored in the docker volume. \n\nUnbound is set to pull in any files ending with `*.conf` from this folder into the running config. \n\nYou can edit the file via `docker exec` like thus: \n```\ndocker exec -it stubby-unbound vi /etc/unbound.d/somefile.conf\n```\n\nOr you copy a file from outside the container to it:\n```\ndocker cp somefile.conf stubby-unbound:/etc/unbound.d/\n```\n\nAfter making changes reload unload so it pulls in this config. The `/usr/sbin/unbound-reload` script does that. Run it thus:\n```\ndocker exec stubby-unbound unbound-reload\n```\n\n### Stubby\nStubby doesn't need any configuring but it would be a good idea to change the upstream DNS servers after downloading this repo and before building the image. \n\nWhen the image is built the `stubby` folder is copied into it as `/etc/stubby`, but during runtime a new docker volume is created and mapped to this location within the container (similar to what I do above). Since this volume is empty the first time, the contents of `/etc/stubby` are copied over to this docker volume but any subsequent changes its contents are stored in the docker volume. \n\nYou can edit the config file or copy from outside the container using similar commands as above. \n\n## Building \u0026 Running\nThe quickest way to get started after cloning/ downloading this repo is to use the `./scripts/buildlocal.sh` file. It takes the name and tag to assign the image from the `buildinfo.json` file.\n\nNOTE: the script is optional. You can build this via `docker build` too. And additional script `./.scripts/buildxandpush.sh` is what I use to create multi-arch images and push to Docker Hub. It too is optional. \n\nAfter the image is built you can run it manually via `docker run` or you use the `./.scripts/createcontainer.sh` script which takes the image name and container name as mandatory parameters and optionally the IP address and network of the container. I tend to use a macvlan network to run this so the container has its own IP address on my network. \n\n### Systemd integration\nThe `./.scripts/createcontainer.sh` script doesn’t run the container. It creates the container and also creates a systemd service unit file along with some instructions on what to do with it. This way you have systemd managing the container so it always starts after a system reboot. The unit file and systemd integration is optional of course; I wanted the container to always start after a reboot as it provides DNS for my home lab and is critical, that’s why I went through this extra effort. \n\nNote: The service unit file is set to only restart if the service is aborted. This is intentional in case you want to `docker stop` the container sometime. \n\n## Notes\nThis was my first Docker image. It has changed substantially since the initial days as I learnt more from building other images and tried to keep things common across all my images. \n\nThanks to [GitHub - MatthewVance/stubby-docker: Gain the full power of DNS-over-TLS forwarding by combining Stubby with Unbound](https://github.com/MatthewVance/stubby-docker) and [GitHub - treibholz/docker-stubby: minimal alpine-linux based stubby](https://github.com/treibholz/docker-stubby) which I referred to extensively to pick up Docker as I went along. Any mistakes or inefficiencies in this Docker image are all mine. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frakheshster%2Fdocker-stubby-unbound","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frakheshster%2Fdocker-stubby-unbound","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frakheshster%2Fdocker-stubby-unbound/lists"}