Use NGINX To Build A Reverse Proxy
Tags: proxy, webserver, administration, nginx
Published: 2021-01-27 11:32:15

---
title: Use NGINX To Build A Reverse Proxy
published: true
date: 2019-02-08 02:53:02 UTC
tags: proxy,webserver,administration,nginx
canonical_url: 
---

a proxy server is a mediator server that will forward every request from clients to different destinations. destination server does not see clients directly, so they don't know anything about those clients.

after accepting a request from a client, the proxy server will assign a port to that request and forwards the request to its destination. after receiving the reply on that port, the response will be forwarded to the client through the previous connection.

![proxy server](http://iakrami.ir/assets/img/posts/proxy_server.png)

unlike proxy servers, a reverse proxy server resides beside web servers. clients see web servers behind a reverse proxy as one server and can not distinguish them.

![reverse proxy server](http://iakrami.ir/assets/img/posts/reverse_proxy.png)

Reverse proxies forward requests to one or more ordinary servers that handle them. The response from the proxy server is returned as if it came directly from the original server, leaving the client with no knowledge of the origin servers.

#### Common Uses For A Reverse Proxy Server:
##### Load Balancing

A reverse proxy server can act as a load-balancer in front of backend servers and distributing client requests across a group of servers in a manner that maximizes speed and capacity utilization while ensuring none of them is overloaded. If one goes down, the load balancer redirects traffic to the remaining active ones.

##### Web Acceleration

Reverse proxies can compress requests, as well as cache commonly requested content, which speeds up the flow of traffic between clients and servers.

##### Encryption / SSL Acceleration

the SSL encryption is often not done by web servers, and instead reverse proxy will handle it. by this, all services across web servers are encrypted and secured just by one configuration.

## Installing NGINX

as we write this article current version of NGINX is `1.14.2`.

#### CentOS/RHEL:
1. Install the EPEL repository:

```bash
$ sudo yum install epel-release
```
2. Update the repository:

```bash
$ sudo yum update
```
3. Install NGINX Open Source:

```bash
$ sudo yum install nginx
```
4. Verify the installation:

```bash
$ sudo nginx -v
```
  

#### Debian/Ubuntu:
1. Update the Debian repository information:

```bash
$ sudo apt-get update
```
2. Install the NGINX Open Source package:

```bash
$ sudo apt-get install nginx
```
3. Verify the installation:

```bash
$ sudo nginx -v
```

other installation methods and operating systems are available on this link: [Installing NGINX Open Source](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/)

## Configure NGINX

assume that we have two main services on the server. one is hosted by apache on port 8080 and another one is a nodejs service on port 8090.

URLs for the first service are as follow:

```
http://localhost:8080/login
http://localhost:8080/home
http://localhost:8080/assets/css/home.css
http://localhost:8080/assets/js/home.js
```

and here are URLs for the second service:

```
http://localhost:8090/api
http://localhost:8090/api/getAll
http://localhost:8090/api/set
```

ok, now let's look at our configuration. the main location of this file is `/etc/nginx/nginx.conf`. if you can not find that just create it:

```nginx
server {
    listen 80;
    listen [::]:80;

    server_name example.com; 
}

```

you should replace `example.com` with your own domain name.

we have defined a new server on port 80 on `line 2`. `server_name` is our domain name. now we want to define our rules for URLs in reverse proxy. just add these lines after `server_name`.

```nginx
location /app {
    proxy_pass http://localhost:8080/;
}
location /api {
    proxy_pass http://localhost:8090/api/;
}

```

as you can see if the URL starts with `/app`, the request will be forwarded to the first service.

```
http://localhost/app/login => http://localhost:8080/login
http://localhost/app/home => http://localhost:8080/home
http://localhost/api/getAll => http://localhost:8090/api/getAll
http://localhost/app/xxxx => http://localhost:8080/xxxx
http://localhost/api/xxxx => http://localhost:8090/api/xxxx
```

## Advanced Configuration

real-time web applications often do not buffer data, so we may also want to disable it on the reverse proxy server.

```nginx
location /api {
    proxy_pass http://localhost:8090/api/;
    proxy_buffering off;
}

```

you may also need to set or add headers to the requests:

```nginx
location /app {
    proxy_pass http://localhost:8080/;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
}

```

This configuration uses the built-in `$remote_addr` variable to send the IP address of the original client to the proxy host.

By default, the Host header from the request is not forwarded but is set based on the `proxy_pass` statement.

you can use regular expressions for defining custom locations:

```nginx
location ~ ^/app/css/(.*)$ {
    proxy_pass http://localhost:8080/assets/css/$1;
}
```
```
http://localhost/app/css/home.css => http://localhost:8080/assets/css/home.css
```

We also can use `rewrite`:

```nginx
location /app/ {
    rewrite ^/app/dashboard/(.*)$ /app/home?path=$1 break;
    proxy_pass http://localhost:8080/;
}

```

If the rewrite rule is hit, the URI specified in the directive is ignored and the full changed request URI is passed to the server:

```
http://localhost/app/dashboard/addUser => http://localhost:8080/home?path=addUser
http://localhost/app/assets/css/home.css => http://localhost:8080/assets/css/home.css
```

### Using NGINX Load Balancer

Define servers that you want to balance request loads on them:

```nginx
upstream backend {
    server 10.1.0.101; 
    server 10.1.0.102;
    server 10.1.0.103;
}

```

now we can use load balancer in `location` parameter of reverse proxy:

```nginx
server {
    listen 80; 
 
    location / {
       proxy_pass http://backend;
    }
}

```

### SSL Encryption With NGINX

First of all, define certifications like this:

```nginx
http {
    ssl_certificate /root/certs/example.com/example.com.crt;
    ssl_certificate_key /root/certs/example.com/example.com.key;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
    ssl_protocols TLSv1.1 TLSv1.2;

```

now you can enable HTTPS for your servers by this:

```nginx
server {
    listen 203.0.113.30:443 ssl;
    listen [2001:DB8::5]:443 ssl;
    server_name example1.com www.example1.com;
    root /var/www/example1.com;
}
server {
    listen 203.0.113.40:443 ssl;
    listen [2001:DB8::6]:443 ssl;
    server_name example2.com www.example2.com;
    root /var/www/example2.com;
}

```