Skip to main content
RunBook Academy

LinuxLVII · Linux Load Balancingnginx LB

nginx as a load balancer - the versatile option

Intermediate⏱ ~10 minnginx

What you'll learn

  • Configure nginx as a load balancer
  • Set up upstream and health checks
  • Compare nginx and HAProxy for the workload
  • Test load balancing

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09

Not yet marked complete on this device.

nginx is the most widely deployed web server; it can also act as a load balancer. This lesson covers the LB use case and when to choose nginx over HAProxy.

Configure nginx as a load balancer

http {
    upstream backend {
        server 10.0.0.10:80;
        server 10.0.0.11:80;
        server 10.0.0.12:80;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        location /health {
            access_log off;
            return 200 "ok\n";
        }
    }
}

Algorithms

upstream backend {
    ip_hash;                          # source IP hash (session affinity)
    # least_conn;                      # least connections
    # random;                         # random
    server 10.0.0.10:80;
    server 10.0.0.11:80;
}

ip_hash: client IP always goes to the same backend. least_conn: backend with fewest connections. random: random selection.

Health checks

nginx Plus has active health checks. Open-source nginx has passive health checks via max_fails and fail_timeout:

upstream backend {
    server 10.0.0.10:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.11:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:80 max_fails=3 fail_timeout=30s;
}

After 3 failures within 30s, the backend is marked down. It is retried after the timeout.

For active health checks, use nginx Plus or a separate health-check script (via upstream_check modules).

TLS termination

server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/private.pem;
    ssl_certificate_key /etc/ssl/private.key;

    location / {
        proxy_pass http://backend;
    }
}

TLS is terminated at nginx; backend traffic is plain HTTP.

Compare to HAProxy

FeaturenginxHAProxy
Active health checksPlus onlyYes (open source)
Layer 4 LBYes (stream)Yes
Layer 7 LBYes (HTTP)Yes (HTTP, more features)
TLS terminationYesYes
Hot reloadYes (config reload)Yes
MetricsBasicDetailed (stats page)
Per-request routingLimitedFull (ACLs, maps)

For simple use cases, nginx is enough. For complex routing, active health checks, or detailed metrics, HAProxy is better.

When to use nginx as LB

  • The same nginx instances serve static content and load balance.
  • The traffic is HTTP(S) only.
  • The team already knows nginx.
  • Active health checks are not required (or done by another tool).

When to use HAProxy

  • Active health checks are required.
  • Complex layer 7 routing (path, header, cookie-based).
  • Detailed metrics are required.
  • Layer 4 load balancing is needed.

Knowledge check

Knowledge check · 3 questions

  1. Q1. What nginx directive declares a load balancer backend pool?

  2. Q2. Open-source nginx has active health checks.

  3. Q3. Which of the following are valid nginx load balancing algorithms? Select all that apply.

Passing score: 75%. Answers are checked in this browser.