What Should I Set As My Resolver For A Nginx Reverse Proxy In App Platform

Posted August 22, 2021 902 views
NginxDigitalOcean App Platform

Currently, I am attempting to deploy nginx as a reverse proxy for my App Platform app. I have a web service deployed named web on port 80 and from the proxy service I am able to reach it using curl http://web (get the HTML back and everything). My issue is that I cannot seem to resolve it in nginx due to not knowing the correct address for the resolver. So for example, my configuration for my default location looks like this:

location ~* ^/(.*) {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        resolver ${RESOLVER} valid=10s;
        set $web_upstream http://web;
        proxy_pass $web_upstream/$1$is_args$args;

Where ${RESOLVER} is what I’m setting for my resolver address. I’ve tried the IP from the nameserver inside /etc/resolv.conf ( and I get invalid UDP DNS response) as well as a few others but nothing seems to work and I cannot find documentation anywhere stating how DNS inside App Platform works.

Any ideas?

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Submit an Answer
1 answer

This configuration looks to be missing the search domain. web is not a fully qualified domain, but instead a local domain.

You can build a fully qualified domain by taking the first search domain from /etc/resolv.conf and adding it as a suffix to the component name. Normal resolvers (such as Linux standard library, gethostbyname, and virtually all programming runtimes) do this automatically. It’s unclear why, but nginx looks to leverage this configuration for upstream declarations, but not dynamic resolves.

On App Platform, the search address typically has a format like app-$APP_UUID.svc.cluster.local, yielding a fully qualified name like$APP_UUID.svc.cluster.local. This address is only valid against the internal DNS resolver (obtained from the nameserver line in /etc/resolv.conf. The nameserver and search fields in /etc/resolv.conf are dynamic and WILL change between deployments. These values should be parsed programmatically at deploy time; hard coded values WILL cause failures. Again, most resolvers will use the POSIX standard /etc/resolv.conf configuration; nginx dynamic resolution seems to be a rare exception.

You may be able to bypass this headache by using the upstream directive in nginx, which uses the standard resolver configuration in /etc/resolv.conf. The upstream mechanism only resolves the name (web) at startup (or reload). This is safe because the resolved address (for web) is stable for the life of the nginx instance. If multiple instances of web are present a local layer-4 load-balancer will balance connections across the web instances.

  • That might work if you can force the nginx to be the last service to start on the app platform and maybe add something to force it to restart if another service restarts so it can re-resolve the addresses (which is normally why you would want a resolver so you don’t have to worry about that).

  • @cbaker I did everything you said, parsing the nameserver and search domain from /etc/resolv.conf and updating the nginx.conf file accordingly during the deployment step, giving me something like this:

    server {
        server_name myapp.*;
        location ~ {
            resolver valid=60s; # <= Parsed from /etc/resolv.conf
            set $upstream ""; # <= Parsed from /etc/resolv.conf; "myapp" is the component name
            proxy_pass $upstream;

    The service deploys fine, but when I try to reach, I’m getting a 502 and the following error in /var/log/nginx/error.log:

    [error] 23#23: *32 could not be resolved (3: Host not found), client:, server: myapp.*, request: "GET / HTTP/1.1", host: ""

    What am I missing? The myapp component is a static component btw, in case that make a difference.