Skip to content

AdGuard Home

Network-Wide DNS Protection

AdGuard Home is a network-wide software for blocking ads & tracking. It operates as a DNS server that re-routes tracking domains to a "black hole," thus preventing your devices from connecting to those servers. Unlike browser extensions, AdGuard Home protects all devices on your network without requiring individual configuration.

Why Choose AdGuard Home?

  • Network-wide ad blocking - protect all devices at once
  • Privacy-focused - no telemetry or cloud dependencies
  • Encrypted DNS - DNS-over-HTTPS and DNS-over-TLS
  • Lightweight - minimal resource usage with local caching

Install

Infrastructure as Code

This AdGuard Home instance is deployed using OpenTofu with custom Incus images. The infrastructure configuration manages container provisioning and persistent storage volumes.

Custom AdGuard Image

The AdGuard Incus image is built and maintained at forgejo.benoit.jp.net/Benoit/Laminar.

Infrastructure Configuration

The OpenTofu configuration provisions:

  • Incus instance running custom AdGuard Home image with macvlan networking
  • Two persistent storage volumes:
    • /opt/adguard/data - Query logs, statistics database, and filtered data
    • /var/backups/adguard - Backup storage

Macvlan Networking

The AdGuard container uses a macvlan network interface instead of the default Incus bridge. This gives the container its own IP address directly on the LAN, which is essential for a DNS server that needs to be reachable by all devices on the network.

Configuration File Location

The AdGuard configuration file (AdGuardHome.yaml) is located at /opt/adguard/AdGuardHome.yaml (outside the persistent data volume) and must be backed up separately during upgrades.

OpenTofu Configuration
resource "incus_storage_volume" "adguard_opt_adguard_data" {
  name = "adguard_opt_adguard_data"
  pool = incus_storage_pool.default.name
  config = {
    "initial.gid"  = "1001"
    "initial.uid"  = "1001"
    "initial.mode" = "700"
  }
}

resource "incus_storage_volume" "adguard_var_backups_adguard" {
  name = "adguard_var_backups_adguard"
  pool = incus_storage_pool.default.name
}

resource "incus_instance" "adguard" {
  name  = "adguard"
  image = "laminar.incus:adguard-0.107.71-1benoitjpnet"

  device {
    name = "opt_adguard_data"
    type = "disk"
    properties = {
      path   = "/opt/adguard/data"
      source = incus_storage_volume.adguard_opt_adguard_data.name
      pool   = incus_storage_pool.default.name
    }
  }

  device {
    name = "var_backups_adguard"
    type = "disk"
    properties = {
      path   = "/var/backups/adguard"
      source = incus_storage_volume.adguard_var_backups_adguard.name
      pool   = incus_storage_pool.default.name
    }
  }

  device {
    name = "eth0"
    type = "nic"
    properties = {
      nictype = "macvlan"
      parent  = "enp1s0"
    }
  }
}

Deploy Infrastructure

Apply OpenTofu configuration
tofu apply

Initial Configuration

After provisioning, access the AdGuard Home web interface to complete initial setup:

  1. Navigate to http://<container-ip>:3000
  2. Set admin username and password
  3. Configure upstream DNS servers (recommended: 1.1.1.1, 8.8.8.8)
  4. Set DNS bind interface (default: all interfaces, port 53)
  5. Add blocklists (AdGuard provides default lists, or add custom ones)

Recommended Blocklists

Popular community-maintained blocklists to consider:

Upgrade

Incus Image Upgrade

When upgrading to a newer Incus image version, follow these steps to migrate your data.

Critical: Tailscale Global Nameserver Warning

If you are using AdGuard as a Tailscale global nameserver, you must disable it in the Tailscale admin console before upgrading. Updates redeploy the container from scratch, which will:

  • Uninstall Tailscale from the container
  • Cause DNS resolution to fail for all Tailscale clients
  • The new container will receive a different Tailscale IP address

Backup current instance data before upgrading:

Enter Incus container
incus shell adguard

Backup AdGuard configuration

Backup configuration
cp /opt/adguard/AdGuardHome.yaml /var/backups/adguard/

Remove old machine from Tailscale (if using Tailscale)

Before upgrading, remove the old AdGuard machine from the Tailscale Admin Console. You'll add the new container as a fresh machine after the upgrade.

Deploy to new Incus image and restore data:

Update OpenTofu configuration

Edit your OpenTofu configuration file to update the image version:

resource "incus_instance" "adguard" {
  name  = "adguard"
  image = "laminar.incus:adguard-NEW-VERSION"  # Update this line
  # ...
}

Apply infrastructure changes

Provision new Incus container
tofu apply
Enter Incus container
incus shell adguard

Restore AdGuard configuration

