Nginx – redirect based on port number

load balancingnginx

I want to use nginx as a load balancer to distribute load over 2 servers. I have done this in the past, but am stuck with a specific requirement.

I need to forward the requests onto the servers (from the nginx load balancer) based on the incoming port number, but do not want to have to enter every single entry in the /etc/nginx/conf.d/load-balancer.conf file and was wondering if there was a way to regex it based on the incoming port number?

At the moment, as an example, I have this which works correctly:

# Port 444
upstream backend444 {
   server 10.0.0.1:444;
   server 10.0.0.2:444;
}

server {
   listen 444 ssl;
   server_name domain.com;
   ssl_certificate /etc/letsencrypt/live/domain.com/cert.pem;
   ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
   location / {
      proxy_pass https://backend444;
   }
}

# Port 445
upstream backend445 {
   server 10.0.0.1:445;
   server 10.0.0.2:445;
}
server {
   listen 445 ssl;
   server_name domain.com;
   ssl_certificate /etc/letsencrypt/live/domain.com/cert.pem;
   ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
   location / {
      proxy_pass https://backend445;
   }
}

If there a way for me to regex or use variables for the port numbers so that I can just match the port number and redirect the request on with the same port number?

Failing that, is there any other way to do this? I have many ports to add. The incoming port just needs to go to the same port on the destination server.

Thanks.

Best Answer

First: I don't believe that the listen directive of nginx can be set dynamically at its own configuration. You should end up with having these configuration as a static content into the configuration file ( /etc/nginx/conf.d/load-balancer.conf )

Second: How to get this file to be filled without you to do it manually ?

a) If you use ansible as a configuration management, you can do it with jinja2 ( the templating engine used by ansible )

b) You can create a shell script to fill the content of the nginx config file. Here is an example of what you can do:

#!/bin/bash

# Source file ( List of backend ports )
FILE="${1}"

# Loop through each line from the file and parse the values
for PORT in $( cat ${FILE} ); do

    cat >> /tmp/nginx_lb_config_file <<EOF
# Begin Port ${PORT}
upstream backend${PORT} {
    server 10.0.0.1:${PORT};
    server 10.0.0.2:${PORT};
}
server {
    listen ${PORT} ssl;
    server_name domain.com;
    ssl_certificate /etc/letsencrypt/live/domain.com/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
    location / {
        proxy_pass https://backend${PORT};
    }
}

# End Port ${PORT}


EOF
done

Save this on a file called, say filltheconfig.sh and set the execution bit on the file ( chmod +x filltheconfig.sh )

Note: The source file contains only one port per line. Example:

user@host:~$ cat sourcefile
444
445
446
447

Hope this help! :)