feat(stack): add AdGuard Home DNS ad-blocking

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 <noreply@anthropic.com>
This commit is contained in:
2025-12-25 14:09:38 +01:00
co-authored by Claude Opus 4.5
parent 7f9e73a849
commit facdd6a2ec
3 changed files with 138 additions and 2 deletions
+55
View File
@@ -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.**
+27 -2
View File
@@ -1,7 +1,7 @@
# Container Reference - tower-of-joy Infrastructure # Container Reference - tower-of-joy Infrastructure
> **Last Updated:** 2025-12-24 > **Last Updated:** 2025-12-25
> **Total Services:** 26 containers across 20 stacks > **Total Services:** 27 containers across 21 stacks
> **System:** Intel i7-6700, RTX 2080 Ti (11GB VRAM), 16GB RAM, Zorin OS 16.3 > **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 | | **Home Assistant** | 8123 | https://housekeeping.schweitz.net | Internet | No | - | ✅ Running |
| **Paperless-ngx** | 8091 | https://documents.schweitz.net | Internet | No | 8 | ✅ Running | | **Paperless-ngx** | 8091 | https://documents.schweitz.net | Internet | No | 8 | ✅ Running |
| **ClamAV** | 3310 | N/A (host service) | No | No | - | ✅ 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) ### External Domains (SSL via Let's Encrypt)
- **home.schweitz.net** → Organizr (Protected by Authentik SSO) - **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 | | git.schweitz.internal | localhost | 3002 |
| library.schweitz.internal | localhost | 8088 | | library.schweitz.internal | localhost | 8088 |
| tatlock.schweitz.internal | localhost | 82 | | tatlock.schweitz.internal | localhost | 82 |
| dns.schweitz.internal | localhost | 3053 |
**DNS Resolution:** Via `/etc/hosts` on tower-of-joy (192.168.86.149) **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
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. 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.
+56
View File
@@ -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)