Your Nginx Redirect Is Probably Wrong — Here's the Fix

One misplaced directive is all it takes to turn a routine URL change into a "too many redirects" error or a silent SEO loss. Here's the two-directive fix, seven mistakes that take sites down in production, and how to verify it before it ships.

A developer sitting at a desk, focused on a monitor while debugging a server configuration issue
Photo: Luke Peters / Unsplash

You've moved a page, merged two domains, or finally switched to HTTPS — and now you need the old URLs to land somewhere useful instead of throwing a 404. Someone tells you "just add a redirect in Nginx," you open the config file, and you're staring at server and location blocks with no idea which directive is safe to touch.

Get it slightly wrong and the failure isn't subtle — it's a redirect loop, a browser error page, or search engines quietly dropping rankings you built over years. The good news is that Nginx redirects are one of the more forgiving parts of server configuration once you know the two directives that do almost all the work. This guide covers those directives, seven real misconfigurations that take sites down in production, and the exact commands to verify a redirect before you ship it.

Quick Answer

To set up an Nginx redirect, add a return 301 directive inside the relevant server or location block pointing to the new URL, save the config file, run nginx -t to check for syntax errors, then reload Nginx with systemctl reload nginx. Use return 301 for permanent moves and return 302 only for temporary ones.

What is an Nginx redirect?

An Nginx redirect is a directive placed inside a server or location block that tells a visitor's browser (or a search engine crawler) to request a different URL than the one it asked for, along with an HTTP status code explaining why.

Everything else — domain migrations, HTTPS enforcement, www normalization, bulk path restructures — is a variation on those two directives applied to a specific server_name or path.

How a redirect actually flows

It helps to see the full round trip before editing config files, because most redirect bugs come from misunderstanding which side is doing what. The browser only ever follows instructions — it never decides on its own that a URL has moved.

Diagram of an Nginx 301 redirect request-response flow Browser GET /old-page Nginx location /old-page { return 301 /new-page; } no backend hit /new-page 200 OK 1. request 2. 301 + Location header 3. browser re-requests /new-page
A 301 redirect is two full HTTP round trips: Nginx never fetches the new page itself — it hands the browser a Location header and the browser makes a second request on its own.

That second round trip is the part people forget. Nginx isn't "showing" the new page — it's telling the browser where the new page lives and stepping out of the way. This is also why a redirect loop is fatal: if step 2 ever points back to a URL that matches the same location block, the browser just keeps repeating steps 1 through 3 until it gives up and shows a "too many redirects" error.

Why getting redirects right matters

A redirect that's misconfigured doesn't always fail loudly — it often just quietly costs you traffic or rankings:

The scale of this compounds fast once a site has been live for a few years. A migration that "only" touches a handful of URLs on paper often turns out to intersect with a much larger surface once old sitemaps, cached search results, and partner links are accounted for:

3–6 mo
Typical time for search engines to fully re-crawl and consolidate a 301'd URL
1 rule
Can usually cover an entire domain move — no per-page mapping needed with $request_uri
0 ms
Extra backend time added by a return directive — it never touches the app server
📊 Quick stat Nginx's own documentation recommends return over rewrite for any redirect that doesn't need pattern matching, specifically because rewrite is evaluated on every request and is a more common source of misconfiguration and redirect loops.

Step-by-step: setting up a redirect

  1. Identify the old URL and the new URL. Write down exactly what should redirect to what, including whether it's a single page, a whole path, or an entire domain.
  2. Open the site's Nginx config file. This is usually at /etc/nginx/sites-available/your-site — edit it with sudo nano or your preferred editor.
  3. Find or create the relevant server block. For a single page, add the redirect inside a location block; for a whole domain or protocol change, add it inside the server block itself.
  4. Add the return directive. Match the pattern to the scenario — a single path needs an exact location match, while a domain or protocol change belongs directly inside the server block.
  5. Test the configuration. Run sudo nginx -t — this checks the syntax without applying anything, and will point to the exact line if something's wrong.
  6. Reload Nginx. Run sudo systemctl reload nginx (or sudo nginx -s reload) to apply the change without dropping active connections.
  7. Verify the redirect. Run curl -I https://yoursite.com/old-page and confirm the response shows the correct status code and a Location header pointing to the new URL.

