AdguardTeam/AdGuardHome · critical
creating dns server: %w
Error message
creating dns server: %w
What it means
AdGuard Home could not create its DNS server instance (dnsforward.Server created via dnsServerNew with the TLS manager, HTTP registrar, and clients storage). Creation fails when the supplied parameters are invalid, e.g. bad TLS material registration or listener/socket problems on the requested addresses.
Source
Thrown at internal/home/dns.go:131
DNSFilter: globalContext.filters,
Stats: globalContext.stats,
QueryLog: globalContext.queryLog,
PrivateNets: parseSubnetSet(config.DNS.PrivateNets),
Anonymizer: anonymizer,
DHCPServer: globalContext.dhcpServer,
EtcHosts: hc,
LocalDomain: config.DHCP.LocalDomainName,
TLSManager: tlsManager,
}
err = initDNSServer(
ctx,
params,
httpReg,
confModifier,
)
if err != nil {
return fmt.Errorf("creating dns server: %w", err)
}
for _, route := range config.HTTPConfig.DoH.Routes {
mux.Handle(route, globalContext.dnsServer)
}
return nil
}
// initDNSServer initializes the [context.dnsServer]. To only use the internal
// proxy, none of the arguments are required, but params must be non-nil and
// valid. In other cases all the arguments also must not be nil. It also must
// not be called unless [config] and [globalContext] are
// initialized.
func initDNSServer(
ctx context.Context,
params dnsforward.DNSCreateParams,
httpReg aghhttp.Registrar,View on GitHub (pinned to b41aefbe51)
Solutions
- Check the wrapped error for the exact cause (bind: address already in use is typical)
- Free the conflicting port (e.g. disable systemd-resolved stub listener or stop the other DNS server)
- Verify listening interface IPs in config.yaml still exist on the host
- Run with CAP_NET_BIND_SERVICE or as root when binding ports <1024
Example fix
# before # port 53 occupied by systemd-resolved # after sudo mkdir -p /etc/systemd/resolved.conf.d echo -e '[Resolve] DNSStubListener=no' | sudo tee /etc/systemd/resolved.conf.d/adguard.conf sudo systemctl restart systemd-resolved
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: ensure DNS ports are free
import "net"
func portFree(network string, port int) bool {
l, err := net.Listen(network, fmt.Sprintf(":%d", port))
if err != nil { return false }
l.Close()
return true
}
// refuse to start if 53/853/443 conflict
for _, p := range []struct{n string; v int}{{"udp",53},{"tcp",53}} {
if !portFree(p.n, p.v) { return fmt.Errorf("port %d/%s busy", p.v, p.n) }
} Try / catch
if err := initDNS(ctx, params); err != nil {
var se *net.OpError
if errors.As(err, &se) && se.Op == "listen" {
log.Error("DNS port conflict — stop competing resolver", slogutil.KeyError, err)
}
return fmt.Errorf("creating dns server: %w", err)
} Prevention
- Disable systemd-resolved DNSStubListener on Linux before installing
- Reserve DNS/DoH/DoT ports exclusively for AdGuard Home in deployment configs
- Use systemd unit with CAP_NET_BIND_SERVICE instead of root
When it happens
Trigger: Calling initDNS when dnsServerNew fails: invalid listening addresses, port already in use, failure wiring the HTTP/Doh registrar or TLS manager into the dnsforward server constructor.
Common situations: Port 53 (or DoH/DoT/DoQ ports) already bound by systemd-resolved or another DNS server; invalid listen interface IPs in config; insufficient privileges to bind low ports.
Related errors
- creating new dns server: %w
- preparing dns server: %w
- starting dhcp server: %w
- cannot get network interfaces: %w
- collecting dns addresses: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/039d63a0f3dbd59c.
Report an issue: GitHub.