Setting up Nginx as a reverse proxy load balancer on RHEL and CentOS
When Australian sites handle a sudden rush of visitors, whether it is a Boxing Day sale or the streaming spike when the AFL grand final kicks off at 3pm AEST, a single web server can buckle fast. Spreading incoming requests across several backend nodes keeps response times steady and prevents one busy box from becoming the single point of failure.
This walkthrough shows how to deploy Nginx as a load balancer on RHEL, CentOS Stream, Rocky Linux, and Fedora. If you are new to reverse proxies, the foundational guide on Linuxtpoint covers the theory before you get hands-on.
Preparing the host and enabling the right repositories
Before installing anything, refresh the system. On RHEL-family distributions the EPEL and nginx-stable repositories are the cleanest sources for a modern build:
sudo dnf update -y
sudo dnf install -y epel-release
sudo dnf config-manager --set-enabled crb
Australian sysadmins often pin packages to a specific minor version so production environments in Sydney, Melbourne, and Perth data centres stay aligned with the same binary.
Installing the Nginx package
With the repository enabled, install the web server and start the service:
sudo dnf install -y nginx
sudo systemctl enable --now nginx
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
firewalld is the default on RHEL and its derivatives. If your edge device sits behind a corporate firewall, also open ports 80 and 443 on the upstream router.
Defining upstreams and choosing a balancing algorithm
The upstream block lists the backend servers that will share traffic:
upstream backend_pool {
least_conn;
server 10.0.0.11:8080 weight=3;
server 10.0.0.12:8080 weight=2;
server 10.0.0.13:8080;
keepalive 32;
}
least_conn sends each new request to the server with the fewest active connections, which works well when request durations vary. Weights let you favour beefier instances, useful when one of your nodes lives in the AWS Sydney region (ap-southeast-2) on a higher-spec instance type.
Building the virtual host and adding health checks
The server block then routes traffic into the upstream pool. Active health checks, available in Nginx Plus and recent open source builds, can probe each backend:
server {
listen 80;
server_name example.com.au;
location / {
proxy_pass http://backend_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;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
health_check interval=10s fails=3 passes=2 uri=/healthz;
}
Make sure every backend exposes a /healthz endpoint that returns HTTP 200 only when the application is ready. A misconfigured probe is a common cause of cascading failures during peak retail events, when one slow database query can ripple across the fleet.
Terminating TLS at the load balancer
Putting the TLS handshake on the load balancer reduces CPU load on the application nodes and centralises certificate management. Add a 443 listener that follows the ACSC guidance on strong ciphers:
server {
listen 443 ssl http2;
server_name example.com.au;
ssl_certificate /etc/pki/tls/certs/example.com.au.crt;
ssl_certificate_key /etc/pki/tls/private/example.com.au.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / { proxy_pass http://backend_pool; }
}
Redirect plain HTTP traffic to HTTPS with a second server block listening on port 80, which keeps the .au domain compliant with the Privacy Act and modern browser expectations.
Tuning worker processes and caching
By default Nginx uses one worker per CPU core, but you can cap the count in /etc/nginx/nginx.conf to match a smaller VM. Enable gzip for text responses and add a small micro-cache:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=microsite:10m max_size=1g inactive=60m;
Inside the location block, set proxy_cache microsite; and proxy_cache_valid 200 30s; to serve repeated reads from RAM. Local benchmarks on a 4-vCPU node in a NextDC Sydney facility showed roughly a 40 percent drop in upstream requests once the cache warmed up.
Hardening, logging, and ongoing monitoring
Australian hosts face the same brute-force noise as anywhere else, so fail2ban with the nginx-http-auth jail is a sensible baseline. Rotate logs with a daily cron job triggered at 02:00 AEST, well before business hours begin on the east coast. Ship access logs to a central collector so the team in Brisbane, Adelaide, or Perth can audit requests without remote-logging into each box.
Test the full configuration with nginx -t before reloading, then systemctl reload nginx to apply changes without dropping connections. Keep nginx.conf under version control so any drift is easy to spot during post-incident reviews.
If you want a pre-baked Ansible role or a Docker image that already wires these blocks together, browse the project showcase for starter templates. The fastest way to validate the setup is to pull a synthetic load with wrk or hey, watch the upstream connections spread evenly, and confirm that killing one backend does not break the service for end users.