DNS-over-HTTPS (DoH) encrypts your DNS queries, preventing ISPs, network administrators, and attackers from monitoring which websites you visit. While public DoH resolvers like Cloudflare and Google exist, running your own gives you complete control over your DNS privacy, ad-blocking capabilities, and query logs. In this comprehensive guide, you’ll learn how to set up your own DNS-over-HTTPS resolver using AdGuard Home.

💡 This article contains affiliate links. If you buy through them, we earn a small commission at no extra cost to you. Learn more.

Why Run Your Own DoH Resolver?

Privacy and Control: When you use public DNS resolvers, you’re trusting third parties with metadata about every website you visit. Running your own DoH resolver keeps this data under your control. You decide what gets logged, how long logs are retained, and who has access to them.

Centralized Ad-Blocking: AdGuard Home combines DNS-over-HTTPS encryption with powerful ad-blocking and tracker filtering. Instead of configuring ad-blockers on every device, your DoH resolver blocks ads network-wide for all connected devices — phones, tablets, smart TVs, and IoT devices.

Protection from DNS Hijacking: Many ISPs hijack DNS queries to inject ads, redirect typos to search pages, or log your browsing history. DoH encryption prevents this interference, ensuring your queries reach your resolver unmodified.

Bypass DNS-Based Censorship: Encrypted DNS prevents network-level censorship based on DNS filtering. While VPNs offer broader protection, DoH alone can bypass many simple DNS-based blocks without the performance overhead of a full VPN tunnel.

Better Performance: Running a local DoH resolver eliminates latency from remote DNS services. Queries stay on your network until they’re forwarded upstream, and AdGuard Home’s aggressive caching reduces upstream queries significantly.

Prerequisites

Before starting, you’ll need:

  • A server or homelab device: Any Linux system will work. A mini PC like the Beelink SER5 Max or Intel NUC makes an excellent always-on DNS server
  • Docker and Docker Compose installed: We’ll use containers for easy deployment and isolation
  • A domain name: For proper TLS certificates (Let’s Encrypt requires a real domain)
  • Port 443 and 53 available: DoH uses HTTPS (443), and standard DNS uses port 53
  • Basic Linux command-line knowledge: You’ll be editing configuration files and running Docker commands

Understanding DNS-over-HTTPS Architecture

Before diving into configuration, let’s understand how DoH works:

Standard DNS sends queries in plaintext over UDP port 53. Anyone monitoring your network (ISP, Wi-Fi administrator, attacker) can see every domain you query. DNS responses are also unencrypted and can be spoofed.

DNS-over-HTTPS encapsulates DNS queries inside HTTPS requests. Your device sends encrypted HTTPS traffic to your DoH resolver on port 443 (or 853 for DNS-over-TLS). The queries are encrypted using TLS, making them indistinguishable from regular HTTPS traffic.

Your DoH resolver (AdGuard Home) receives these encrypted queries, decrypts them, processes them (applying filters and ad-blocking rules), then forwards them to upstream DNS servers. The responses follow the reverse path back to your client, encrypted end-to-end.

Step 1: Set Up AdGuard Home with Docker

Create a directory for your AdGuard Home configuration:

1
2
mkdir -p ~/adguardhome/{work,conf}
cd ~/adguardhome

Create a docker-compose.yml file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
version: '3'

services:
  adguardhome:
    image: adguard/adguardhome:latest
    container_name: adguardhome
    restart: unless-stopped
    ports:
      - "53:53/tcp"        # DNS
      - "53:53/udp"        # DNS
      - "80:80/tcp"        # Web UI (initial setup)
      - "443:443/tcp"      # DoH
      - "443:443/udp"      # DoH (HTTP/3)
      - "3000:3000/tcp"    # Initial setup web UI
    volumes:
      - ./work:/opt/adguardhome/work
      - ./conf:/opt/adguardhome/conf
    cap_add:
      - NET_ADMIN

Important Port Notes:

  • Port 3000 is only needed for initial setup; you can remove it after configuration
  • Port 80 can be removed after setup if you only want DoH (not plain HTTP management)
  • Ports 443 TCP and UDP enable both HTTPS and HTTP/3 for DoH

Start AdGuard Home:

1
docker compose up -d

Step 2: Initial AdGuard Home Configuration