Here's what that looks like as actual config, for the two most common cases — a single page move and a full HTTP-to-HTTPS upgrade for the whole domain:

nginx · single page redirect
# Redirects one exact old URL to one exact new URL location = /old-page { return 301 /new-page; }
nginx · http to https, entire domain
# Every request on port 80 is upgraded to https, # with the original path preserved via $request_uri server { listen 80; server_name yoursite.com www.yoursite.com; return 301 https://$host$request_uri; }
Try the Rebrixe Nginx Redirect Generator — free Fill in your old and new URLs, get a ready-to-paste server block. No syntax memorizing required.
Generate Redirect Rule →

7 mistakes that break production

Most redirect incidents trace back to one of these seven patterns. Each one is easy to avoid once you know to check for it.

A developer wearing headphones, staring intently at a monitor while troubleshooting a configuration error
Most of these mistakes surface at the worst possible time — mid-deploy, with traffic already flowing. Photo: Nubelson Fernandes / Unsplash
1

Using rewrite when return would do the job

rewrite is built for pattern matching with regular expressions. For a straightforward one-to-one redirect, it adds unnecessary regex processing on every matching request — return is faster and much harder to misconfigure.

2

Creating a redirect loop

This usually happens when the destination URL falls inside the same location block that's issuing the redirect, or when an HTTPS redirect sits behind a load balancer or reverse proxy that doesn't correctly forward the original protocol — so Nginx thinks every request is still on HTTP and keeps redirecting it. The fix is usually to trust the X-Forwarded-Proto header from the proxy instead of relying on Nginx's own view of the connection.

3

Reaching for 302 on a permanent move

A 302 tells search engines the old URL might come back, so they keep it in the index instead of transferring its ranking signals. If the move is permanent, the status code should say so — reserve 302 for genuinely temporary situations like a maintenance page.

4

Editing the config and forgetting to reload

Saving the file doesn't apply anything on its own. Without running nginx -t and then reloading, the live server keeps serving the old configuration until it's explicitly told to pick up the change.

5

Mismatched trailing slashes

location /old-page and location /old-page/ are not the same match in Nginx. A redirect rule written for one won't necessarily catch requests to the other, which can leave some incoming links — especially ones with a trailing slash added by a CMS — unredirected.

6

Dropping query strings during a redirect

A plain return 301 /new-page; silently strips anything after a ? in the original request. If old links include tracking parameters, filters, or pagination that still matter, the redirect needs to explicitly forward $is_args$args so that information isn't lost.

7

Testing in a browser that already cached the old redirect

Browsers cache 301 responses aggressively, sometimes ignoring server-side changes entirely during the same session. A redirect that was fixed on the server can still appear broken in a browser tab that visited the old URL earlier — always verify with curl -I or a private browsing window, not the tab you were just testing in.

💡 Pro tip Always run nginx -t before every reload, even for a change that looks trivial. It takes a second and it's the difference between a clean reload and taking your entire site down over a missing semicolon.

Real-world examples

How the same two directives cover almost every situation you'll actually run into, from a single moved article to a full domain rebrand:

Single page moved
Path-to-path redirect
return 301
An old blog URL redirects to its new location inside a location block matching the exact old path.
Protocol upgrade
HTTP to HTTPS
Separate port 80 block
A dedicated server block listening on port 80 redirects every request to the same path on HTTPS.
Domain rebrand
Old domain to new domain
$request_uri preserved
Every path on the retired domain maps to the identical path on the new domain in one rule.
Canonical host
www to non-www
One server_name match
A server block matching the www subdomain redirects to the bare domain to avoid duplicate content.
Blog restructure
Folder-wide path change
rewrite with capture group
Every URL under an old /articles/ folder maps to the same slug under a new /blog/ folder in one rule.
Site relaunch
Bulk unrelated URL list
map + redirect map file
Hundreds of old-to-new URL pairs with no shared pattern are resolved through a lookup table instead of dozens of location blocks.

