NGINX: How to proxy http(s) traffic to one server and ws(s) traffic to another?

I'm new to nginx and how it handles locatoins, and was hoping to get help for a problem I'm having:

On the same server I have an Apache web server and a websocket server. Apache works on port 8080 and the websocket server works on 9090. I would like to put an nginx proxy in front so that http/https traffic gets proxied to apache and the ws/wss traffic gets proxied to the websocket server.

I have the following configuration:

location /ws* {
    proxy_pass ws://127.0.0.1:9090;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
    proxy_pass http://127.0.0.1:8080;
}

This works fine, but the problem I'm facing is that all ws* requests also get redirected to the apache server whilst I only want them to be redirected to the ws server. I've read that nginx takes only the first location that matches, but this seems to be wrong in my case.

So the question is how do I proxy http(s) traffic ONLY to apache and ws(s) traffic ONLY to the web socket server?


The location syntax you have doesn't seem like what you are trying to do.

If you are trying to do regex with the location URL, the proper syntax is:

location ~ /ws.* {

If you are trying to do everything under ws directory, you should have:

location /ws/ {

You may want to review the documentation for more information on location. http://nginx.org/en/docs/http/ngx_http_core_module.html#location