DEV Community

Cover image for Ultimate Guide to Using NGINX as a Reverse Proxy and Load Balancer:Best Practices and Tips
KUSEH SIMON WEWOLIAMO
KUSEH SIMON WEWOLIAMO

Posted on

Ultimate Guide to Using NGINX as a Reverse Proxy and Load Balancer:Best Practices and Tips

What is NGINX and Why Use It?

Nginx (pronounced "engine-X) is an open-source high-performance HTTP web server that can also be used as a reverse proxy. Other uses cases of nginx include Load Balancing, API Gateway,SSL/TLS Termination and Content caching. Over the years Nginx has grown to become one of the most popular and widely used webserver for its high performance, scalability, and low resource usage. Some companies that use Nginx include Uber Netflix,Instagram,Airbnb etc.

This article will demonstrate how to configure and use Nginx as a Reverse proxy and a Load Balancer. We will configure nginx as reverse proxy and load balancer to distribute traffic between three django applications. Before we dive into the details of configuring nginx , lets first understand what reverse proxy and load balancer are.

Understanding Reverse Proxy and Load Balancing

What is a Reverse Proxy? A reverse proxy( proxy means to act on behalf ) is a special type of server that sits in front of other webservers and directs requests from clients (such as web browsers) to those servers. Reverse proxies are often used to improve security, performance, and dependability.

What is Load Balancing?Load balancing is a technique of distributing computational workloads between two or more computing nodes. Load balancing is often employed to evenly distribute network traffic among several servers. This reduces the strain on each server and makes the servers more efficient, speeding up performance and reducing latency.

Setting Up NGINX as a Reverse Proxy and Load Balancer

Prerequisites
To follow this guide, you should have

  1. A Linux OS, preferably ubuntu.
  2. Basic knowledge of using the terminal.
  3. Docker Installed. The Official documentation will guide you through how to install Docker
  4. Nginx Installed . You can follow the official Documentation to install Nginx on your preferred OS.

Step 1 Setting up docker Containers
We will be setting up 3 docker Containers to server as the backend servers.
The docker containers run will be running a django blog application.

  • 1. Create a directory on your computer for the project:
  mkdr projects/DjangoApps
Enter fullscreen mode Exit fullscreen mode
  • 2. cd into the directory you created
  cd projects/Djangoapps
Enter fullscreen mode Exit fullscreen mode
  • 3. Create a docker-compose.yml file
 touch docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

open the docker-compose.yml file and past this code

version: '3'

services:
  app1:
    image: kodecapsule/django-blog-app:dark-server
    container_name: dark-server
    ports:
      - "8000:8000"
    restart: always

  app2:
    image: kodecapsule/django-blog-app:green-server
    container_name: green-server
    ports:
      - "8001:8000"
    restart: always

  app3:
    image: kodecapsule/django-blog-app:blue-server
    container_name: blue-server
    ports:
      - "8002:8000"
    restart: always
Enter fullscreen mode Exit fullscreen mode

The above docker-compose.yml file setsup three Docker containers running different versions of the same Django blog application,
each tagged with a different server name (dark-server, green-server, blue-server) from the Docker Hub repository kodecapsule/django-blog-app.
Each container is mapped to a unique host port (8000, 8001, 8002) so they can be accessed individually, while internally all containers listen on port 8000. The restart: always policy ensures that the containers automatically restart if they fail or if the Docker service restarts.

  • 4. Run the docker containers
 docker-compose up
Enter fullscreen mode Exit fullscreen mode

This will download and run three docker containers dark-server, green-server and blue-server.Open your browser and make sure you are able to access the three applications

dark-server dark-server.
green-server
green-server.
blue-server
blue-server

Step 2 Configure NGINX as a Reverse Proxy
Nginx configuration is always in nginx.conf file. The nginx.conf file is the main file that is mainly used to configure nginx behavior.
By default this file is located in /etc/nginx/nginx.conf .

  worker_processes 1; 
  events{
     worker_connections 1024;
  }
  http{
      include /etc/nginx/mime.types;

      upstream django_servers {
              server localhost:8000;
              server localhost:8001;
              server localhost:8002;
          }  

      server {
        listen 8080;
        # Proxy requests to Django backend
        location / {
            proxy_pass http://django_servers;
            proxy_set_header Host $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;

            # Handle timeouts
            proxy_connect_timeout 60;
            proxy_read_timeout 60;
        }

    }


  }

Enter fullscreen mode Exit fullscreen mode

The server context defines all the configuration needed for nginx to act as a reverse proxy.The NGINX configuration above defines a server with the listen directive listening on port 8080.
To configure Nginx as a reverse proxy the proxy_pass directive is used which enables nginx to forward all incoming requests to a group of backend Django servers. It sets headers like Host, X-Real-IP,
and X-Forwarded-For to pass client information to the backend servers, preserving the original request details.

Additionally, it configures timeout settings (connect and read) to control how long NGINX waits for a response from the backend servers, ensuring smooth handling of slow responses or potential server delays.

Step 3 Configure Nginx as a Load Balancer

configure nginx as load bala using round-robin

    upstream django_servers {
              server localhost:8000;
              server localhost:8001;
              server localhost:8002;
          } 

Enter fullscreen mode Exit fullscreen mode

The upstream block defines a load balancer named django_servers, which distributes incoming requests across the three Django application instances running on ports 8000, 8001, and 8002 on localhost.
By default, NGINX uses a round-robin strategy, sending each new request to a different server in sequence to balance the load.
This setup helps improve performance and reliability, as traffic is spread across multiple instances, preventing any single server from being overwhelmed.
You can read more about Using nginx as HTTP load balancer
Open your browser and enter localhost:8080. Reload several the site several time to see how nginx is able to route the traffic between the three servers.
Other load balancing algorithms that can be used are Weighted load balancing, Least connected load balancing,ip-hash

Common Errors and Troubleshooting

Below are some list of some errors you are likely to face when

🛑 1. NGINX Fails to Start or Reload
NGINX won't start or reload after changing the configuration. This is usually causee by Syntax or configuration errors in your nginx.conf
solution: Run a config test to catch syntax errors:

  nginx -t
Enter fullscreen mode Exit fullscreen mode

If there's an error, it will show the line and reason, like this

 nginx: [emerg] "server" directive is not allowed here in /etc/nginx/nginx.conf:34
Enter fullscreen mode Exit fullscreen mode

Fix the error, then restart nginx:

  sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

📛 2. 502 Bad Gateway
The browser shows a 502 Bad Gateway error. This error occures when nginx can't reach the backend servers ( Django containers).
Some common reasons maybe backend server(s) down or misconfigured, incorrect proxy_pass address, port mismatches (e.g., app runs on port 8000, but NGINX tries 8001).
solution:Check and make sure the backend servers are running.

⏳ 3. 504 Gateway Timeout
If the browser shows a 504 Gateway Timeout error , the error might be due to backend server(s)
takeing too long to respond, or NGINX can't establish a connection to the servers.
This maybe due to slow application responses (e.g., long-running DB queries) or timeout values are too low.

Solution:
Increase timeout settings in nginx.conf

  proxy_connect_timeout 120;
  proxy_read_timeout 120;
  proxy_send_timeout 120;

Enter fullscreen mode Exit fullscreen mode

🚩 4. Connection Refused
If you have connection refused in logs this may likely be due to the backend server not accepting connections or is bound to the wrong address.

Solution:
Ensure the app listens on the right IP:

⚠️ 5. Load Balancer Not Distributing Traffic Properly

If you have only one server getting all the traffic, or traffic doesn't balance as expected.This maybe due to the default round-robin behavior or sticky sessions or caching issues.
Solution:
Check and make sure the you are using the right load balancing algorithm:

Default round-robin behavior:

  upstream django_servers {
            server localhost:8000;
            server localhost:8001;
            server localhost:8002;
          } 
Enter fullscreen mode Exit fullscreen mode

Least Connections behavior:

  upstream django_servers {
            least_conn;
            server localhost:8000;
            server localhost:8001;
            server localhost:8002;
          }
Enter fullscreen mode Exit fullscreen mode

IP Hash behavior:

  upstream django_servers {
            ip_hash;
            server localhost:8000;
            server localhost:8001;
            server localhost:8002;
          }
Enter fullscreen mode Exit fullscreen mode

Conclusion and Next Steps

Nginx is a versatal webserver that can be used as a reverse proxy and load balancer for any web application.
With Nginx's simple configuration and vast ecosystem, you'll have plenty of flexibility to adapt to your application's evolving needs.
So, what's next? Explore how to configure nginx for SSL/TLS termination connections, caching static content and other features of Nginx.

References and Additional Resources

https://nginx.org/
https://nginx.org/en/docs/http/load_balancing.html
https://en.wikipedia.org/wiki/Nginx
https://www.keycdn.com/support/nginx

Top comments (0)