Nginx Behind Haproxy
To run nginx behind haproxy, place HAProxy at the edge to route network traffic. Then set up Nginx on inner hosts to serve web files and apps. Platform teams often use this two-tier setup to split load balancing from web serving. Still, managing both layers often leads to broad host permissions for engineers. When admins share root keys to fix routing rules, one mistake can break traffic. How an nginx behind haproxy architecture works In an nginx behind haproxy setup, each tool does one clear
NGINX Security Configuration + HAProxy Security: the complete guide
Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.
To run nginx behind haproxy, place HAProxy at the edge to route network traffic. Then set up Nginx on inner hosts to serve web files and apps. Platform teams often use this two-tier setup to split load balancing from web serving. Still, managing both layers often leads to broad host permissions for engineers. When admins share root keys to fix routing rules, one mistake can break traffic.
How an nginx behind haproxy architecture works
In an nginx behind haproxy setup, each tool does one clear job well. HAProxy sits on the front line and takes in all public requests. It checks server health, drops bad connections, and spreads load across many backend nodes. It can also handle TLS keys at the edge so inner servers work less.
Once HAProxy picks a healthy node, it forwards the request to an Nginx host. Nginx acts as the web server and local router for the app. It serves static files like images and scripts right from the disk. It also sends dynamic requests to local app processes running on that same machine.
When traffic jumps through two routers, the inner server loses the client IP address. By default, Nginx only sees the internal IP address of the HAProxy node. This causes problems for audit logs, rate limits, and geo rules on the backend. Every request in the Nginx log looks like it came from the load balancer.
Forwarding client data between the two tiers
Teams fix the missing IP problem in two primary ways. For web traffic, HAProxy can add a standard forwarding header to every HTTP request. Nginx reads this header and swaps in the real client IP for its logs. You must tell Nginx to trust the HAProxy subnet before it accepts that header. Without that trust rule, anyone could fake their IP address in a request.
For raw TCP traffic or mixed protocols, teams use the PROXY protocol instead. HAProxy wraps connection details in a small header before sending data to Nginx. Nginx reads this wrapper at the start of the connection to get the IP. Both tiers must agree on this setting, or connections will fail right away.
Health checks also need care when you run two tiers of routing. HAProxy polls Nginx on a set schedule to see if the node is up. If Nginx returns a good status even when the app is dead, traffic drops. Engineers must wire the Nginx health check path through to the real app status.
NGINX Security Configuration + HAProxy Security: architecture patterns and best practices
Continue reading? Get the full guide.
Free. No spam. Unsubscribe anytime.
What native routing solves and the operational gap
This two-tier pattern gives teams great control over network flow and server load. HAProxy handles high connection counts and fast failovers without breaking a sweat. Meanwhile, Nginx caches static content and buffers slow clients away from the app code. Together, they keep public web traffic fast and stable during big spikes.
Yet this network setup only controls how public user traffic reaches the app. It does not solve how engineers log in to manage these Linux hosts. When a routing rule fails, admins often log in with shared admin keys. Native host access decides who can log in, not what commands they run inside.
An engineer fixing an Nginx file often gets full root control over the machine. From there, they can read private TLS keys or query internal databases by mistake. Standard network rules cannot stop a risky command inside an active admin session. Also, if sensitive data like emails or card numbers flows through debug logs, anyone on the box can read it unless masking rewrites matched fields in results.
Add runtime guardrails and masking beside your databases and APIs
Login rules, role grants, and CI checks govern who connects to your stack. Yet any allowed script, engineer, or AI agent still runs commands with the full scope of its role. For workloads on Postgres, MySQL, SQL Server, MongoDB, ClickHouse, Kubernetes, SSH, or internal HTTP services, hoop.dev sits beside the service as an open-source proxy, a sidecar for your database or API.
Before a query runs, hoop.dev guardrails check the statement against your rules. An AI Analyzer you configure can score intent or hold risky calls for human review. Next, hoop.dev data masking rewrites sensitive fields in responses, and each verdict is logged per listener. Explore the MIT-licensed project on GitHub.
Frequently asked questions
Why put Nginx behind HAProxy instead of using just one tool?
HAProxy excels at pure load balancing, complex health checks, and high connection counts. Nginx excels at serving static files, caching responses, and running local fastcgi apps. Running both lets each layer focus on its best task on busy sites.
Where should TLS termination happen in this two-tier setup?
Most teams terminate public TLS at the HAProxy edge to keep key management in one place. If internal network rules require encryption, HAProxy can re-encrypt traffic to Nginx using internal certificates.
How do you prevent IP spoofing when passing client addresses to Nginx?
Configure Nginx to only accept forwarded IP headers from the exact internal IP addresses of your HAProxy nodes. Also configure HAProxy to strip out any existing forwarded headers sent by external clients before adding its own.
Related guides
In this post