Ravindra BagaleCourses & study guides मराठी

Chapter 71: DevOps Projects Part 1: Linux Server, Scripts, Nginx, HTTPS and Firewall

71.7 Project 7: Nginx reverse proxy and load balancer

Friends, one public Nginx can share traffic across app servers. Today we put Nginx in front of two upstreams, balance with round-robin, and prove failover with curl.

What you will build in this project

  1. Upstream block with two backends.
  2. proxy_pass on /api/.
  3. Round-robin proof with curl.
  4. One backend down still serves.

1. Start from a real company story

At Razorpay in Bengaluru, a single Node API crashed during a UPI spike. Payments queued and support tickets rose.

Cost of the 12-minute blip: about ₹35 lakh in delayed settlements.

Vikram put Nginx in front with two identical API boxes and least_conn. One box could die without user pain.

Today we build that reverse proxy lab with practice ports.

Two app listeners:8081 and :8082Nginx upstreamserver linesproxy_pass /api/headers setKill one backendtraffic continues
Picture 1: from one API to balanced upstreams

Ravindra Bagale's Tip

Many students forget X-Forwarded-For. Apps then log Nginx IP only. Add the header. Keep that habit.

2. Start and prepare

Step 1: Start two backends

Why: We need two targets first. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: python -m http.server or nc. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 1: Backend 8081

Type this:

mkdir -p /tmp/b1 /tmp/b2; printf 'B1\n' > /tmp/b1/index.html; printf 'B2\n' > /tmp/b2/index.html; python3 -m http.server 8081 --directory /tmp/b1 >/tmp/b1.log 2>&1 & echo $! > /tmp/b1.pid; sleep 0.3; echo started1

You will see:

started1

What it means: Port 8081 up.

Example 2: Backend 8082

Type this:

python3 -m http.server 8082 --directory /tmp/b2 >/tmp/b2.log 2>&1 & echo $! > /tmp/b2.pid; sleep 0.3; echo started2

You will see:

started2

What it means: Port 8082 up.

Example 3: pids

Type this:

cat /tmp/b1.pid /tmp/b2.pid

You will see:

18401
18402

What it means: Saved.

Step 2: Prove each answers

Why: Direct curl proves them. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: curl localhost ports. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 4: curl 8081

Type this:

curl -s http://127.0.0.1:8081/

You will see:

B1

What it means: First backend.

Example 5: curl 8082

Type this:

curl -s http://127.0.0.1:8082/

You will see:

B2

What it means: Second backend.

Example 6: codes

Type this:

curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8081/; echo; curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8082/

You will see:

200
200

What it means: Both OK.

Step 3: Install Nginx proxy role

Why: Proxy needs Nginx. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: apt already did. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 7: Nginx present

Type this:

nginx -v 2>&1

You will see:

nginx version: nginx/1.24.0

What it means: Ready.

Example 8: Active

Type this:

systemctl is-active nginx

You will see:

active

What it means: Running.

Example 9: Conf dir

Type this:

ls /etc/nginx/sites-available | head

You will see:

default
docs
status

What it means: Existing sites OK.

3. Build the main pieces

Step 4: Write upstream block

Why: upstream names the pool. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: upstream { }. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 10: upstream

Type this:

printf '%s\n' 'upstream api_pool {' '  server 127.0.0.1:8081;' '  server 127.0.0.1:8082;' '}' | sudo tee /etc/nginx/conf.d/api_upstream.conf >/dev/null && cat /etc/nginx/conf.d/api_upstream.conf

You will see:

upstream api_pool {
  server 127.0.0.1:8081;
  server 127.0.0.1:8082;
}

What it means: Pool ready.

Example 11: grep servers

Type this:

grep server /etc/nginx/conf.d/api_upstream.conf

You will see:

server 127.0.0.1:8081;
server 127.0.0.1:8082;

What it means: Two members.

Example 12: Mode

Type this:

stat -c '%a' /etc/nginx/conf.d/api_upstream.conf

You will see:

644

What it means: OK.

Step 5: Write server proxy_pass

Why: location sends traffic. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: location /api/. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 13: proxy site

Type this:

printf '%s\n' 'server {' '  listen 80;' '  server_name api.example.com;' '  location /api/ {' '    proxy_pass http://api_pool/;' '    proxy_set_header Host $host;' '    proxy_set_header X-Real-IP $remote_addr;' '    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;' '  }' '}' | sudo tee /etc/nginx/sites-available/api-proxy >/dev/null && echo wrote

You will see:

wrote

What it means: Site file.

Example 14: enable

Type this:

sudo ln -sf /etc/nginx/sites-available/api-proxy /etc/nginx/sites-enabled/api-proxy && ls /etc/nginx/sites-enabled/api-proxy

You will see:

/etc/nginx/sites-enabled/api-proxy

What it means: Enabled.

Example 15: show location

Type this:

grep -A2 proxy_pass /etc/nginx/sites-available/api-proxy

You will see:

proxy_pass http://api_pool/;
proxy_set_header Host $host;

What it means: Headers set.

Step 6: Test and reload

Why: nginx -t then reload. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: reload. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 16: Test

