External Access Issue: Frontend Loads But Backend APIs Fail Through Nginx Reverse Proxy

Nginx Proxy Problem with External DNS Access

I’ve got an nginx setup that works perfectly when I access it from inside my local network. However, when I try to reach it from outside using my domain name (myapp.tech), the frontend loads just fine but none of the backend API calls work.

Here’s my current nginx configuration:

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
    worker_connections 2048;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format combined '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log combined;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 120;
    types_hash_max_size 4096;

    # Frontend server on port 3000
    server {
        listen 3000;
        server_name mysite.local www.mysite.local;

        root /var/www/dist;
        index index.html;

        location / {
            try_files $uri /index.html;
        }
    }

    # External domain server
    server {
        listen 80;
        server_name myapp.tech;

        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;

        root /var/www/dist;
        index index.html;

        location / {
            try_files $uri /index.html;
        }
    }

    server {
        listen 80 default_server;
        server_name myapp.tech _;
        root /;

        client_body_timeout 30s;
        client_header_timeout 30s;

        location /api-gateway/ {
            rewrite ^/api-gateway/(.*)$ /$1 break;
            proxy_pass http://10.0.1.45:9001/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        location /auth-service/ {
            rewrite ^/auth-service/(.*)$ /$1 break;
            proxy_pass http://10.0.1.78:8080/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

I tried merging the server blocks and setting the same document root for both but then nothing worked at all. I know the frontend and backend need different configurations but I’m not sure what I’m doing wrong here.

I’m pretty new to nginx so this might be something basic I’m missing. Any help would be great!

wait, are you testing the api calls from outside your network? if your frontend’s hitting localhost or internal ips, that wont work externally. what urls is your javascript actually calling? this might be a client-side routing problem, not an nginx issue.

You’ve got two server blocks listening on port 80 with the same server_name - that’s why nginx can’t decide which one to use and serves requests randomly. Just merge everything into one server block for myapp.tech. Move your /api-gateway/ and /auth-service/ locations into the same block that handles your frontend. Now nginx knows exactly where to route everything. I ran into this same mess deploying a React app with microservices. Put your API locations first with specific paths, then add the frontend location last with the catch-all try_files directive. This way nginx hits your API routes before falling back to the frontend.

your frontend server block is missing the api routes completely. the external domain block only serves static files, but all your api endpoints live in the default_server block. when nginx gets requests for myapp.tech, it routes them to the second server block that has zero proxy configs. either combine the blocks or copy your api locations into the myapp.tech server block.