AdguardTeam/AdGuardHome · error

constructing tls config: %w

Error message

constructing tls config: %w

What it means

newServerConfig could not build the TLS configuration for the DNS server. newDNSTLSConfig combines certificate data for DNS-over-TLS/HTTPS/QUIC plus optional DNSCrypt settings; failure means certificates are missing/invalid or the DNSCrypt sub-configuration failed.

Source

Thrown at internal/home/dns.go:275

// newServerConfig converts values from the configuration file into the internal
// DNS server configuration.  All arguments must not be nil.
func newServerConfig(
	dnsConf *dnsConfig,
	clientSrcConf *clientSourcesConfig,
	dohConf *doHConfig,
	tlsManager aghtls.Manager,
	httpReg aghhttp.Registrar,
	clientsContainer dnsforward.ClientsContainer,
	confModifier agh.ConfigModifier,
) (newConf *dnsforward.ServerConfig, err error) {
	hosts := aghalg.CoalesceSlice(dnsConf.BindHosts, []netip.Addr{netutil.IPv4Localhost()})

	fwdConf := dnsConf.Config
	fwdConf.ClientsContainer = clientsContainer

	intTLSConf, err := newDNSTLSConfig(tlsManager, hosts)
	if err != nil {
		return nil, fmt.Errorf("constructing tls config: %w", err)
	}

	newConf = &dnsforward.ServerConfig{
		UDPListenAddrs:         ipsToUDPAddrs(hosts, dnsConf.Port),
		TCPListenAddrs:         ipsToTCPAddrs(hosts, dnsConf.Port),
		Config:                 fwdConf,
		TLSConf:                intTLSConf,
		TLSAllowUnencryptedDoH: dohConf.InsecureEnabled,
		UpstreamTimeout:        time.Duration(dnsConf.UpstreamTimeout),
		ConfModifier:           confModifier,
		HTTPReg:                httpReg,
		LocalPTRResolvers:      dnsConf.PrivateRDNSResolvers,
		UseDNS64:               dnsConf.UseDNS64,
		DNS64Prefixes:          dnsConf.DNS64Prefixes,
		UsePrivateRDNS:         dnsConf.UsePrivateRDNS,
		ServeHTTP3:             dnsConf.ServeHTTP3,
		UseHTTP3Upstreams:      dnsConf.UseHTTP3Upstreams,
		ServePlainDNS:          dnsConf.ServePlainDNS,

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Verify certificate_chain and private_key paths exist and are readable by the service user
  2. Validate the pair matches: openssl x509 -noout -modulus -in cert.pem | openssl md5 vs openssl rsa -noout -modulus -in key.pem | openssl md5
  3. Renew or re-issue the certificate if expired or corrupt
  4. If DNSCrypt is enabled, check the wrapped error for the DNSCryptConfig sub-error and fix that file first

Example fix

# check cert validity
openssl x509 -in cert.pem -noout -dates -subject
# regenerate self-signed pair if broken
openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \
  -keyout key.pem -out cert.pem -subj '/CN=dns.example.com'
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate TLS material before enabling DoT/DoH/DoQ
func certPairOK(certPath, keyPath string) error {
    cb, err := os.ReadFile(certPath); if err != nil { return err }
    kb, err := os.ReadFile(keyPath); if err != nil { return err }
    c, _ := tls.X509KeyPair(cb, kb)
    if c.Certificate == nil { return fmt.Errorf("cert/key mismatch or unparseable") }
    return nil
}

Try / catch

if _, err := newDNSTLSConfig(tlsManager, hosts); err != nil {
    return nil, fmt.Errorf("constructing tls config: %w", err) // inspect for cert vs dnscrypt cause
}

Prevention

When it happens

Trigger: Enabling DoT/DoH/DoQ with invalid, missing, or unreadable certificate files (certificate chain, private key), expired/unparseable PEM data, or a DNSCrypt config error surfacing through newDNSTLSConfig.

Common situations: paths in tls config pointing to moved/deleted cert files, cert and key mismatched, cert expired after Let's Encrypt renewal script failed, or wrong file permissions.

Understand the failure class

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/02150a643ea37993. Report an issue: GitHub.