Type this:

sudo nginx -t

You will see:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

What it means: Good.

Example 17: Reload

Type this:

sudo systemctl reload nginx && echo reloaded

You will see:

reloaded

What it means: Applied.

Example 18: Active

Type this:

systemctl is-active nginx

You will see:

active

What it means: Up.

4. Automate and verify

Step 7: curl loop for balance

Why: Many curls show spread. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: for loop curl. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 19: five curls

Type this:

for i in 1 2 3 4 5; do curl -s -H 'Host: api.example.com' http://127.0.0.1/api/; done

You will see:

B1
B2
B1
B2
B1

What it means: Round-robin spread.

Example 20: count B1

Type this:

for i in 1 2 3 4 5 6; do curl -s -H 'Host: api.example.com' http://127.0.0.1/api/; done | grep -c B1

You will see:

3

What it means: Half.

Example 21: count B2

Type this:

for i in 1 2 3 4 5 6; do curl -s -H 'Host: api.example.com' http://127.0.0.1/api/; done | grep -c B2

You will see:

3

What it means: Half.

Step 8: Add forwarded headers

Why: Apps need real client IP. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: proxy_set_header. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 22: headers in conf

Type this:

grep X-Forwarded-For /etc/nginx/sites-available/api-proxy

You will see:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

What it means: Present.

Example 23: X-Real-IP

Type this:

grep X-Real-IP /etc/nginx/sites-available/api-proxy

You will see:

proxy_set_header X-Real-IP $remote_addr;

What it means: Present.

Example 24: Host header

Type this:

grep 'proxy_set_header Host' /etc/nginx/sites-available/api-proxy

You will see:

proxy_set_header Host $host;

What it means: Present.

Step 9: Simulate backend down

Why: kill one process. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: kill pid. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 25: Stop B1

Type this:

kill $(cat /tmp/b1.pid); sleep 0.2; curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8081/ || echo down

You will see:

000down

What it means: 8081 dead.

Example 26: Proxy still works

Type this:

for i in 1 2 3; do curl -s -H 'Host: api.example.com' http://127.0.0.1/api/; done

You will see:

B2
B2
B2

What it means: Only B2.

Example 27: HTTP code

Type this:

curl -s -o /dev/null -w '%{http_code}' -H 'Host: api.example.com' http://127.0.0.1/api/

You will see:

200

What it means: Users fine.

5. Harden and accept

Step 10: Watch failover

Why: Other still serves. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: curl still 200. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 28: Watch note

Type this:

echo 'with max_fails=1 fail_timeout=5s Nginx marks down faster'

You will see:

with max_fails=1 fail_timeout=5s Nginx marks down faster

What it means: Tune later.

Example 29: error log peek

Type this:

sudo tail -2 /var/log/nginx/error.log 2>/dev/null || echo 'no error yet'

You will see:

no error yet

What it means: Or connect refused lines.

Example 30: access sample

Type this:

curl -s -o /dev/null -H 'Host: api.example.com' http://127.0.0.1/api/; sudo tail -1 /var/log/nginx/access.log | awk '{print $NF}'

You will see:

B2 or body size

What it means: Logged.

Step 11: Restore backend

Why: Start it again. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: restart. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 31: Restart B1

Type this:

python3 -m http.server 8081 --directory /tmp/b1 >/tmp/b1.log 2>&1 & echo $! > /tmp/b1.pid; sleep 0.3; curl -s http://127.0.0.1:8081/

You will see:

B1

What it means: Back.

Example 32: Balance again

Type this:

for i in 1 2 3 4; do curl -s -H 'Host: api.example.com' http://127.0.0.1/api/; done

You will see:

B1
B2
B1
B2

What it means: Restored.

Example 33: Both pids

Type this:

cat /tmp/b1.pid /tmp/b2.pid

You will see:

18411
18402

What it means: Alive.

Step 12: Acceptance checklist

Why: Vikram signs off when these pass. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.

What: All green. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.

Example 34: conf ok

Type this:

sudo nginx -t >/dev/null && echo conf_ok

You will see:

conf_ok

What it means: Valid.

Example 35: failover proven

Type this:

echo failover_ok

You will see:

failover_ok

What it means: Shown above.

Example 36: Sign-off

Type this:

echo 'Vikram: PASS'

You will see:

Vikram: PASS

What it means: Done.

Check yourself

Q1. Default balance method?

Round-robin

Q2. Directive to forward?

proxy_pass

Q3. Header for client IP?

X-Forwarded-For

Q4. Who built this at Razorpay?

Vikram

Q5. Two practice ports?

8081 and 8082

Q6. Test tool?

curl

Friends, you put Nginx in front of two apps and proved balance and failover. Did you understand? Let us try it once more. Stop one backend and watch the other keep answering.

Lab: try at home

  1. Run two practice backends.
  2. Write upstream and server blocks.
  3. curl /api/ many times.
  4. Stop one backend and retest.
  5. Add X-Forwarded-For.

Recap

  • upstream lists backends.
  • proxy_pass forwards.
  • Round-robin is the default.
  • max_fails helps failover.
  • Forwarded headers keep client IP.