XiaTools

SysAdmin Guide: Tracing Nginx Server Block Redirects

Updated 10 Oct 2026

Tracing and debugging unexpected HTTP redirects in Nginx server blocks requires a systematic approach to examine headers, location match orders, and return directives. Whether you are migrating domains, enforcing HTTPS, or fixing erratic browser redirect loops, understanding how Nginx evaluates requests is essential for reliable web operations.

Before diving into complex configuration files, you can quickly analyze your live routing behavior using the Redirect Checker to inspect the complete HTTP status code chain, final destination, and intermediate header hops instantly.

Understanding Nginx Redirect Mechanics

Nginx handles redirects through a combination of directives, primarily return, rewrite, and try_files, acting across server and location contexts. Unlike Apache, which parses .htaccess files distributed across directories, Nginx evaluates static configuration blocks sequentially based on specific match precedence rules.

When a request hits your server, Nginx first selects the best matching server block based on the listen directives and the Host header. It then evaluates location blocks using exact matches (=), preferential prefix matches (^~), regular expressions (~ or ~*), and standard prefix matches. If a redirect directive exists within the winning block, Nginx immediately halts further processing, appends the appropriate Location header, and sends an HTTP status code back to the client.

Common Redirect Directives Compared

Directive Context Behavior Use Case
return server, location, if Stops processing immediately and returns code + URL. Permanent (301) or temporary (302) redirects to new domains or protocols.
rewrite server, location, if Rewrites URI using regex; can trigger internal or external redirects. Complex pattern matching, query string preservation, legacy URL restructuring.
error_page http, server, location Catches HTTP errors and redirects internally or externally. Custom 404 pages or routing 50x errors to maintenance nodes.

Step-by-Step CLI Debugging Workflow

When troubleshooting complex redirection loops, relying solely on a web browser can be misleading due to aggressive client-side caching. Use these command-line tools to inspect the raw network transactions.

1. Tracing Headers with cURL

Use curl with the -I or -L flags to trace every intermediate hop and verify the exact status codes and Location headers returned by Nginx.

curl -I -v https://example.com/old-path

Sample output showing a clean 301 permanent redirect:

*   Trying 192.0.2.1:443...
* Connected to example.com (192.0.2.1) port 443 (#0)
> GET /old-path HTTP/2
> Host: example.com
> User-Agent: curl/7.88.1
> Accept: */*
<
HTTP/2 301 
Server: nginx/1.24.0
Date: Tue, 01 Jan 2025 00:00:00 GMT
Content-Type: text/html
Content-Length: 169
Location: https://example.com/new-path

To follow the entire chain automatically until the final 200 OK response, run:

curl -sIL https://example.com/old-path

2. Inspecting DNS and IP Routing

Before blaming Nginx configuration files, ensure your domain points to the expected server IP using dig or nslookup:

dig +short example.com A
dig +short -x 192.0.2.1

3. Testing Configuration Syntax and Dry Runs

Always validate your Nginx configuration syntax before reloading the service in production:

sudo nginx -t

If the test passes, gracefully reload Nginx to apply changes without dropping active connections:

sudo systemctl reload nginx

Analyzing Nginx Error Logs for Redirect Loops

Infinite redirect loops often manifest as HTTP 500 errors or browser warnings about too many redirects. Nginx logs these events to the error log file, typically located at /var/log/nginx/error.log.

Increase your log verbosity temporarily by editing your nginx.conf file under the http context:

error_log /var/log/nginx/error.log debug;

Tail the error log while generating a test request from your terminal:

sudo tail -f /var/log/nginx/error.log | grep -i rewrite

Look for entries indicating rewrite limits or recursive location matching:

2025/01/01 00:00:00 [notice] 12345#12345: *1 recursive redirection, client: 192.0.2.50, server: example.com, request: "GET / HTTP/1.1", host: "example.com"

This specific error indicates that a location block is matching a request, issuing a rewrite or redirect, and the resulting URI is matching the exact same rule again.

Common Nginx Redirect Pitfalls and Fixes

Pitfall 1: The Catch-All HTTP to HTTPS Loop

A classic misconfiguration occurs when enforcing SSL inside a catch-all server block without checking if the incoming request is already secure.

Incorrect Configuration:

server {
    listen 80;
    listen 443 ssl;
    server_name example.com;
    # This triggers an infinite loop for HTTPS requests if ssl directives fail or match incorrectly
    return 301 https://$host$request_uri;
}

Correct Configuration: Split your HTTP and HTTPS traffic into distinct server blocks:

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;
    # Application logic goes here
}

Pitfall 2: Using if Inside Location Blocks

In Nginx administration, the adage "if is evil" (ifIsEvil) is well-documented. Using if directives inside location contexts can cause unpredictable redirection behavior because if creates a separate configuration context.

Avoid this pattern:

location / {
    if ($http_user_agent ~* "BadBot") {
        return 403;
    }
    if ($request_method = POST) {
        return 301 https://secure.example.com$request_uri;
    }
}

Fix: Use standard map directives in the http context or separate location blocks instead of conditional if statements.

Pitfall 3: Forgetting Trailing Slashes

When defining return or rewrite rules with URIs, missing or extra trailing slashes can accidentally strip parameters or cause double slashes in the destination URL.

Example Fix:

# Correct preservation of request URI parameters
location /old-folder/ {
    return 301 https://example.com/new-folder$request_uri;
}

SysAdmin Troubleshooting Checklist

  • Verify DNS records point to the correct server IP address (192.0.2.1 or 2001:db8::1).
  • Run sudo nginx -t to confirm syntax validity.
  • Test HTTP headers using curl -I -v to examine intermediate status codes.
  • Check /var/log/nginx/error.log for recursive redirection notices.
  • Ensure HTTP and HTTPS server blocks are cleanly separated in your configuration files.
  • Clear local browser cache or test in incognito mode to bypass cached 301 responses.
  • Confirm that load balancers or reverse proxies (e.g., Cloudflare, AWS ALB) are not conflicting with Nginx SSL termination headers (X-Forwarded-Proto).

By following this structured workflow, you can accurately trace, diagnose, and resolve even the most complex Nginx server block redirection issues in production environments.

Frequently asked questions

Why does my browser keep showing a redirect loop even after fixing the Nginx configuration?

Web browsers aggressively cache permanent 301 redirects for performance reasons. When you test your changes, clear your browser cache, use an incognito window, or test directly from the command line using curl to see the real-time headers.

What is the performance difference between using return and rewrite for redirects?

The return directive is significantly faster and cleaner because it executes immediately without evaluating regular expressions. Always prefer return over rewrite when executing static domain or protocol redirects.

How do I preserve query parameters when redirecting an Nginx location block?

Nginx automatically appends query parameters to the destination URL if you use the $request_uri variable instead of $uri. Ensure your return statement uses $request_uri to maintain query strings seamlessly.

Why does Nginx log a recursive redirection error?

This error occurs when a request matches a location block, triggers a redirect rule, and the resulting destination URI matches that same location block again. Separating your catch-all server blocks and refining location match criteria resolves this.

How can I handle HTTP to HTTPS redirection when Nginx sits behind a load balancer?

When Nginx sits behind an SSL-terminating load balancer, direct checks on $scheme will always show http. You must configure Nginx to inspect the X-Forwarded-Proto header sent by the proxy to determine if the original client connection was secure.

Related articles

Free tools