Setup nginx as Reverse Proxy for Node.js app under a subpath
nginx is a simple yet powerful HTTP server, Reverse proxy,
Load Balancer, etc. My favorite part about nginx is how easy it is to setup and
configure with its simple nginx.conf
file. I haven’t worked on backend
services much but I wanted to play around with nginx for a side project and
needed to serve static assets (html, css, js etc) from a directory for requests
on /
route as well as forward requests on /api/*
route to an api service
(Node.js).
http://mydomain.tld/styles.css 👉 / # Serve static files from a directory
http://mydomain.tld/api/users 👉 /api/* # Proxy requests to Node.js service as /*
Here’s the nginx.conf
from (/etc/nginx/nginx.conf
) that serves static
assets. The static asset files are placed in /usr/share/nginx/html
directory.
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
http {
server {
listen 3333;
listen [::]:3333;
location / {
root /usr/share/nginx/html;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
}
}
}
I have a simple Node.js API service running on 8080
port.
const fastify = require("fastify")({ logger: true });
fastify.get("/", async (request, reply) => {
return { hello: "world" };
});
const start = async () => {
try {
await fastify.listen({ port: 8080 });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
We can use location {}
to handle incoming requests to /api
.
location ^~ /api {
# value can be anything that you want to be proxied
proxy_pass http://localhost:8080/;
}
^~
ensures requests starting with /api
are handled in this location
block
and a trailing slash /
to the proxied path ensures requests are forwarded
under /
path to our Node.js service (http://localhost:8080/👈
).
i.e Request /api/xyz/
is forwarded as /xyz
to Node.js service.
Note: You can ignore adding trailing slash if you are handling all requests as
is inside Node.js service under /api/*
path. For example:
fastify.get("/api/*", () => {});
Let’s test both the services with a simple curl -v
command
Since we are proxying Node.js service here, Node.js sees all requests as though
they were coming from nginx. We can also add additional proxy headers in nginx
if we want them to be forwarded to our proxied node.js server using
proxy_set_header
.
location ^~ /api {
proxy_pass http://localhost:8080/;
proxy_set_header Host $http_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;
}
Complete nginx.conf
config:
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
http {
server {
listen 3333;
listen [::]:3333;
location / {
root /usr/share/nginx/html;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
}
location ^~ /api {
proxy_pass http://localhost:8080/;
proxy_set_header Host $http_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;
}
}
}
Further Reading / References: