Skip to content

AdGuard Home: from web UI to client filtering

  • AdGuard Home owns OpenWrt port 53; the web UI is on 3000.
  • dnsmasq moves to 5353 and keeps serving DHCP.
  • DHCP clients receive 192.168.2.1 as DNS.
  • A custom filter rule blocks a test domain while normal names still resolve.
  • The data disk, AGH config and filter survive a reboot.
  • PVE 9.2.2 single NIC; OpenWrt 25.12.6 x86_64 VM 201 (1GB RAM, 2GB data disk).
  • WAN net0 on vmbr0 (DHCP); LAN net1 on an isolated vmbr2 (192.168.2.0/24).
  • AGH 0.107.79 from the OpenWrt apk feed.
  • Do not share one bridge between two OpenWrt VMs that both run DHCP: in this lab VM 200 is on vmbr1 (192.168.1.0/24), so VM 201 must use vmbr2 (192.168.2.0/24). Otherwise a client may receive a lease from the wrong subnet.
Physical portPVE bridgeVirtual NICOpenWrt interfaceRole
nic0vmbr0net0wan DHCPupstream 192.168.50.1
—vmbr2net1lan 192.168.2.1AGH + DHCP clients
Port Component Role
53 AdGuard Home client DNS, filtering, upstream forwarding
3000 AdGuard Home web UI
5353 dnsmasq DHCP and local DNS; no longer on 53

Do not bind AGH and dnsmasq to 53 at the same time. Do not point DHCP option 6 at an address that is not listening on 53.

Router shellBack up config and prepare the data disk
Terminal window
cp /etc/config/dhcp /etc/config/dhcp.bak.$(date +%F)
cp /etc/config/adguardhome /etc/config/adguardhome.bak.$(date +%F) 2>/dev/null || true
cat /etc/config/dhcp

Keep console or LAN access to OpenWrt. Do not make the only management path depend on the DNS you are changing.

ExpectedYou can restore dnsmasq/AGH configuration.

AdGuard Home first-run welcome page with Get Started and Step 1/5
The AGH 0.107.79 first-run welcome page. Click Get Started to open the setup wizard. Captured in a temporary lab; the Chinese language is selected.
Router shellInstall AGH, data-disk tools and fstab support
Terminal window
apk update
apk add adguardhome block-mount e2fsprogs

e2fsprogs provides mkfs.ext4; block-mount provides the fstab service. A local OpenWrt mirror is fine, but packages must still pass signature checks.

Expectedadguardhome, block-mount and e2fsprogs are installed.

Router shellFormat and persist the data disk

Only run this on a lab data disk you have confirmed is empty:

Terminal window
mkfs.ext4 -F /dev/sdb
mkdir -p /opt/agh
mount /dev/sdb /opt/agh
block info /dev/sdb

Use the UUID printed by block info. In LuCI Mount Points, set that disk’s target to /opt/agh and enable it; or find the matching @mount[n] from the CLI:

Terminal window
uci show fstab
# find the @mount[n] whose uuid is <your-UUID>
uci set fstab.@mount[n].target='/opt/agh'
uci set fstab.@mount[n].enabled='1'
uci commit fstab
/etc/init.d/fstab enable
block mount
mount | grep /opt/agh

This lab used the auto-detected fstab.@mount[2] for the 2GB data disk; changing its target to /opt/agh and enabling it worked. Do not copy [2]; match your UUID.

Expected/opt/agh is on a separate disk and survives reboot.

Router shellMove dnsmasq to 5353
Terminal window
uci set dhcp.@dnsmasq[0].port='5353'
uci commit dhcp
/etc/init.d/dnsmasq restart
netstat -lnp | grep -E ':53|:5353'

Clients cannot resolve on 53 until AGH starts.

ExpectedPort 53 is free and DHCP still works.

Router shellStart AGH and complete first-run setup
Terminal window
uci set adguardhome.config.work_dir='/opt/agh/work'
uci commit adguardhome
mkdir -p /opt/agh/work
chown -R adguardhome:adguardhome /opt/agh /etc/adguardhome
/etc/init.d/adguardhome enable
/etc/init.d/adguardhome start
sleep 3
netstat -lnp | grep -E ':3000|:53'

Open http://192.168.2.1:3000/ and set:

  • web port 3000;
  • DNS port 53;
  • an admin username/password;
  • upstream DNS 192.168.50.1 for this lab;
  • disable DNSSEC if the upstream does not validate it.

