{"id":30512916,"url":"https://github.com/allenhack638/self-hostable-private-dns","last_synced_at":"2026-05-03T22:34:00.146Z","repository":{"id":311030757,"uuid":"1034935935","full_name":"allenhack638/self-hostable-private-dns","owner":"allenhack638","description":"Private DNS resolver with Pi-hole + DoH/DoT + automatic HTTPS. Network-wide ad blocking and secure DNS in Docker.","archived":false,"fork":false,"pushed_at":"2025-08-21T18:01:58.000Z","size":493,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-21T19:27:48.967Z","etag":null,"topics":["ad-blocking","caddy","dns","dns-over-https","dns-over-tls","dnsdist","docker","docker-compose","network-filtering","pihole","privacy","private-dns","security","self-hosted"],"latest_commit_sha":null,"homepage":"https://github.com/allenhack638/self-hostable-private-dns","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/allenhack638.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,"zenodo":null}},"created_at":"2025-08-09T09:49:43.000Z","updated_at":"2025-08-21T19:21:39.000Z","dependencies_parsed_at":"2025-08-21T19:31:35.973Z","dependency_job_id":"0f0ad6f6-b9b2-49b7-bd9f-bad1bfd3e8f1","html_url":"https://github.com/allenhack638/self-hostable-private-dns","commit_stats":null,"previous_names":["allenhack638/dns-server"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/allenhack638/self-hostable-private-dns","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allenhack638%2Fself-hostable-private-dns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allenhack638%2Fself-hostable-private-dns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allenhack638%2Fself-hostable-private-dns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allenhack638%2Fself-hostable-private-dns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/allenhack638","download_url":"https://codeload.github.com/allenhack638/self-hostable-private-dns/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allenhack638%2Fself-hostable-private-dns/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32587819,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"ssl_error","status_checked_at":"2026-05-03T22:09:10.534Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["ad-blocking","caddy","dns","dns-over-https","dns-over-tls","dnsdist","docker","docker-compose","network-filtering","pihole","privacy","private-dns","security","self-hosted"],"created_at":"2025-08-26T06:00:30.730Z","updated_at":"2026-05-03T22:34:00.142Z","avatar_url":"https://github.com/allenhack638.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Self-hosted Private DNS (Pi-hole + Dnsdist + Caddy)\n\n![Pi-hole Dashboard Screenshot](docs/images/pihole-dashboard.png)\n\nRun your own **private DNS resolver** with advanced filtering, DNS over HTTPS (DoH), and DNS over TLS (DoT) — all in a simple Docker setup.  \nPi-hole provides customizable DNS filtering and query logging, dnsdist handles DNS/DoT/DoH backends, and Caddy manages HTTPS with automatic Let's Encrypt certificates.\n\n## ✨ Features\n\n- **Custom DNS filtering**: Centralized control over which domains are resolved\n- **Secure DNS**: DoH at `https://\u003cDOMAIN_DNS\u003e/dns-query` and DoT on port `853`\n- **Automatic TLS**: Caddy obtains and renews certificates via Let's Encrypt\n- **Dashboard**: Full query visibility and management at `https://\u003cDOMAIN_DASHBOARD\u003e/admin/`\n- **Persistence \u0026 health checks**: Data volumes and restart policies included\n\n## 🔧 Prerequisites\n\n### DNS Records\n\nSet up **A/AAAA DNS records** pointing both domains to your server's public IP:\n\n- `DOMAIN_DNS` → e.g., `dns.example.com`\n- `DOMAIN_DASHBOARD` → e.g., `dashboard.example.com`\n\n### Port Requirements\n\nEnsure the following ports are available (no other services using them):\n\n- `80, 443` → Caddy (HTTP/HTTPS)\n- `53/tcp, 53/udp` → DNS (dnsdist → Pi-hole)\n- `853/tcp` → DoT (dnsdist)\n\n## 🚀 Quick Start\n\n1. **Clone the repository:**\n\n   ```bash\n   git clone --depth=1 https://github.com/allenhack638/self-hostable-private-dns.git\n   cd self-hostable-private-dns\n   ```\n\n2. **Configure environment:**\n\n   ```bash\n   cp .env.example .env\n   # Edit .env with your domain names and password\n   ```\n\n3. **Start the stack:**\n\n   ```bash\n   docker compose up -d\n   ```\n\n4. ⚠️ **If you see \"port 53 already in use\" errors, then disable systemd-resolved:**\n\n   ```bash\n   # Stop the containers first\n   docker compose down\n\n   # Disable systemd-resolved\n   sudo systemctl stop systemd-resolved\n   sudo systemctl disable systemd-resolved\n\n   # Start the stack again\n   docker compose up -d\n   ```\n\n**To re-enable systemd-resolved later (if needed):**\n\n```bash\ndocker compose down\nsudo systemctl enable systemd-resolved\nsudo systemctl start systemd-resolved\n```\n\n\u003e **Why this order matters**: If you disable `systemd-resolved` first, your system will lose DNS resolution temporarily, preventing Docker from pulling images and Caddy from verifying certificates. Starting the stack first allows everything to download properly, then we only disable `systemd-resolved` if there's actually a conflict.\n\n## ⚙️ Configuration\n\n### Environment Variables\n\n| Variable                         | Description                                       | Example                 |\n| -------------------------------- | ------------------------------------------------- | ----------------------- |\n| `TZ`                             | Timezone in tz database format                    | `Asia/Kolkata`          |\n| `FTLCONF_webserver_api_password` | Dashboard login password (use a strong password!) | `your-secure-password`  |\n| `DOMAIN_DNS`                     | Public domain for DoH/DoT (TLS via Caddy)         | `dns.example.com`       |\n| `DOMAIN_DASHBOARD`               | Public domain for the dashboard                   | `dashboard.example.com` |\n\n\u003e **Timezone reference**: See the full list in [tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).\n\n## 📡 Usage\n\n### Service Endpoints\n\n| Protocol  | Address / URL                       | Port |\n| --------- | ----------------------------------- | ---- |\n| DNS       | `\u003cSERVER_IP\u003e`                       | 53   |\n| DoT       | `\u003cDOMAIN_DNS\u003e`                      | 853  |\n| DoH       | `https://\u003cDOMAIN_DNS\u003e/dns-query`    | 443  |\n| Dashboard | `https://\u003cDOMAIN_DASHBOARD\u003e/admin/` | 443  |\n\n### Port Summary\n\n| Port(s)        | Service                 |\n| -------------- | ----------------------- |\n| 53/tcp, 53/udp | DNS (dnsdist → Pi-hole) |\n| 80, 443        | Caddy (HTTP/HTTPS)      |\n| 853/tcp        | DoT (dnsdist)           |\n\n## 💾 Data \u0026 Persistence\n\n- **Pi-hole configuration**: Stored in `data/pihole/`\n- **Caddy certificates**: Stored in `data/caddy-data/`\n- **Shared certificates**: Copied to `data/shared-certs/` for dnsdist access\n\nAll data persists between container restarts and updates.\n\n## 📜 Monitoring \u0026 Troubleshooting\n\n### View Logs\n\n**All services (live):**\n\n```bash\ndocker compose logs -f\n```\n\n**Individual services:**\n\n```bash\ndocker compose logs dns-pihole\ndocker compose logs dns-caddy\ndocker compose logs dns-dnsdist\n```\n\n### Health Checks\n\nThe stack includes built-in health checks and restart policies to ensure services stay running.\n\n## 🙌 Credits\n\nThis project is built with these excellent open-source tools:\n\n- [Pi-hole](https://pi-hole.net/) – Network-level DNS filtering and management\n- [dnsdist](https://dnsdist.org/) – High-performance DNS load balancer with DoH/DoT support\n- [Caddy](https://caddyserver.com/) – Modern web server with automatic HTTPS\n\n## 🤝 Contributing\n\nIssues, questions, and feature requests are welcome! Please open an issue or start a discussion in this repository.\n\n## 📖 Advanced Configuration\n\nNeed custom configurations? I can help with:\n\n- Custom ACLs and fine-grained access control\n- Advanced dnsdist load-balancing strategies\n- Conditional forwarding rules\n- Integration with upstream/external resolvers\n- Enterprise-grade scaling and security hardening\n\n📬 **Contact**: [allenbenny038@gmail.com](mailto:allenbenny038@gmail.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallenhack638%2Fself-hostable-private-dns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fallenhack638%2Fself-hostable-private-dns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallenhack638%2Fself-hostable-private-dns/lists"}