Open your browser and navigate to http://your-server-ip:3000. You’ll see the AdGuard Home setup wizard.

Setup Steps:

  1. Choose Port: Keep the defaults (port 80 for admin panel, port 53 for DNS). We’ll configure HTTPS in the next step.

  2. Create Admin Account: Set a strong username and password. This account has full access to DNS logs and configuration.

  3. Configure Devices: Skip this for now — we’ll configure DoH clients later.

After completing the wizard, you’ll be redirected to the admin panel at http://your-server-ip. Log in with your credentials.

Step 3: Configure TLS Certificates for DoH

DoH requires valid TLS certificates. You have two options:

Install Certbot on your host system:

1
2
3
4
5
# Ubuntu/Debian
sudo apt update && sudo apt install certbot

# Generate certificate (replace with your domain)
sudo certbot certonly --standalone -d dns.yourdomain.com

Certbot will place certificates in /etc/letsencrypt/live/dns.yourdomain.com/.

Copy certificates to your AdGuard Home directory:

1
2
3
sudo cp /etc/letsencrypt/live/dns.yourdomain.com/fullchain.pem ~/adguardhome/conf/
sudo cp /etc/letsencrypt/live/dns.yourdomain.com/privkey.pem ~/adguardhome/conf/
sudo chown $USER:$USER ~/adguardhome/conf/*.pem

Certificate Renewal: Let’s Encrypt certificates expire every 90 days. Set up a cron job to renew and copy them:

1
sudo crontab -e

Add this line:

0 3 * * * certbot renew --quiet && cp /etc/letsencrypt/live/dns.yourdomain.com/*.pem /home/yourusername/adguardhome/conf/ && docker restart adguardhome

Option B: Self-Signed Certificates (Testing Only)

For testing or internal-only use, you can generate self-signed certificates:

1
2
3
4
cd ~/adguardhome/conf
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout privkey.pem -out fullchain.pem \
  -subj "/CN=dns.yourdomain.local"

Note: Clients will show certificate warnings with self-signed certificates. This is acceptable for testing but not recommended for production.

Step 4: Enable DoH in AdGuard Home

  1. Open AdGuard Home Admin Panel: Navigate to http://your-server-ip

  2. Go to Settings → Encryption Settings

  3. Configure TLS:

    • Enable HTTPS: Check this box
    • Server Name: Enter your domain (e.g., dns.yourdomain.com)
    • Certificate Path: /opt/adguardhome/conf/fullchain.pem
    • Private Key Path: /opt/adguardhome/conf/privkey.pem
    • Port HTTPS: 443
  4. Enable DNS-over-HTTPS: The DoH endpoint will be https://dns.yourdomain.com/dns-query

  5. Optional - Enable DNS-over-TLS: Port 853 for DoT support

  6. Click Save

AdGuard Home will restart and begin serving DoH on port 443.

Verify DoH is Working:

1
2
curl -H 'accept: application/dns-json' \
  'https://dns.yourdomain.com/dns-query?name=example.com&type=A'

You should receive a JSON response with DNS data.

Step 5: Configure Upstream DNS Servers

AdGuard Home needs upstream DNS servers to forward queries. You can use encrypted upstreams for end-to-end privacy.

In AdGuard Home Admin Panel:

  1. Go to Settings → DNS Settings

  2. Upstream DNS Servers: Add encrypted upstreams:

https://dns.cloudflare.com/dns-query
https://dns.quad9.net/dns-query
tls://1.1.1.1
tls://9.9.9.9
  1. Bootstrap DNS Servers: Required to resolve DoH upstream addresses:
1.1.1.1
9.9.9.9
  1. Test Upstreams: Click “Test upstreams” to verify connectivity

  2. Save Configuration

Performance Tip: Use geographically close DNS servers for better latency. You can also mix DoH and DoT upstreams for redundancy.

Step 6: Configure Ad-Blocking and Filters

One major advantage of AdGuard Home is built-in ad-blocking:

  1. Go to Filters → DNS Blocklists

  2. Add Filter Lists: Click “Add blocklist” and add:

    • AdGuard DNS filter: https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt
    • AdAway: https://adaway.org/hosts.txt
    • Steven Black’s Unified Hosts: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
    • OISD Big: https://big.oisd.nl/
  3. Update Filters: Click “Check for updates” to download filter lists

  4. Configure Allowed/Blocked Services (optional): Block entire services like Facebook, TikTok, or YouTube network-wide

AdGuard Home will now block ads, trackers, and malicious domains for all DoH clients.

Step 7: Configure DoH Clients

Now configure your devices to use your DoH resolver.

Windows 10/11

Windows has native DoH support:

  1. Open Settings → Network & Internet → Status
  2. Click Properties for your active network
  3. Scroll to DNS server assignment and click Edit
  4. Select Manual
  5. Enable IPv4
  6. Preferred DNS: Enter your AdGuard Home server IP (e.g., 192.168.1.100)
  7. DNS over HTTPS: Select On (automatic template)
  8. Fallback DNS: Configure a backup server
  9. Click Save

Windows will automatically use DoH if your server advertises support.

macOS

macOS supports DoH via configuration profiles:

  1. Create a configuration profile using Apple Configurator or download a template
  2. Configure the DoH server URL: https://dns.yourdomain.com/dns-query
  3. Install the profile: System Preferences → Profiles

Alternatively, use third-party apps like DNSCrypt Proxy for easier configuration.

Linux

Install systemd-resolved (most modern distributions include it):

Edit /etc/systemd/resolved.conf:

1
2
3
4
[Resolve]
DNS=192.168.1.100
DNSOverTLS=opportunistic
Domains=~.

Restart systemd-resolved:

1
sudo systemctl restart systemd-resolved

For native DoH (not DoT), use dnscrypt-proxy or stubby.

Android

Android 9+ supports native DoH:

  1. Settings → Network & Internet → Private DNS
  2. Select Private DNS provider hostname
  3. Enter: dns.yourdomain.com
  4. Tap Save

Android will automatically use DoH for all DNS queries.

iOS/iPadOS

iOS 14+ supports DoH via configuration profiles:

  1. Create a signed .mobileconfig profile with your DoH server details
  2. Install via Settings → General → Profiles
  3. Trust the profile

Apps like NextDNS or Cloudflare WARP simplify this process.

Browsers (Firefox, Chrome, Edge)

Most modern browsers support DoH independently:

Firefox:

  1. Settings → Privacy & Security → DNS over HTTPS
  2. Select Custom and enter: https://dns.yourdomain.com/dns-query

Chrome/Edge:

  1. Settings → Privacy and security → Security
  2. Enable Use secure DNS
  3. Select Custom and enter: https://dns.yourdomain.com/dns-query

Browser-level DoH only affects browser traffic, not system-wide queries.

Step 8: Testing Your DoH Resolver

Test DNS Resolution:

1
2
3
4
5
6
# Standard DNS query
nslookup example.com your-server-ip

# DoH query using curl
curl -H 'accept: application/dns-json' \
  'https://dns.yourdomain.com/dns-query?name=example.com&type=A'

Verify Ad-Blocking:

Visit http://blockads.fivefilters.org/ or query a known ad domain:

1
nslookup ads.google.com your-server-ip

You should receive a blocked/null response.

Check DNS Leak:

Visit dnsleaktest.com to verify your DoH queries aren’t leaking to your ISP’s DNS servers. You should only see your AdGuard Home server (or your chosen upstream providers, not your ISP).

Monitor Logs:

In AdGuard Home, go to Query Log to see real-time DNS queries. Verify that blocked domains show as “Blocked” and allowed domains resolve correctly.

Advanced Configuration

Enable Query Logging and Statistics

AdGuard Home provides detailed analytics:

  1. Settings → General Settings
  2. Query log retention: Set retention period (7 days, 30 days, etc.)
  3. Enable statistics: Track blocked queries, top clients, top domains

Privacy Note: If you’re running this for privacy, consider shorter log retention or disable logging entirely.

Configure Access Control Lists (ACLs)

Restrict which clients can use your DoH resolver:

  1. Settings → DNS Settings → Access Settings
  2. Allowed clients: Add IP ranges or individual IPs
  3. Disallowed clients: Block specific IPs
  4. Blocked domains: Additional custom blocks beyond filter lists

This prevents unauthorized users from using your DoH resolver.

Rate Limiting

Prevent abuse and DoS attacks:

  1. Settings → DNS Settings
  2. Rate limit: Set queries per second per client (default: 20)

DNSSEC Validation

Enable DNSSEC to verify DNS response authenticity:

  1. Settings → DNS Settings
  2. Enable DNSSEC: Check this box

DNSSEC adds cryptographic signatures to DNS responses, preventing tampering.

Conditional Forwarding (Split DNS)

Send specific domains to different DNS servers:

  1. Settings → DNS Settings → Upstream DNS servers
  2. Add domain-specific upstreams:
[/local.domain/]192.168.1.1
[/internal.company.com/]10.0.0.1

This is useful for resolving internal domains through your local DNS server while using DoH for external queries.

Troubleshooting Common Issues

Certificate Errors: If clients report certificate errors, verify:

  • Your domain’s DNS A record points to your server’s IP
  • Certificates are valid: openssl x509 -in fullchain.pem -text -noout
  • The server name in AdGuard Home matches your certificate’s Common Name (CN)

Port 53 Conflicts: If port 53 is already in use (by systemd-resolved or dnsmasq):

  • Stop conflicting service: sudo systemctl stop systemd-resolved
  • Or configure AdGuard Home to use a different port (then configure clients accordingly)

DoH Not Working: Check firewall rules:

1
2
3
4
sudo ufw allow 443/tcp
sudo ufw allow 443/udp
sudo ufw allow 53/tcp
sudo ufw allow 53/udp

Slow Queries: If DNS resolution is slow:

  • Add more upstream servers for redundancy
  • Enable parallel upstream queries in AdGuard Home settings
  • Reduce filter list count (too many lists can slow processing)

IPv6 Issues: If you’re not using IPv6, disable it in AdGuard Home:

  • Settings → DNS Settings → DNS server configuration
  • Uncheck Enable IPv6

Security Best Practices

Use Strong Authentication: Your AdGuard Home admin panel controls your entire DNS infrastructure. Use a strong password and consider IP-based access restrictions.

Keep AdGuard Home Updated: Run docker compose pull && docker compose up -d regularly to get security patches.

Harden Your Server: If your DoH resolver is publicly accessible:

  • Enable a firewall (UFW, iptables)
  • Use Fail2Ban to block brute-force attempts on HTTPS
  • Disable password authentication for SSH
  • Keep your OS updated

Monitor Logs: Regularly review query logs for unusual activity (sudden spikes, suspicious domains, unauthorized clients).

Backup Configuration: AdGuard Home stores configuration in ~/adguardhome/conf/AdGuardHome.yaml. Back this up regularly:

1
cp ~/adguardhome/conf/AdGuardHome.yaml ~/adguardhome/conf/AdGuardHome.yaml.backup

Performance Optimization

Increase Cache Size: AdGuard Home caches DNS responses. Increase cache size for better performance:

Edit ~/adguardhome/conf/AdGuardHome.yaml:

1
2
3
4
dns:
  cache_size: 10000000  # 10 million entries
  cache_ttl_min: 300    # Minimum cache TTL (5 minutes)
  cache_ttl_max: 86400  # Maximum cache TTL (24 hours)

Restart AdGuard Home after editing:

1
docker restart adguardhome

Use Local Upstream Resolvers: If you run Unbound or another recursive resolver locally, use it as an upstream to eliminate external dependencies:

127.0.0.1:5335

Enable HTTP/3: AdGuard Home supports HTTP/3 (QUIC) for DoH, which offers better performance over unreliable connections. It’s automatically enabled when you expose port 443/UDP.

Conclusion

You now have a fully functional DNS-over-HTTPS resolver with ad-blocking, query logging, and complete privacy control. Your DNS queries are encrypted end-to-end, protected from ISP snooping, DNS hijacking, and network-based censorship.

Unlike public DoH services, you control your data. You decide what gets blocked, what gets logged, and who has access. Combined with AdGuard Home’s powerful filtering capabilities, you’ve built a privacy-focused DNS infrastructure that protects all devices on your network.

Next Steps:

  • Configure all your devices to use your DoH resolver
  • Fine-tune filter lists based on your browsing habits
  • Set up automated backups of your configuration
  • Consider running a secondary AdGuard Home instance for redundancy
  • Explore integrating with Home Assistant or other home automation systems for conditional DNS filtering

Your self-hosted DoH resolver puts you back in control of one of the internet’s most fundamental protocols — and that’s something worth protecting.