DEV Community

Pro
Pro

Posted on

How to Set Up Nginx Reverse Proxy for Next.js with a BasePath Under /market Without Causing Redirect Loops or 404s When Sharing Port 80 with Another Site?

Environment:

I'm using Ubuntu 22.04 LTS and Nginx 1.24.
I don't have a domain name; users are accessing the VPS directly via the public IPv4 address (e.g., http://203.0.113.7/...).
Another app called "lottery" is already served on port 80, with a separate server block configuration.
The new app I'm working on is a Next.js 16 app running behind PM2 on 127.0.0.1:3001, with a basePath set to /market (which means it expects URLs like /market, /market/listings, and so on).
I'm also running a Fastify API on 127.0.0.1:4000, which I want to expose as /market-api on port 80.

What Works:

When I curl the server directly, curl http://127.0.0.1:3001/market returns a 200 OK status.
Similarly, curl http://127.0.0.1:4000/... works fine locally.
Both processes are online, and I can see them running in PM2.

What Fails:

When trying to access the app from the browser, http://PUBLIC_IP:3001 and http://PUBLIC_IP:4000 both time out or give an ERR_EMPTY_RESPONSE. There's no firewall on the VPS (UFW is not enabled), so I suspect the provider's firewall only allows ports 22, 80, and 443. The goal is to serve everything via port 80 using Nginx.
I tried adding a reverse proxy in my Nginx config like this:

location /market/ {
    proxy_pass http://127.0.0.1:3001/market/;
    ...
}
Enter fullscreen mode Exit fullscreen mode

But when I visit http://PUBLIC_IP/market, I get an ERR_TOO_MANY_REDIRECTS. The responses keep alternating between /market and /market/ (it seems like a conflict between Next.js canonical URLs and Nginx's prefix rules).

After adjusting the proxy_pass directive, the page sometimes loads but shows a 404 from Next.js or appears unstyled (e.g., /_next/ requests go to the wrong path). I suspect this is due to the server block for requests with Host: PUBLIC_IP being misconfigured. The Nginx snippet is only in the "lottery" vhost, while the default_server handles requests to the IP address. I might also have an outdated build of the app without the basePath correctly set.
There's another issue (not strictly related to Nginx): the frontend was built with NEXT_PUBLIC_API_URL=http://PUBLIC_IP:4000, so when the app tries to make register/login calls to port 4000 from the browser, it fails when port 4000 isn't publicly open. I fixed this by using http://PUBLIC_IP/market-api instead, and configured Nginx with a location /market-api/ โ†’ 127.0.0.1:4000 proxy.

What I Want:

I'm looking for the correct Nginx configuration to achieve the following:

http://PUBLIC_IP/market and http://PUBLIC_IP/market/... should correctly route to Next.js with the basePath set to /market.
http://PUBLIC_IP/market-api/... should correctly route to the API running on port 4000 with the /market-api prefix removed.
I want to avoid any redirect loops between /market and /market/.
I need guidance on where to place these configurations, considering I have multiple listen 80 server blocks (the default one and the one for the named site). Should the configuration for /market live in the default_server block for IP access, or can one server_name cover both the raw IP and the domain?

Tags:
nginx, reverse-proxy, next.js, ubuntu, basepath, pm2

Top comments (1)

Collapse
 
art_light profile image
Art light

๐Ÿ‘