Reverse Proxy a NodeJS App with Apache or NGINX
I have found it annoying to have my static web site sitting in the web root (i.e. port 80) and the rest server on another port. In order to have everything pointing back to port 80 we can set up a reverse proxy in our server directive.
Reverse Proxy
Whereas a regular proxy takes requests from the “inside” and decides how/where to pass them “out”, a reverse proxy takes requests from the “outside” and decides how/where to pass them “in”. If we can somehow identify requests destined for the node app then we can configure apache/nginx to forward them on.
You can launch a node server in the background and redirect the output into a log file like so:
nohup npm start 1> webapp-out.log 2>&1 &
Assuming that your app is using port 3000 (and the port is exposed), your endpoint is now listening for requests on port 3000 of your server.
In our example we’ll identify requests that should be forward on to our app by prepending /api
to each of the endpoints. For example if we had two endpoints /message
and /post
we would change them to /api/message
and /api/post
respectively. This can be thought of as a mount point for our app. Now we can tell the web server to forward on all requests that begin with /api
Apache
1) For Apache we’ll have to enable mod_proxy and mod_proxy_http
sudo a2enmod proxy sudo a2enmod proxy_http
2) Then add the following four lines to the
ProxyRequests Off ProxyPreserveHost On ProxyPass /api http://localhost:3000 ProxyPassReverse /api http://localhost:3000
3) Restart apache2:
sudo service apache2 restart
Now you can call your app by prepending /api to the url of your endpoint!
NGINX
1) NGINX doesn’t have anything like Apache’s ProxyPassReverse. Instead we’ll add this to the directives. On my server (Ubuntu0416) that’s in /etc/nginx/sites-available/
location /api { proxy_set_header X-Forwarded-Host $host:$server_port; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:3000; }
2) Restart nginx:
sudo service nginx restart
Now you can call your app by prepending /api
to the url of your endpoint!
A few side notes:
1) If you want all requests going to your node app you can leave out the mount point and simply use /
:
Apache
ProxyRequests Off ProxyPreserveHost On ProxyPass / http://localhost:3000 ProxyPassReverse / http://localhost:3000
NGINX
location / { proxy_set_header X-Forwarded-Host $host:$server_port; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:3000; }
2) If you don’t want to modify your node app you can use a rewrite rule to strip out the mount point from the request. You’d still need to call the endpoint like /api/message
but then the directive can rewrite the request to /message
and pass that on to your app.
Apache
coming soon…
NGINX
location /api { proxy_set_header X-Forwarded-Host $host:$server_port; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; rewrite ^/api(.*) $1 break; proxy_pass http://localhost:3000; }
Much of this info came from the this github gist and nginx.com