Nginx is failing to resolve external hostnames because its built-in DNS resolver configuration is missing or invalid.
The most common culprit is a missing resolver directive in your Nginx configuration, particularly in server or location blocks that make upstream requests using variables. Nginx needs to know which DNS servers to query.
Cause 1: Missing resolver Directive
- Diagnosis: Check your
nginx.confand any included configuration files for theresolverdirective within the relevantserverorlocationblocks. If it’s not there, or commented out, this is likely the issue.grep -r "resolver" /etc/nginx/ - Fix: Add a
resolverdirective pointing to valid DNS servers. For example, to use Google’s public DNS servers:resolver 8.8.8.8 8.8.4.4 valid=30s; - Why it works: This explicitly tells Nginx which DNS servers to use for resolving hostnames specified in directives like
proxy_passwhen those hostnames are variables. Thevalid=30spart caches DNS records for 30 seconds.
Cause 2: Invalid DNS Server IP Address
- Diagnosis: If you have a
resolverdirective, ensure the IP addresses specified are reachable from your Nginx server. You can test this withpingordig.ping 8.8.8.8 dig @8.8.8.8 google.com - Fix: Replace invalid IP addresses with known good ones, such as your internal DNS servers or public ones like
1.1.1.1(Cloudflare) or8.8.8.8(Google).resolver 1.1.1.1 1.0.0.1 valid=30s; - Why it works: Nginx can only use DNS servers that are accessible and responsive. Using correct IPs ensures the DNS resolution process can actually complete.
Cause 3: Firewall Blocking DNS Traffic
- Diagnosis: Even if the
resolverdirective is correct, a firewall on the Nginx server or an intermediate network device might be blocking UDP port 53, which is used for DNS queries.
Check your cloud provider’s security group rules as well.sudo ufw status verbose # If using UFW sudo iptables -L -n -v # If using iptables directly - Fix: Allow outbound UDP traffic on port 53 to your specified DNS servers. For
iptables:
If using UFW:sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT sudo iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT # Sometimes TCP is used as a fallbacksudo ufw allow out 53/udp sudo ufw allow out 53/tcp - Why it works: DNS resolution relies on network communication. Opening the necessary ports ensures Nginx can send its DNS queries and receive responses.
Cause 4: resolver Directive in the Wrong Context
- Diagnosis: The
resolverdirective must be placed in a context where it can be used by other directives that require name resolution. This is typically within anhttpblock,serverblock, orlocationblock that performs upstream requests (e.g.,proxy_pass,uwsgi_pass,fastcgi_pass). If it’s only in amaincontext or a context that doesn’t perform lookups, it won’t be effective.# Incorrect placement (won't affect proxy_pass in a location block) http { resolver 8.8.8.8; server { ... } } # Correct placement http { server { resolver 8.8.8.8; location / { proxy_pass http://my_backend; } } } - Fix: Move the
resolverdirective into thehttp,server, orlocationblock that contains the directive requiring name resolution (likeproxy_pass). - Why it works: Nginx processes directives within their scope. Placing
resolverin the same scope as or a parent scope of the name-resolving directive ensures Nginx can find and use the DNS server configuration when needed.
Cause 5: DNS Server Not Responding or Overloaded
- Diagnosis: If your specified DNS servers are intermittently unavailable or overloaded, Nginx might fail to resolve names. This can be harder to diagnose directly from Nginx logs. Check the health of your DNS infrastructure.
- Fix: Switch to more reliable DNS servers, or investigate and fix issues with your current DNS servers.
resolver 9.9.9.9 valid=30s; # Example: Switching to Quad9 - Why it works: A stable DNS resolution service is critical for Nginx to translate hostnames into IP addresses for upstream connections.
Cause 6: Using Hostnames in proxy_pass that are Not Resolvable at Nginx Startup (and resolver is missing)
- Diagnosis: If you use a hostname in
proxy_passthat Nginx tries to resolve immediately upon loading the configuration (e.g., if the hostname is static and not a variable), andresolveris not defined, it will fail.# This will fail if resolver is not defined, as Nginx tries to resolve 'my-app-service' on config load location / { proxy_pass http://my-app-service:8080; } - Fix: Ensure the
resolverdirective is present in the sameserverorlocationblock.location / { resolver 8.8.8.8; proxy_pass http://my-app-service:8080; } - Why it works: Nginx needs the
resolverdirective to perform the lookup formy-app-serviceto translate it into an IP address that it can then connect to.
After fixing the resolver directive and ensuring DNS is functional, the next error you’ll likely encounter is related to the actual upstream service not responding, or a TLS handshake failure if you’re using HTTPS for upstream connections.