Skip to main content

proxay_pass

proxy_pass is a directive from the ngx_http_proxy_module that tells NGINX to forward (proxy) client requests to an upstream backend server and return the backend’s response to the client.

In short:

Client → NGINX (reverse proxy) → Backend server

Why proxy_pass Is Used

proxy_pass enables NGINX to act as a reverse proxy, providing:

  • Load balancing
  • Security (hide backend servers)
  • SSL termination
  • Caching
  • Request routing
  • Centralized access control

Basic Syntax

proxy_pass URL;

Where URL can be:

  • http:// or https://
  • A hostname
  • An IP address
  • An upstream group
  • A Unix socket

Context Where proxy_pass Is Allowed

ContextAllowed
location
if (inside location)⚠️ limited
server
http

proxy_pass is almost always used inside a location block.

Simple Reverse Proxy

server {
listen 80;

location / {
proxy_pass http://localhost:3000;
}
}
  • Client requests http://example.com/
  • NGINX forwards request to http://localhost:3000
  • Backend response is returned to the client
  • Client never sees the backend address

How Request Flow Works

Request:

GET /products?id=10 HTTP/1.1
Host: example.com

NGINX:

  • Receives request
  • Matches location /
  • Proxies request to backend
  • Sends response back to client

proxy_pass With URI

The presence or absence of a trailing slash (/) in proxy_pass changes behavior.

Case 1: proxy_pass WITHOUT URI

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

Result

/api/users → http://backend/api/users

Full original URI is preserved

Case 2: proxy_pass WITH URI

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

Result

/api/users → http://backend/users

Matching part (/api/) is replaced

Rule to Remember

proxy_passBehavior
No URIURI is appended
With URILocation prefix is replaced

Reverse Proxy Using Upstream (Load Balancing)

upstream backend_app {
server 10.0.0.11:8080;
server 10.0.0.12:8080;
}

Usage

location / {
proxy_pass http://backend_app;
}
  • Requests distributed across multiple servers
  • Default algorithm: round-robin
  • Backend failures handled automatically

Commonly Used Proxy Headers

When using proxy_pass, you must forward important headers.

location / {
proxy_pass http://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;
proxy_set_header X-Forwarded-Proto $scheme;
}
  • Host → original domain
  • X-Real-IP → client IP
  • X-Forwarded-For → proxy chain
  • X-Forwarded-Proto → http/https

Proxying to HTTPS Backend

location / {
proxy_pass https://backend.example.com;
}

Optional SSL tuning:

proxy_ssl_server_name on;
proxy_ssl_verify off;

Proxy to Unix Socket (High Performance)

location / {
proxy_pass http://unix:/run/backend.sock;
}
  • Faster than TCP
  • Common for local services

WebSocket Proxying

WebSockets require HTTP/1.1 and upgrade headers.

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

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

Timeout & Buffer Controls

location / {
proxy_pass http://backend;

proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}

Protects NGINX from slow or dead backends

Common Mistakes

  • Forgetting trailing slash behavior
  • Missing proxy headers
  • Using proxy_pass outside location
  • Proxying HTTPS without SNI
  • Using if incorrectly

Debugging Tips

  • Test config: nginx -t
  • Enable debug logs: error_log /var/log/nginx/error.log debug;
  • Check upstream status: curl -v http://example.com

Real-World Example (Production Style)

server {
listen 80;
server_name example.com;

location /api/ {
proxy_pass http://api_backend/;

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_read_timeout 30s;
}
}