If you have no browser, use the AGH setup API; never commit the admin password.

ExpectedThe web UI is reachable on 3000.

Router shellAdvertise AGH through DHCP
Terminal window
uci add_list dhcp.lan.dhcp_option='6,192.168.2.1'
uci commit dhcp
/etc/init.d/dnsmasq restart
uci show dhcp.lan | grep dhcp_option

Changing the dnsmasq port alone may stop some clients from receiving DNS; set option 6 explicitly.

ExpectedClients receive 192.168.2.1 as DNS.

LuCIAdd a deterministic filter rule

In Filters → Custom filtering rules add:

||blocked.example^

This is a reserved test domain. Add maintained filter lists later for real use. Verify with nslookup, not by “the page looks broken”.

Expectedblocked.example returns 0.0.0.0; normal names still resolve.

AdGuard Home dashboard with DNS query and filtering statistics
The dashboard after setup. Zero queries immediately after configuration is normal; verify the DNS port and upstream first.
Router shellCheck ports and local resolution
Terminal window
netstat -lnp | grep -E ':53|:3000|:5353'
nslookup blocked.example 192.168.2.1
nslookup openwrt.org 192.168.2.1

Expected: blocked.example returns 0.0.0.0 (IPv6 may also show ::); openwrt.org returns a real address.

ExpectedAGH listens on 53/3000; dnsmasq on 5353.

ComputerVerify from a DHCP client
Terminal window
ip addr show
ip route
cat /etc/resolv.conf
nslookup blocked.example
nslookup openwrt.org

If the client DNS is not 192.168.2.1, go back to DHCP option 6 and the dnsmasq port.

ExpectedThe client gets 192.168.2.x and DNS 192.168.2.1.

Router shellRe-verify after reboot
Terminal window
reboot

After reboot:

Terminal window
mount | grep /opt/agh
netstat -lnp | grep -E ':53|:3000'
nslookup blocked.example 192.168.2.1
nslookup openwrt.org 192.168.2.1

ExpectedThe data disk mounts, AGH starts, and the rule survives.

Terminal window
logread | grep -i adguard | tail -50
netstat -lnp | grep ':53'
/usr/bin/AdGuardHome --check-config -c /etc/adguardhome/adguardhome.yaml

If dnsmasq still owns 53, confirm dhcp.@dnsmasq[0].port='5353'. For a bad config, restore the backup:

Terminal window
cp /etc/adguardhome/adguardhome.bak.YYYY-MM-DD /etc/adguardhome/adguardhome.yaml
/etc/init.d/adguardhome restart

Temporarily return DNS to dnsmasq:

Terminal window
uci set dhcp.@dnsmasq[0].port='53'
uci -q delete dhcp.lan.dhcp_option
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/adguardhome stop

Restore basic resolution first, then debug AGH one layer at a time.

Terminal window
mount | grep /opt/agh
block info /dev/sdb
logread | grep -i fstab

Check the fstab UUID, target and enabled flag; mount manually, then restart AGH.

AdGuard Home filters page showing the default blocklists
The filters page lists enabled blocklists. This capture shows only the defaults, with no third-party subscription; add a test rule separately.
  • Confirm the client actually uses AGH as DNS.
  • Confirm the rule is under Custom filtering rules, not a subscription.
  • Query AGH directly: nslookup blocked.example 192.168.2.1.
  • Browser or OS DoH can bypass AGH.
  • Environment: PVE 9.2.2 single NIC; OpenWrt 25.12.6 VM 201 (1GB/2GB data disk); AGH 0.107.79.
  • Ports: AGH 53 + web 3000; dnsmasq 5353; DHCP option 6 192.168.2.1.
  • Client: DHCP 192.168.2.166/24, DNS 192.168.2.1; blocked.example → 0.0.0.0, openwrt.org → 64.226.122.113.
  • Reboot: /opt/agh mounted via fstab; AGH, dnsmasq and filtering rules recovered; web returned 302.
  • Not tested: real browser UI interaction, external subscription lists, physical LAN clients, IPv6, long-run stability.
  • This is an E2 lab record; it has not been independently reviewed or tested on a physical LAN.
  • Recipe: tests/recipes/agh-25.12-vm201.md; environment notes: docs/agh-e2-run.md.
  • Update testedVersions when the package/version changes; do not copy init scripts across firmware versions.

Sources

Router.Homes

Independent OpenWrt notes. Every page states the firmware, device, package manager and way back.

Icons: Solar by 480 Design, CC BY 4.0