From facdd6a2eca184de2b844db1ed5b3920c89c521f Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Thu, 25 Dec 2025 14:09:38 +0100 Subject: [PATCH] feat(stack): add AdGuard Home DNS ad-blocking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deploy AdGuard Home as network-wide DNS ad blocker with: - Quad9 DoH upstream for encrypted, security-focused DNS - Web UI on port 3053, DNS on 192.168.86.149:53 - Internal domain: dns.schweitz.internal Includes setup guide (ADGUARD_SETUP.md) for completing wizard. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- ADGUARD_SETUP.md | 55 +++++++++++++++++++++++++++++++++++++++++++++ CONTAINERS.md | 29 ++++++++++++++++++++++-- stacks/adguard.yml | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 ADGUARD_SETUP.md create mode 100644 stacks/adguard.yml diff --git a/ADGUARD_SETUP.md b/ADGUARD_SETUP.md new file mode 100644 index 0000000..bcc45b0 --- /dev/null +++ b/ADGUARD_SETUP.md @@ -0,0 +1,55 @@ +# AdGuard Home Setup - Remaining Steps + +Complete these steps when you're on the local network. + +## 1. Setup Wizard + +Access: **http://192.168.86.149:3053** + +Configure: +- Admin interface: All interfaces, port **3053** +- DNS server: All interfaces, port **53** +- Create admin username/password + +## 2. Configure Upstream DNS (Quad9 DoH) + +Settings → DNS settings → Upstream DNS servers: + +``` +https://dns.quad9.net/dns-query +``` + +Enable: **Parallel requests** for faster resolution + +## 3. Add Blocklists + +Filters → DNS blocklists → Add blocklist: + +| List | URL | +|------|-----| +| AdGuard DNS filter | (enabled by default) | +| OADB | `https://raw.githubusercontent.com/ookangzheng/dbl-oisd-nl/master/dbl.txt` | +| Steven Black | `https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts` | + +## 4. Configure Router + +Set your router's DNS server to: **192.168.86.149** + +This makes all devices on the network use AdGuard for DNS. + +## 5. Verify + +```bash +# Test DNS resolution +dig @192.168.86.149 google.com + +# Test ad blocking (should return 0.0.0.0 or NXDOMAIN) +dig @192.168.86.149 ads.google.com + +# Test internal domain +curl http://dns.schweitz.internal/ +``` + +--- + +**Delete this file after setup is complete.** diff --git a/CONTAINERS.md b/CONTAINERS.md index cd17783..489495e 100644 --- a/CONTAINERS.md +++ b/CONTAINERS.md @@ -1,7 +1,7 @@ # Container Reference - tower-of-joy Infrastructure -> **Last Updated:** 2025-12-24 -> **Total Services:** 26 containers across 20 stacks +> **Last Updated:** 2025-12-25 +> **Total Services:** 27 containers across 21 stacks > **System:** Intel i7-6700, RTX 2080 Ti (11GB VRAM), 16GB RAM, Zorin OS 16.3 --- @@ -36,6 +36,7 @@ | **Home Assistant** | 8123 | https://housekeeping.schweitz.net | Internet | No | - | ✅ Running | | **Paperless-ngx** | 8091 | https://documents.schweitz.net | Internet | No | 8 | ✅ Running | | **ClamAV** | 3310 | N/A (host service) | No | No | - | ✅ Running | +| **AdGuard Home** | 53, 3053 | http://dns.schweitz.internal | LAN (DNS) | No | - | ✅ Running | ### External Domains (SSL via Let's Encrypt) - **home.schweitz.net** → Organizr (Protected by Authentik SSO) @@ -68,6 +69,7 @@ Internal domains provide LAN-accessible URLs without SSL or Authentik, ideal for | git.schweitz.internal | localhost | 3002 | | library.schweitz.internal | localhost | 8088 | | tatlock.schweitz.internal | localhost | 82 | +| dns.schweitz.internal | localhost | 3053 | **DNS Resolution:** Via `/etc/hosts` on tower-of-joy (192.168.86.149) @@ -211,6 +213,29 @@ Nginx Proxy Manager serves as the unified reverse proxy and SSL certificate mana --- +### AdGuard Home + +AdGuard Home is a network-wide DNS-based ad and tracker blocker that functions as a local DNS server, filtering requests at the network level before they reach any device. It provides encrypted DNS (DoH/DoT) to upstream resolvers, a web-based dashboard for query statistics and configuration, and customizable blocklists for ads, trackers, and malware domains. All devices on the network pointing to this DNS server receive ad blocking without requiring per-device software installation. + +| Property | Value | +|----------|-------| +| **Image** | `adguard/adguardhome:latest` | +| **Container Name** | `adguard` | +| **Access URL (LAN)** | http://192.168.86.149:3053 | +| **Internal Domain** | http://dns.schweitz.internal | +| **External Access** | LAN only (DNS server for local network) | +| **Port Mapping** | 192.168.86.149:53:53 (DNS), 3053:3000 (Web UI) | +| **Network Mode** | Bridge (docker-dataplane) | +| **Restart Policy** | `unless-stopped` | +| **Volume Mounts** | `~/docker-data/adguard/work:/opt/adguardhome/work`, `~/docker-data/adguard/conf:/opt/adguardhome/conf` | +| **Resource Limits** | None | +| **GPU Required** | No | +| **Dependencies** | None | +| **Upstream DNS** | Quad9 DoH (https://dns.quad9.net/dns-query) | +| **Health Check** | `nslookup localhost 127.0.0.1` (30s interval) | + +--- + ### Ollama Ollama is a GPU-accelerated large language model server that provides a REST API for running local LLM inference with models up to 13B parameters, leveraging the RTX 2080 Ti's 11GB VRAM for fast on-device AI capabilities. It manages model downloads, quantization, and serving through a simple API compatible with OpenAI's format, supporting use cases like code generation, chat applications, and text processing without cloud dependencies. The service stores models on the SSD for quick loading times and maintains persistent model storage across container restarts. diff --git a/stacks/adguard.yml b/stacks/adguard.yml new file mode 100644 index 0000000..ccb8698 --- /dev/null +++ b/stacks/adguard.yml @@ -0,0 +1,56 @@ +version: '3.8' + +# AdGuard Home - Network-wide DNS Ad Blocking +# Infrastructure Layer +# Ports: 53 (DNS), 3053 (Web UI) +# GPU: No +# Storage: SSD (configs and work data) + +services: + adguard: + image: adguard/adguardhome:latest + container_name: adguard + restart: unless-stopped + ports: + - "192.168.86.149:53:53/tcp" # DNS TCP (bound to LAN IP to avoid systemd-resolved conflict) + - "192.168.86.149:53:53/udp" # DNS UDP + - "3053:3000/tcp" # Web UI + volumes: + # SSD storage for configs and query logs + - /home/jpmschweitzer/docker-data/adguard/work:/opt/adguardhome/work + - /home/jpmschweitzer/docker-data/adguard/conf:/opt/adguardhome/conf + environment: + - TZ=Europe/Amsterdam + healthcheck: + test: ["CMD-SHELL", "nslookup localhost 127.0.0.1 || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + networks: + - docker-dataplane + +networks: + docker-dataplane: + external: true + name: docker-dataplane + +# Setup Instructions: +# 1. Deploy this stack via Portainer +# 2. Access setup wizard at http://192.168.86.149:3053 +# 3. Configure: +# - Admin interface: Listen on port 3053, all interfaces +# - DNS server: Listen on port 53, all interfaces +# - Create admin username/password +# 4. After setup, configure in AdGuard Home UI: +# - Settings → DNS settings → Upstream DNS: +# https://dns.quad9.net/dns-query +# - Enable "Parallel requests" +# - Filters → DNS blocklists → Add recommended lists +# 5. Configure router DNS to 192.168.86.149 +# +# Testing: +# dig @192.168.86.149 google.com # Should resolve +# dig @192.168.86.149 ads.google.com # Should be blocked +# +# Internal access: http://dns.schweitz.internal (requires NPM proxy + /etc/hosts entry)