Bird
Raised Fist0
Nginxdevops~5 mins

Proxy headers in Nginx - Commands & Configuration

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
When you use Nginx to forward requests to another server, it needs to send extra information called proxy headers. These headers tell the receiving server details like the original visitor's IP address or the original request protocol. Without these headers, the server might not know where the request really came from or how it was made.
When you want to forward web traffic from Nginx to an application server and keep the visitor's original IP address.
When your backend server needs to know if the original request was made over HTTP or HTTPS.
When you want to pass the original host name from the client to the backend server.
When you want to add security by controlling which headers are sent to the backend.
When you want to enable logging on the backend server with accurate client information.
Config File - nginx.conf
nginx.conf
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:8080;
        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;
    }
}

This configuration sets up Nginx to listen on port 80 for example.com. It forwards all requests to a backend server running on localhost port 8080.

The proxy_set_header lines add important headers:

  • Host sends the original host name.
  • X-Real-IP sends the client's IP address.
  • X-Forwarded-For adds the client's IP to the chain of forwarded addresses.
  • X-Forwarded-Proto tells if the original request was HTTP or HTTPS.
Commands
This command tests the Nginx configuration file for syntax errors before applying changes.
Terminal
sudo nginx -t
Expected OutputExpected
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
This command reloads Nginx to apply the new configuration without stopping the service.
Terminal
sudo systemctl reload nginx
Expected OutputExpected
No output (command runs silently)
This command sends a simple HTTP request to check if Nginx is forwarding requests correctly with the proxy headers.
Terminal
curl -I http://example.com
Expected OutputExpected
HTTP/1.1 200 OK Server: nginx Date: Wed, 01 Jan 2025 12:00:00 GMT Content-Type: text/html Connection: keep-alive
-I - Fetch only HTTP headers without the body
Key Concept

If you remember nothing else from this pattern, remember: proxy headers let the backend server know the original client details when Nginx forwards requests.

Common Mistakes
Not setting the X-Real-IP or X-Forwarded-For headers in the proxy configuration.
The backend server will see Nginx's IP instead of the real client IP, causing incorrect logging and security issues.
Always include proxy_set_header X-Real-IP $remote_addr and proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for in your proxy settings.
Forgetting to reload Nginx after changing the configuration.
Changes won't take effect until Nginx reloads, so the proxy headers won't be sent as expected.
Run sudo nginx -t to test, then sudo systemctl reload nginx to apply changes.
Summary
Use proxy_set_header directives in Nginx to send original client information to backend servers.
Test your Nginx configuration with nginx -t before reloading to avoid errors.
Reload Nginx after changes to apply the new proxy header settings.

Practice

(1/5)
1. What is the main purpose of setting proxy headers like X-Real-IP in an nginx configuration?
easy
A. To encrypt the data between nginx and the client
B. To cache the client's request on nginx
C. To pass the original client's IP address to the backend server
D. To block unwanted IP addresses from accessing the server

Solution

  1. Step 1: Understand proxy headers role

    Proxy headers like X-Real-IP carry client info through nginx to backend servers.
  2. Step 2: Identify the purpose of X-Real-IP

    This header specifically passes the original client's IP address to the backend for logging or processing.
  3. Final Answer:

    To pass the original client's IP address to the backend server -> Option C
  4. Quick Check:

    Proxy headers pass client info = B [OK]
Hint: Remember: X-Real-IP shows client's real IP to backend [OK]
Common Mistakes:
  • Confusing proxy headers with encryption settings
  • Thinking proxy headers cache requests
  • Assuming proxy headers block IPs
2. Which of the following is the correct nginx directive to set the X-Forwarded-Proto header to the client's protocol?
easy
A. proxy_set_header X-Forwarded-Proto $scheme;
B. set_header X-Forwarded-Proto $protocol;
C. proxy_header X-Forwarded-Proto $scheme;
D. header_set X-Forwarded-Proto $protocol;

Solution

  1. Step 1: Recall nginx syntax for proxy headers

    The correct directive to set headers in nginx proxy is proxy_set_header.
  2. Step 2: Match variable for client protocol

    The variable $scheme holds the client's protocol (http or https).
  3. Final Answer:

    proxy_set_header X-Forwarded-Proto $scheme; -> Option A
  4. Quick Check:

    proxy_set_header + $scheme = A [OK]
Hint: Use proxy_set_header with $scheme for protocol header [OK]
Common Mistakes:
  • Using incorrect directive names like set_header
  • Using wrong variable names like $protocol
  • Mixing directive order or syntax
3. Given this nginx proxy configuration snippet:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

What will be the value of X-Forwarded-For if the client IP is 10.0.0.1 and the request passed through one proxy with IP 192.168.1.1?
medium
A. 10.0.0.1
B. 192.168.1.1, 10.0.0.1
C. 192.168.1.1
D. 10.0.0.1, 192.168.1.1

Solution

  1. Step 1: Understand $proxy_add_x_forwarded_for behavior

    This variable appends the $remote_addr (proxy IP seen by nginx) to the existing X-Forwarded-For header chain from previous proxies.
  2. Step 2: Order of IPs in X-Forwarded-For

    The chain lists the original client first, then proxy IPs appended. For client 10.0.0.1 via proxy 192.168.1.1, it becomes 10.0.0.1, 192.168.1.1.
  3. Final Answer:

    10.0.0.1, 192.168.1.1 -> Option D
  4. Quick Check:

    Client IP last in X-Forwarded-For = C [OK]
Hint: X-Forwarded-For lists original client first, then proxies [OK]
Common Mistakes:
  • Reversing IP order in X-Forwarded-For
  • Confusing X-Real-IP with X-Forwarded-For
  • Ignoring existing proxy IPs in header
4. You have this nginx config snippet:
proxy_set_header X-Real-IP $remote_addr
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

When reloading nginx, it fails with a syntax error. What is the problem?
medium
A. Missing semicolon at the end of the first proxy_set_header line
B. Incorrect variable name $proxy_add_x_forwarded_for
C. proxy_set_header cannot be used twice in one block
D. X-Real-IP header cannot be set manually

Solution

  1. Step 1: Check nginx directive syntax

    Each directive line must end with a semicolon in nginx configuration.
  2. Step 2: Identify missing semicolon

    The first line lacks a semicolon after $remote_addr, causing syntax error.
  3. Final Answer:

    Missing semicolon at the end of the first proxy_set_header line -> Option A
  4. Quick Check:

    Every directive needs semicolon = D [OK]
Hint: Always end nginx directives with semicolon [OK]
Common Mistakes:
  • Ignoring semicolon syntax rules
  • Assuming variable names are wrong without checking
  • Thinking headers can't be set multiple times
5. You want to ensure your backend server correctly logs the original client IP and protocol when nginx proxies requests. Which complete nginx proxy header configuration snippet achieves this?
hard
A. proxy_set_header X-Real-IP $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $protocol;
B. 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;
C. proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
D. 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

Solution

  1. Step 1: Verify correct variables for headers

    X-Real-IP should be $remote_addr, X-Forwarded-For uses $proxy_add_x_forwarded_for, and X-Forwarded-Proto uses $scheme.
  2. Step 2: Check syntax correctness

    Each directive must end with a semicolon; 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; has correct syntax and variables.
  3. Final Answer:

    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; -> Option B
  4. Quick Check:

    Correct vars + semicolons = A [OK]
Hint: Use $remote_addr, $proxy_add_x_forwarded_for, $scheme with semicolons [OK]
Common Mistakes:
  • Swapping variables between headers
  • Omitting semicolons causing errors
  • Using undefined variables like $protocol