How to Configure Nginx Web Server for Load Balancing, Reverse Proxy, and SSL
Nginx is a versatile web server that is widely used for its high performance, stability, and rich feature set. One of its most powerful features is the ability to act as a load balancer and reverse proxy, making it a vital component in scaling web applications. Additionally, securing web traffic with SSL (Secure Sockets Layer) is essential in modern web applications. In this guide, we will walk through configuring Nginx for load balancing, reverse proxy, and SSL.
Nginx is a versatile web server known for its high performance, stability, and rich feature set. With its capabilities as a load balancer and reverse proxy, it plays a crucial role in scaling web applications. Moreover, it is essential to secure web traffic using SSL. In this guide, we will demonstrate how to configure Nginx for load balancing, reverse proxy, and SSL.
Table of Contents
- What is Nginx
- How Nginx Secures Communication, Performs Load Balancing, and Acts as a Reverse Proxy
- How to Implement SSL Certificates in Nginx
- How to Configure Reverse Proxy in Nginx
- How to Configure Nginx for Load Balancing
- Source Code on GitHub & Docker Compose File
- Conclusion
- FAQ Section
What is Nginx
Nginx (pronounced “engine-x”) is an open-source web server that can also be used as a reverse proxy, load balancer, mail proxy, and HTTP cache. It is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.
How Nginx Secures, Balances, and Reverse Proxies Traffic
Enhancing Security with SSL Encryption
Nginx secures data transmitted over the internet by encrypting it, protecting sensitive information from prying eyes and tampering.
To understand working of SSL/TLS in depth, including how to generate SSL certificates, you can refer to my blog post Understanding HTTPS, SSL/TLS & Certificate Generation | Learn How SSL Works.
Load Balancing
Nginx distributes incoming network traffic across multiple servers to ensure no single server becomes overwhelmed, enhancing the availability and reliability of web applications.
Reverse Proxy
Nginx acts as an intermediary for requests from clients seeking resources from servers, improving security, performance, and reliability.
How to Implement SSL Certificates in Nginx
a. Generate a Self-Signed Certificate
To generate a self-signed SSL certificate, you can use OpenSSL. This method is particularly useful for testing purposes or internal applications where a trusted Certificate Authority (CA) is not required.
Generate CSR : Create a folder and run below command into its terminal
openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -out yourdomain.csr
Enter below details :
Country Name (2 letter code) [AU]: IN
State or Province Name (full name) [Some-State]: MH
Locality Name (eg, city) []: Mumbai
Organization Name (eg, company) [Internet Widgits Pty Ltd]: CodeOps Trek
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: www.codeopstrek.com
Email Address []: contact@codeopstrek.com
Generate Self-Signed Certificate
Two files will be generate in folder youromain.csr & yourdomain.key. Execute below command.
openssl x509 -req -days 365 -in yourdomain.csr -signkey yourdomain.key -out yourdomain.crt
A certificate will generated in folder as yourdomain . As it is self signed and not by a trusted CA , a cross mark will be seen but this certificate works as a normal certificate and it will provide encrypt data and secure transmission.
b. Create a Custom Nginx Docker Image
To create a custom Nginx Docker image with your SSL certificates and configurations, follow these steps:
- Create a folder : Custom Nginx
- Create Nginx Configuration File: Create a file named
nginx.confwith your custom Nginx configuration, including SSL settings. - Create Dockerfile: Write a Dockerfile to build your custom Nginx image.
- Save Folder Containing SSL and Key: Save your SSL certificate and key in a folder.
Your folder structure should be like below :
custom-nginx ├── Certificate │ ├── codeopstrek.key │ ├── codeopstrek.csr │ ├── codeopstrek.crt ├── nginx.conf └── Dockerfile
nginx.conf
server {
listen 8080;
listen 443 ssl;
server_name www.codeopstrek.com;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html; # Serve the default Nginx welcome page
index index.html index.htm;
}
}
Dockefile
# Use the official Nginx image as the base image
FROM nginx:latest
# Maintainer information (replace with your own)
LABEL maintainer="CodeOps Trek"
# Copy SSL certificate and key to the container
COPY ./Certificate/codeopstrek.crt /etc/nginx/ssl/nginx.crt
COPY ./Certificate/codeopstrek.key /etc/nginx/ssl/nginx.key
# Remove default Nginx configuration file
RUN rm /etc/nginx/conf.d/default.conf
# Copy custom Nginx configuration file
COPY nginx.conf /etc/nginx/conf.d/
Run below command to Build Docker Image :
docker build -t custom-nginx .
c. Run Custom Docker Image
docker run --name CustomNginx -it -p 8080:8080 -p 443:443 custom-nginx
Above command will run custom nginx on 2 port i.e; 8080 & 443 . On 8080 http(Non SSL) works while on 443 https(SSL/TLS) work
Click : http://localhost:8080
Click : https://localhost:443
Voila! You’ve successfully integrated SSL into your Nginx setup. Great job!
How to Configure Reverse Proxy in Nginx
Scenario Overview
We have two applications running in Docker containers:
1- Application 1: Running on port 8082, responds with “Hello from first application” at the endpoint /hi.
2- Application 2: Running on port 8084, responds with “Hello from second application” at the endpoint /hi.
We’ll configure Nginx to act as a reverse proxy, routing requests to these applications based on the URL path. For example:
- Requests to
http://localhost:8080/app1/hiwill be routed to Application 1. - Requests to
http://localhost:8080/app2/hiwill be routed to Application 2.
Step 1: Create a Docker Network
First, we’ll create a Docker network to allow our containers to communicate with each other:
docker network create app_network
Step 2: Run Nginx on the Docker Network
Next, we’ll run an Nginx container on the Docker network:
1- Create the Nginx configuration file:Create a file named nginx.conf with the following content:
upstream application1 {
server FirstApplicationContainer:8082;
}
upstream application2 {
server SecondApplicationContainer:8084;
}
server {
listen 8080;
listen 443 ssl;
server_name www.codeopstrek.com;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /app1 {
proxy_pass http://application1;
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;
}
location /app2 {
proxy_pass http://application2;
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;
}
}
2- Run the Nginx container:
docker run --name CustomNginx --network app_network -it -p 8080:8080 -p 443:443 custom-nginx3- Run Application 1 Container:
docker run --name FirstApplicationContainer --network app_network -it application1_image
4- Run Application 2 Container:
docker run --name SecondApplicationContainer --network app_network -it application2_image
Explanation
By running both applications on the same Docker network, they can communicate with each other using their container names as hostnames. Port mapping is not required for either application because they communicate directly within the Docker network, conserving system ports. Port mapping is only necessary for the Nginx container, as it will handle external traffic and route it to the appropriate applications.
Step 3: Testing
Now, you can test the setup:
1- Application 1: Open your browser or use curl to access http://localhost:8080/app1/hi. You should see the response “Hello from first application”.
2- Application 2: Open your browser or use curl to access http://localhost:8080/app2/hi. You should see the response “Hello from second application”.
How to Configure Nginx for Load Balancing
Scenario Overview
We have two applications running in Docker containers:
1. Application 1: Running on port 8082, responds with “Hello from first application” at the endpoint /hi.
2. Application 2: Running two instances:
- Instance 1: Running on port 8084
- Instance 2: Running on port 8086
Both instances respond with “Hello from second application – instance {i}” at the endpoint /hi.
Step 1: Create a Docker Network
docker network create app_network
Step 2: Run Nginx on the Docker Network
Next, we’ll run an Nginx container on the Docker network:
1- Create the Nginx configuration file:Create a file named nginx.conf with the following content:
upstream application1 {
server FirstApplicationContainer:8082;
}
upstream application2 {
server SecondApplicationContainer1:8084;<br> server SecondApplicationContainer1:8086;
}
server {
listen 8080;
listen 443 ssl;
server_name www.codeopstrek.com;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /app1 {
proxy_pass http://application1;
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;
}
location /app2 {
proxy_pass http://application2;
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;
}
}
2- Run the Nginx container:
docker run --name CustomNginx --network app_network -it -p 8080:8080 -p 443:443 custom-nginx
3- Run Application 1 Container:
docker run --name FirstApplicationContainer --network app_network -it application1_image
4- Run Application 2 Container:
docker run --name SecondApplicationContainer1 --network app_network -it application2_image<br>docker run --name SecondApplicationContainer2 --network app_network -it application2_image
Testing Load Balancing
You can test the load balancing by sending multiple requests to http://localhost:8080/app2/hi. You should see responses from both instances of Application 2.
Source Code on GitHub & Docker Compose File
The source code and Docker Compose file for this setup are available on GitHub: Source Code on GitHub
Docker Compose File
1- Create a docker-compose.yml file and paste below code
2- Open terminal of folder where yml file is there and run docker-compose up -d
version: '3'
services:
nginx:
image: codeopstrek/custom-nginx
container_name: CustomNginx
ports:
- "8080:8080"
- "443:443"
networks:
- app_network
app1:
image: codeopstrek/app1
container_name: FirstApplicationContainer
networks:
- app_network
app2-instance1:
image: codeopstrek/app2-instance1
container_name: SecondApplicationContainer1
networks:
- app_network
app2-instance2:
image: codeopstrek/app2-instance2
container_name: SecondApplicationContainer2
networks:
- app_network
networks:
app_network:
driver: bridge
Conclusion
Configuring Nginx for load balancing, reverse proxy, and SSL is a powerful way to enhance the performance, security, and scalability of your web applications. By following the steps outlined in this guide, you can ensure that your web server is optimized for high availability and secure communication.
For further reading and resources, consider exploring the following:
Official Nginx Documentation: Comprehensive guides on configuring Nginx as a reverse proxy, load balancer, and for SSL termination are available in the Nginx documentation. Check out the sections on Nginx Reverse Proxy, Nginx Load Balancing, and Nginx SSL/TLS Termination.
Let’s Encrypt: A free, automated, and open Certificate Authority that provides SSL certificates to secure your web applications. Visit the Let’s Encrypt Documentation to learn more about obtaining and renewing SSL certificates.
By exploring these resources, you can deepen your understanding and enhance your skills in configuring Nginx for reverse proxy, load balancing, and securing your applications with SSL certificates.
FAQ Section
What is a reverse proxy used for?
A reverse proxy is used to distribute client requests to multiple backend servers, enhancing load balancing, security, and scalability.
When should I use a reverse proxy?
You should use a reverse proxy when you need to distribute client requests across multiple servers, enhance security by hiding backend servers, manage SSL/TLS termination, and improve load balancing and scalability of your web applications
What is the difference between reverse proxy and API gateway?
A reverse proxy forwards client requests to backend servers, while a gateway handles protocol translations and routes requests between different networks.
Is load balancer a reverse proxy?
Yes, a load balancer can act as a reverse proxy by distributing client requests across multiple servers to improve performance and reliability.
What is a reverse proxy vs load balancer?
A reverse proxy forwards client requests to backend servers, providing security and caching. A load balancer distributes client requests across multiple servers to optimize resource use, improve response times, and ensure high availability.
