--- title: "Nginx as Application Load Balancer For OPC" slug: "nginx-as-application-load-balancer-for-opc" updated: 2026-05-26T13:22:35Z published: 2026-05-26T13:22:35Z canonical: "help.scalefusion.com/nginx-as-application-load-balancer-for-opc" --- > ## Documentation Index > Fetch the complete documentation index at: https://help.scalefusion.com/llms.txt > Use this file to discover all available pages before exploring further. # Nginx as Application Load Balancer For OPC This guide explains how to configure High Availability (HA) for On-Prem Connector (OPC) using NGINX as a load balancer and reverse proxy. In this setup, NGINX distributes traffic between multiple OPC servers, helping ensure continued availability if one server becomes unavailable. It also covers how to securely expose the setup using Cloudflare Tunnel, monitor backend server health, and view real-time traffic statistics through the NGINX dashboard. > [!CAUTION] > **Note:** This document is intended as a general setup guide and covers only the specific configuration steps. Steps may vary depending on software versions, environment settings, or future updates. Scalefusion does not provide technical support for third-party software or infrastructure configurations referenced in this document. > > Any tools or software mentioned are shared for guidance purposes only, and customers should choose the approach best suited to their environment. ## 1. Overview ### What is a Load Balancer? When users access an application, all requests hit a single entry point. Without a load balancer, if that one server goes down, the entire application becomes unavailable. A load balancer sits in front of multiple application servers and distributes incoming traffic across them — so if one server goes down, traffic automatically flows to the remaining healthy servers without any interruption to users. ### Why Nginx as a Load Balancer? Nginx is a lightweight, high-performance web server that also functions as a reverse proxy and load balancer. It is open-source, battle-tested at scale, and consumes very little memory. For this setup, Nginx is compiled with the VTS (Virtual Host Traffic Status) module which adds a real-time web dashboard showing traffic, health, and response statistics for each backend server — similar to HAProxy's stats page. ### How Traffic Flows in This Setup ```plaintext User Request     │     ▼ Cloudflare (opc-ha-ngnix.xxxx.com)     │  Encrypted tunnel — no open inbound ports needed     ▼ Nginx Load Balancer (192.168.14.74 :80)     │     ├──► OPC Server 1 (192.168.14.157:28767)     │     └──► OPC Server 2 (192.168.14.217:28767) Admin Browser ──► Nginx Stats Dashboard (192.168.14.74:8080/status) ``` Cloudflare receives the public request and tunnels it securely to Nginx on your private network. Nginx decides which OPC server handles the request based on the configured algorithm. The stats page runs on a separate internal-only port so only admins on the local network can access it. ## 2. Infrastructure Details | Role | Hostname | IP Address | Port | | --- | --- | --- | --- | | Load Balancer | ha-nginx | 192.168.14.74 | 80 (app), 8080 (stats) | | OPC App Server 1 | opc-1 | 192.168.14.157 | 28767 | | OPC App Server 2 | opc-2 | 192.168.14.217 | 28767 | | Public URL | opc-ha-xxx.xxxx.com | via Cloudflare | 80/443 | ## 3. Load Balancing Algorithms Nginx supports multiple ways to distribute traffic. You configure this inside the `upstream` block in nginx.conf. Here is what each one does and when to use it. ### Round Robin (Default) Requests go to each server one by one in rotation. Server 1 gets request 1, Server 2 gets request 2, Server 1 gets request 3, and so on. No keyword needed — this is the default when nothing is specified. ```plaintext upstream opc_backend {    server 192.168.14.157:28767;    server 192.168.14.217:28767; } ``` **Best for:** servers with identical hardware where requests take roughly equal time to process. ### Least Connections Each new request goes to whichever server currently has the fewest active connections. This is smarter than round robin when some requests take longer than others — it prevents one server from getting overloaded while the other sits idle. ```plaintext upstream opc_backend {    least_conn;    server 192.168.14.157:28767;    server 192.168.14.217:28767; } ``` **Best for:** applications like OPC where request processing time varies. **This is what we use.** ### Weighted You assign a weight to each server. A server with weight 3 receives 3 requests for every 1 request sent to the server with weight 1. ```plaintext upstream opc_backend {    server 192.168.14.157:28767 weight=3;    server 192.168.14.217:28767 weight=1; } ``` **Best for:** environments where one server has more CPU/RAM than the other. ### IP Hash The same client IP always routes to the same server. Every request from a specific user always lands on the same backend. ```plaintext upstream opc_backend {    ip_hash;    server 192.168.14.157:28767;    server 192.168.14.217:28767; } ``` **Best for:** applications that store session data locally on the server and cannot share it between servers. To switch algorithm on a running system: ```plaintext sudo vi /etc/nginx/conf/nginx.conf # Edit the upstream block, then: nginx -t -c /etc/nginx/conf/nginx.conf sudo systemctl reload nginx ``` Reload (not restart) applies config changes without dropping any active connections. ## 4. Installation and Setup ### Step 1 — Install Build Dependencies SSH into the load balancer server and run: ```plaintext sudo apt-get update && sudo apt-get upgrade -y sudo apt install -y git build-essential libpcre3-dev zlib1g-dev libssl-dev libgeoip-dev wget ``` These are compiler tools and libraries Nginx needs to build from source. We build from source because the VTS stats module is not included in the standard apt package. ### Step 2 — Download Nginx Source Code ```plaintext cd ~ wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -xzf nginx-1.24.0.tar.gz ``` ### Step 3 — Download the VTS Stats Module ```plaintext git clone https://github.com/vozlt/nginx-module-vts.git /tmp/nginx-module-vts # Confirm it downloaded correctly — you must see a file named 'config' ls /tmp/nginx-module-vts/config ``` If you see `No such file or directory`, the clone failed. Check your internet connection and re-run the git clone command. Do not proceed to Step 4 until this file is confirmed present. ### Step 4 — Compile Nginx with VTS Module ```plaintext cd ~/nginx-1.24.0 ./configure \  --prefix=/etc/nginx \  --sbin-path=/usr/sbin/nginx \  --conf-path=/etc/nginx/conf/nginx.conf \  --error-log-path=/var/log/nginx/error.log \  --http-log-path=/var/log/nginx/access.log \  --pid-path=/run/nginx.pid \  --with-http_ssl_module \  --with-http_v2_module \  --with-http_gzip_static_module \  --add-module=/tmp/nginx-module-vts make -j$(nproc) sudo make install ``` > **Important:** `--pid-path=/run/nginx.pid` must match what systemd expects. If these differ, Nginx will time out on startup. This is the most common setup mistake. Verify VTS is compiled in: ```plaintext /usr/sbin/nginx -V 2>&1 | grep vts ``` You must see `--add-module=/tmp/nginx-module-vts` in the output before continuing. ### Step 5 — Create the Nginx Configuration File ```plaintext sudo mkdir -p /etc/nginx/conf sudo vi /etc/nginx/conf/nginx.conf ``` Paste the following complete configuration: ```plaintext worker_processes auto; pid /run/nginx.pid; events {    worker_connections 1024; } http {    vhost_traffic_status_zone;    upstream opc_backend {        least_conn;        server 192.168.14.157:28767 max_fails=3 fail_timeout=30s;        server 192.168.14.217:28767 max_fails=3 fail_timeout=30s;    }    server {        listen 80;        server_name _;        location / {            proxy_pass http://opc_backend;            proxy_set_header Host $host;            proxy_set_header X-Real-IP $remote_addr;            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        }    }    server {        listen 8080;        allow 127.0.0.1;        allow 192.168.14.0/24;        allow all;        location /status {            vhost_traffic_status_display;            vhost_traffic_status_display_format html;        }        location /status/format/json {            vhost_traffic_status_display;            vhost_traffic_status_display_format json;        }    } } ``` What each block does: - `worker_processes auto` — Nginx automatically uses one worker per CPU core - `pid /run/nginx.pid` — where Nginx writes its process ID file, must match systemd - `vhost_traffic_status_zone` — activates the VTS stats module - `upstream opc_backend` — defines both OPC servers with passive health checking. If a server fails 3 times within 30 seconds, Nginx stops sending it traffic for 30 seconds, then retries - `server listen 80` — the main load balancer, receives all traffic and forwards to the upstream pool - `server listen 8080` — the stats dashboard, accessible only from localhost or the 192.168.14.x network Test the configuration before proceeding: ```plaintext /usr/sbin/nginx -t -c /etc/nginx/conf/nginx.conf ``` Expected output: ```plaintext nginx: the configuration file /etc/nginx/conf/nginx.conf syntax is ok nginx: configuration file /etc/nginx/conf/nginx.conf test is successful ``` Do not proceed if you see any errors. Fix the config and re-test. ### Step 6 — Fix the systemd Service File The default nginx systemd service does not know about your custom config path or PID location. You must override it or nginx will time out on startup. ```plaintext sudo systemctl edit nginx.service --force ``` This opens an editor. Paste exactly: ```plaintext [Service] PIDFile=/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -q -c /etc/nginx/conf/nginx.conf -g 'daemon on; master_process on;' ExecStart=/usr/sbin/nginx -c /etc/nginx/conf/nginx.conf -g 'daemon on; master_process on;' ExecReload=/bin/kill -s HUP $MAINPID TimeoutStartSec=60 ``` Save and exit, then apply: ```plaintext sudo systemctl daemon-reload sudo systemctl enable nginx sudo systemctl start nginx sudo systemctl status nginx ``` Expected output shows `Active: active (running)`. If it fails, go to Section 6 — Troubleshooting. ### Step 7 — Install Cloudflare Tunnel Cloudflare Tunnel creates a secure outbound connection from your server to Cloudflare's network. No inbound firewall ports need to be opened. The `service install` command automatically creates and starts the systemd service — no config file needs to be created manually. ```plaintext # Add Cloudflare GPG key sudo mkdir -p --mode=0755 /usr/share/keyrings curl -fsSL https://pkg.cloudflare.com/cloudflare-public-v2.gpg | sudo tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/null # Add Cloudflare apt repository echo 'deb [signed-by=/usr/share/keyrings/cloudflare-public-v2.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list # Install cloudflared sudo apt-get update && sudo apt-get install cloudflared -y # Install as background service — replace with your actual token sudo cloudflared service install ``` Verify it is running: ```plaintext sudo systemctl status cloudflared ``` You should see `Active: active (running)` and log lines showing `Registered tunnel connection` for multiple connection indexes. This means Cloudflare has established redundant connections. ## 5. Verification ### Health Check URL The OPC application exposes a heartbeat endpoint. Use this to confirm traffic is flowing end-to-end through Cloudflare → Nginx → OPC server. Open in browser: ```plaintext http://opc-ha-ngnix.xxxxx.com/opc/heart-beat/ ``` Expected response: ![](https://cdn.document360.io/175c0eac-012f-4410-bdc5-ac60794f82d8/Images/Documentation/image-6TW8ITN0.png) A response of `OK` confirms the full path is working — Cloudflare tunnel is up, Nginx is routing correctly, and the OPC backend server is healthy.