35

Is it possible to set resolver address in nginx proxy configuration from /etc/resolv.conf?

It can be useful for example in docker or in virtualenvironment.

5 Answers 5

23

Unfortunately there's no easy way to do this because nginx use it's own resolver implementation. The two solutions I see are :

1) You generate the resolver list from a script and include it, e.g. :

echo resolver $(awk 'BEGIN{ORS=" "} $1=="nameserver" {print $2}' /etc/resolv.conf) ";" > /etc/nginx/resolvers.conf

http {

    include resolvers.conf;

}

2) You recompile nginx with a third party module like the (very) experimental perl module and write a variable handler :

http {

    perl_modules perl/lib;
    perl_set $resolvers '

        sub {
            return system("awk BEGIN{ORS=\" \"} /nameserver/{print \$2}" /etc/resolv.conf");
        };

    resolver "$resolvers";
}

Now, if you are a hell of a C coder (prepare your eyes for some blood), you can still write an alternative patch or module to make it work this way.

2
  • thanks for the nice script (1)!
    – SScholl
    Apr 26, 2021 at 13:22
  • Do you know which name servers Nginx uses by default? Sep 11, 2022 at 18:29
14

If you're using the Openresty version of nginx then you can use their special local argument to the resolver directive which when set to local=on, means the standard path of /etc/resolv.conf will be used by the resolver (for more details see Openresty resolver docs):

resolver local=on;
1
  • Thank you! This indeed works with OpenResty. For the reference this is the container version I tried it with: openresty/openresty:1.15.8.2-6-buster-fat. I really like this solution since it is environment agnostic and does not require any fragile scripting tricks. Feb 19, 2020 at 6:12
12

For Kubernetes, you can simply add kube-dns as resolver.
The FQDN of the resolver is based on the namespace, by default kube-system.
You might have to change the FQDN to accommodate your configuration.

location / {
   ...
   resolver kube-dns.kube-system.svc.cluster.local;
   ...
}

You can read more about DNS and services here https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/

2
9

For Docker users, solution found here:

Heres a workaround for people using Docker.

export NAMESERVER=`cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' '`

What this does is take all the nameserver entries from /etc/resolv.conf and print them in a line, so you can use them with nginx's resolver directive. Your Dockerfile will need to have a custom script for the entrypoint that generates the config file and then starts nginx. Lets say you have a file called nginx.conf.template that looks something like:

...snip...
http {
  server {

    resolver $NAMESERVER valid=10s;

    ...snip....  
    }
  }
}

Your startup script can then use the envsubst program to generate an nginx.conf and then start nginx. eg:

#!/bin/bash
if [ "$NAMESERVER" == "" ]; then
    export NAMESERVER=`cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' '`
fi

echo "Nameserver is: $NAMESERVER"

echo "Copying nginx config"
envsubst '$NAMESERVER' < /nginx.conf.template > /nginx.conf

echo "Using nginx config:"
cat /nginx.conf

echo "Starting nginx"
nginx -c /nginx.conf -g "daemon off;"

NOTE that in docker this tend to result in the same file, as by default the docker embedded DNS server is 127.0.0.11, see this answer to Docker Network Nginx Resolver.

4
  • 6
    Awk, learn it, it's a fantastic tool for text munging: export NAMESERVER=$(awk '/^nameserver/{print $2}' /etc/resolv.conf). No need for cat, grep or tr in there.
    – j0057
    Jul 3, 2018 at 8:16
  • this doesn't work on Kubernetes though.
    – Kim
    Aug 7, 2019 at 20:24
  • I used NGX_DNS_RESOLVER=$(awk '/nameserver/{a=(a?a" "$2:$2)} END{print a}' /etc/resolv.conf 2> /dev/null)
    – samm
    Feb 26, 2021 at 6:17
  • 1
    For docker users, I recommend putting exec at the front of the bottom line. It makes nginx PID 1, so that commands like docker kill --signal=HUP <container> (reload config) work.
    – mikedep333
    Oct 31, 2022 at 18:07
2

If your system uses resolvconf (as many virtual machines do, but unfortunately Docker does not, see man 8 resolvconf), you might create the nginx resolvers.conf (as in the other answer) in /etc/resolvconf/update-libc.d/nginx. This behaves nicely even in the rare case of dynamic change of resolvers.

#!/bin/sh
conf="resolver $(/usr/bin/awk 'BEGIN{ORS=" "} $1=="nameserver" {print $2}' /etc/resolv.conf);"
[ "$conf" = "resolver ;" ] && exit 0
confpath=/etc/nginx/conf.d/resolvers.conf
if [ ! -e $confpath ] || [ "$conf" != "$(cat $confpath)" ]
then
    echo "$conf" > $confpath
    service nginx reload >/dev/null
fi
exit 0

Some linux distributions include /etc/nginx/conf.d/*.conf in their default configuration. Reload is usually ignored when service is not running. Notice the script may be run without /usr/bin in PATH, so you may need absolute path to awk.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .