~/blog/nginx-intro
Published on

NGINX - Load balancer, Web server and Reverse Proxy

1422 words8 min read–––
Views
Authors
  • avatar
    Name
    Saikrishna Reddy
    Instagram

NGINX

Nginx is commonly used to serve static content like HTML, CSS, and image files and is also capable of handling dynamic content using modules and integrations with various programming languages and applications. It is widely used as a front-end server for web applications, APIs, and websites due to its speed and scalability.

In addition to its role as a web server, Nginx is frequently used as a reverse proxy to distribute incoming client requests to backend servers, such as application servers or other web servers, to improve performance and enhance security.

To install and start Nginx on macOS, you can follow these steps:

Step 1: Open Terminal Open the Terminal application on your Mac. You can find it in the "Utilities" folder within the "Applications" folder, or you can use the Spotlight search (Command + Space) to find and open it.

Step 2: Install Homebrew (if not installed) Homebrew is a popular package manager for macOS. If you don't have Homebrew installed, you can install it by running the following command in the Terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Step 3: Install Nginx Once Homebrew is installed, you can use it to install Nginx. Run the following command in the Terminal:

brew install nginx

Step 4: Start Nginx After the installation is complete, you can start the Nginx server using the following command:

sudo nginx

Note: You might need to enter your macOS user password to run Nginx with elevated privileges (sudo).

Step 5: Verify Nginx is Running To check if Nginx is running, open a web browser and enter "http://localhost" or "http://127.0.0.1" in the address bar. If Nginx is running correctly, you should see the default Nginx welcome page.

Step 6: Stop Nginx (Optional) If you want to stop the Nginx server, you can use the following command:

sudo nginx -s stop

Alternatively, you can use the quit or restart options to stop or restart Nginx, respectively:

sudo nginx -s quit
sudo nginx -s restart

That's it! You've successfully installed and started Nginx on your macOS. You can now use Nginx to serve websites, proxy requests, and perform other web server tasks. Now Let's directly see the usage of nginx for different purposes(like to serve static content, as webserver and as a load balancer) by modifying nginx.conf file.

If you do not have the server(Express) and multiple versions of it, check this first

Config

To open the file :

cd /opt/homebrew/etc/nginx

and open above folder in vs-code to edit it.

nginx.conf
http {
    include mime.types;

    # or we can add like below
    # types {
    #     text/html  html;
    #     text/css  css;
    # }

    #1. load balancing & reverse proxy
    #before testing this, make sure you run the backer server and do port mapping with docker
    #check Obsidian vault for more info(personal)
    #So, when 8080 hits, nginx using round robin algorithm, it forwards the request to one of
    #the following servers.
    upstream backendservers {
        server 127.0.0.1:1111;
        server 127.0.0.1:2222;
        server 127.0.0.1:3333;
    }

    server {
        listen 8080;
        root /Users/skonde/personal/daily-learning/others/test-website;


        #2. Serving from server(say express)
        location / {
            proxy_pass http://backendservers/;
        }

        #3. Serving static content
        #for testing any of the below path comment out above location context(this serves the backend)
        #regular expression
        #paths /count/1, /count/2 ... all get index.html
        location ~* /count/[0-9] {
            root /Users/skonde/personal/daily-learning/others/test-website;
            try_files /index.html =404;
        }

        #root is going to append /fruits at the last of the path. So, we dont need to append again
        # below path will become - /Users/skonde/personal/daily-learning/others/test-website/fruits
        location /fruits {
            root /Users/skonde/personal/daily-learning/others/test-website;
        }

        #if you dont want to append and want to serve from same path then use alias
        # this will become - /Users/skonde/personal/daily-learning/others/test-website/fruits
        location /carbs {
            alias /Users/skonde/personal/daily-learning/others/test-website/fruits;
        }

        #what if there no index.html and you want to look/serve other files
        # use - try_files

        #here, root is trying to serve index.html from vegetables folder. but there is no file
        #with that name but it has veggies.html then it will look for file mentioned under try_files
        #if no file found even from try_files, it returns 404
        location /vegetables {
            root /Users/skonde/personal/daily-learning/others/test-website;
            try_files /vegetables/veggies.html /index.html =404;
        }

        # REDIRECT
        # one way redirection using location with alias
        # another way is :
        # 307 indicates status code for redirection
        # Once this path hits, uri will be redirected from - <host>/crops to <host>/fruits
        # so in this case url will change
        location /crops {
            return 307 /fruits;
        }


        # REWRITE
        #In above case url will change, what if you want to stay at same url and but still want to
        #serve the file? - use rewrite
        #In below case, I want my url to stay at number/<anynumber> but want to serve the file from /count/<anynumber>
        #$1 is the value after /number/<this_is_the_value_for_$1>
        #for /count/<anynumber> take a look at the top for what file is being served
        rewrite ^/number/(\w+) /count/$1;

    }
}

events {

}

Now to reload nginx run,

nginx -s reload

Dockerizing Node App

NOTE: Before testing the load balancing using nginx, make sure you setup simple express server and use docker to run multiple versions of same server on different ports. In my case, I have the running on 3000 and I have used docker to run deploy multiple versions of same server. To do this :

  • Install docker on your system.
  • create a folder and run npm init app inside this folder.
  • also run npm i express and create index.js file.
index.js
const express = require("express");
const app = express();

app.get("/", function (req, res) {
  res.send("It worked, hello.");
});

app.listen(3000, () => {
  console.log("sever listening on 3000");
});

  • start the server by running node index.js
  • creater dockerfile and dockerignore file.
dockerfile
FROM node:18

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --omit=dev

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "node", "index.js" ]
.dockerignore
node_modules
npm-debug.log
  • Build docker image by running
docker build . -t <give_a_name_for_your_server>
  • To create multiple versions of same server repeat the below command with different server
docker run -dp 1111:3000 <given_name_in_above_command>

go back to nginx config file