The folder restructure and bulk-list cases are worth seeing in config form, since they're where people reach for the wrong tool most often.

nginx · folder-wide redirect with rewrite
# /articles/how-to-cook-rice → /blog/how-to-cook-rice # The (.*) capture group carries the slug over unchanged location /articles/ { rewrite ^/articles/(.*)$ /blog/$1 permanent; }
nginx · bulk redirects via a map file
# In nginx.conf, at the http block level map $uri $new_uri { /old-page-1 /new-page-1; /old-page-2 /new-page-2; /legacy/x /modern/x; } # Inside the server block if ($new_uri) { return 301 $new_uri; }
⚠️ Note on if Nginx's documentation is famously wary of the if directive inside location blocks because of how unpredictably it interacts with other rules. Pairing it with map at the server level, as shown above, is one of the few patterns considered safe — it's specifically how Nginx recommends handling large lists of unrelated redirects.

return vs rewrite vs map compared

Nginx offers more than one way to redirect traffic. Here's how the main approaches differ, and which one fits which real-world scenario from above.

Method Performance Flexibility Best for
return Fastest, no regex evaluated Fixed, one-to-one paths Single pages, domain moves, HTTPS enforcement
rewrite Slower, regex on every request Pattern-based, capture groups Bulk URL restructures with a shared pattern, like a renamed folder
map Fast lookup table Many-to-many, easy to scale Large lists of unrelated old-to-new URL pairs after a site relaunch
error_page 404 Not a true redirect Same status code for all Not recommended for SEO-relevant redirects

Generate your Nginx redirect rule right now — free

The Rebrixe Nginx Redirect Generator builds a clean, ready-to-paste server or location block for the most common redirect scenarios — single page, domain move, www normalization, and HTTPS enforcement. No account needed, just fill in the URLs and copy the result.

Free Nginx Redirect Generator Enter your old and new URL, copy the config block.
Open Redirect Generator →

Frequently asked questions

return sends an immediate redirect response without evaluating the request further, making it faster and simpler for straightforward one-to-one redirects. rewrite evaluates the URL against a regular expression and can rewrite it internally or externally, which is more powerful but also more resource-intensive and easier to misconfigure.
Use a 301 (return 301) when the move is permanent, such as after a URL restructure or domain change, since it passes link equity to the new URL and tells search engines to update their index. Use a 302 (return 302) only for temporary moves, like a short maintenance redirect, since it does not transfer ranking signals the same way.
Run nginx -t after editing the config file to check for syntax errors, then reload Nginx and use a command like curl -I on the old URL to confirm it returns the correct status code and Location header pointing to the new URL.
A redirect loop usually happens when the destination URL matches the same location block that triggered the redirect, so the server keeps redirecting to itself. This is common with HTTPS redirects behind a proxy that doesn't correctly report the original protocol, or with rewrite rules that don't exclude the target path.
A full restart isn't necessary. Running sudo nginx -t to validate the config followed by sudo systemctl reload nginx (or nginx -s reload) applies the new redirect without dropping active connections.
Yes. A server block matching the old domain's server_name can use a single return 301 directive pointing to the new domain, with $request_uri appended so every path on the old domain maps to the same path on the new one.
Create a separate server block listening on port 80 for the domain, and inside it use a single return 301 https://$host$request_uri directive. Keeping HTTP and HTTPS in separate server blocks avoids conditional logic and is the configuration Nginx's own documentation recommends.
Use a prefix location block matching the old folder without the exact modifier, then a rewrite directive that captures the remainder of the path and appends it to the new folder, or a return directive combined with $request_uri if the new folder mirrors the same structure.
This is almost always a caching issue. Browsers aggressively cache 301 responses, so a redirect tested, changed, and retested in the same browser session may still show the old destination until the cache is cleared or the test is run in a private window.

Generate your Nginx redirect rule in seconds

The Rebrixe Nginx Redirect Generator builds a clean, ready-to-paste config block for the most common redirect scenarios — no account needed, just a copy-ready server or location block.

Launch the Redirect Generator →
← Back to blogs