Copy configuration from backup
cp /var/backups/adguard/AdGuardHome.yaml /opt/adguard/
Restart AdGuard service
systemctl restart AdGuardHome

Re-install Tailscale (if needed)

Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
Authenticate with new auth key
tailscale up --auth-key=<new-auth-key>

Generate a new auth key from the Tailscale Admin Console.

Get new Tailnet IP address
tailscale ip -4

Update Tailscale Configuration

  • Add the new Tailscale IP as a nameserver in Tailscale admin console
  • Re-enable the global nameserver with the new Tailscale IP (if previously enabled)
  • Test DNS resolution from multiple clients

Verification Required

After restore, verify AdGuard is working properly:

  • Check web interface accessibility at http://<container-ip>:3000
  • Verify DNS resolution: nslookup google.com <adguard-ip>
  • Test ad blocking with known ad domains
  • Confirm all custom settings are preserved
  • Check that blocklists are updating

Upgrade Complete

Your AdGuard Home instance is now running on the new Incus image!

Tailscale Integration

Why Tailscale + AdGuard?

Perfect combination: Access your private DNS server from anywhere while maintaining security and performance. No need to expose AdGuard to the internet! Use AdGuard as your DNS server even when connected to untrusted networks.

Independent Tailscale Node

Tailscale is installed directly inside the AdGuard container, making it an independent Tailscale node with its own identity on the Tailnet. This is preferable to relying on the Incus host's Tailscale, as it gives AdGuard a stable, dedicated Tailscale IP that doesn't depend on the host's networking configuration.

Enter Incus container
incus shell adguard

Install Tailscale

Download and install
curl -fsSL https://tailscale.com/install.sh | sh

Connect to your Tailnet

Authenticate
tailscale up --auth-key=<your-auth-key>

Verify installation

Check status
tailscale status
Get Tailscale IP
tailscale ip -4

Getting Authentication Keys

Generate auth keys in the Tailscale Admin Console:

  • Reusable: For multiple deployments
  • Ephemeral: For temporary testing
  • Preauthorized: Skip manual approval

Configure DNS in Tailscale:

  1. Navigate to Tailscale DNS Settings
  2. Under Nameservers, add your AdGuard Tailscale IP
  3. Optionally enable as Global nameserver to override client DNS settings
  4. Test from a Tailscale-connected device

Security considerations:

  • Use tagged devices in Tailscale for better access control
  • Configure ACLs to restrict which devices can use AdGuard as DNS
  • Enable MagicDNS in Tailscale for seamless name resolution

Troubleshooting

Common Issues & Solutions

DNS not resolving

Check AdGuard service
systemctl status AdGuardHome

Test DNS resolution
nslookup google.com <adguard-ip>
Check logs
journalctl -u AdGuardHome -f

Port 53 already in use

Check what's using port 53
ss -tlnp | grep :53

If systemd-resolved is using port 53:

Disable systemd-resolved DNS stub
sed -i 's/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf
systemctl restart systemd-resolved

Tailscale connectivity issues

Restart Tailscale
tailscale down && tailscale up

Check Tailscale status
tailscale status --peers
Verify IP assignment
tailscale ip -4

Ads not being blocked

  • Verify device is using AdGuard as DNS server (check device network settings)
  • Confirm blocklists are enabled and recently updated
  • Clear device DNS cache
  • Check if domain is in query log but not blocked
  • Test with different browser/device to isolate issue

Legitimate sites being blocked

  1. Check query logs in web interface to identify blocked domain
  2. Add to allowlist:
    @@||example.com^
    
  3. Or disable specific blocklist causing false positive

Blocklists not updating

Force update
curl -X POST "http://localhost:3000/control/filtering/refresh"

Check for network connectivity issues or blocklist URL accessibility.

Slow DNS resolution

  • Check upstream DNS servers are responding quickly
  • Monitor system resources (CPU/RAM) - AdGuard should use minimal resources
  • Reduce query log retention time in settings
  • Consider using faster upstream DNS providers (Cloudflare 1.1.1.1, Google 8.8.8.8)
  • Enable DNS caching in AdGuard settings

High memory usage

Reduce query log size
# Edit configuration file
nano /opt/adguard/AdGuardHome.yaml

# Set smaller values:
querylog:
  size_memory: 500
  interval: 24h

Restart service
systemctl restart AdGuardHome

Web interface slow to load

  • Clear query logs from settings
  • Reduce statistics retention period
  • Check system disk I/O performance

Production Ready

Your AdGuard Home setup is now optimized for production use with:

  • Infrastructure as Code deployment with OpenTofu and Incus
  • Comprehensive backup and restore procedures
  • Tailscale integration for secure remote access
  • Troubleshooting guides for common issues

Related Documentation: