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://orhttps://- A hostname
- An IP address
- An upstream group
- A Unix socket
Context Where proxy_pass Is Allowed
| Context | Allowed |
|---|---|
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_pass | Behavior |
|---|---|
| No URI | URI is appended |
| With URI | Location 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 domainX-Real-IP→ client IPX-Forwarded-For→ proxy chainX-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;
}
}