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.
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.
- return — sends the redirect immediately, without evaluating the URL any further. This is the recommended directive for simple, fixed redirects.
- rewrite — matches the request against a regular expression and can rewrite it internally (no redirect sent to the browser) or externally as a redirect, using capture groups for pattern-based rules.
- Status codes —
301means "moved permanently" and302means "moved temporarily." The code you choose changes how browsers cache the redirect and how search engines treat it. - Where it lives — redirects go inside
/etc/nginx/nginx.conf, or more commonly inside a site-specific file under/etc/nginx/sites-available/that's symlinked intosites-enabled/.
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.
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:
- Broken links stop working. Every inbound link, bookmark, and search result pointing at an old URL turns into a 404 the moment that URL stops existing without a redirect in place.
- Search rankings don't transfer on their own. A 301 redirect tells search engines to pass the old page's ranking signals to the new URL; without it, that history is effectively lost.
- The wrong status code sends the wrong signal. A 302 used for a permanent move can cause search engines to keep indexing the old URL instead of updating to the new one.
- Performance is on the line too. A
rewritedirective used where a simplereturnwould do adds unnecessary regex evaluation on every request to that path.
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:
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
- 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.
-
Open the site's Nginx config file. This is usually at
/etc/nginx/sites-available/your-site— edit it withsudo nanoor your preferred editor. -
Find or create the relevant server block. For a single page, add the redirect inside a
locationblock; for a whole domain or protocol change, add it inside theserverblock itself. -
Add the return directive. Match the pattern to the scenario — a single path needs an exact
locationmatch, while a domain or protocol change belongs directly inside theserverblock. -
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. -
Reload Nginx. Run
sudo systemctl reload nginx(orsudo nginx -s reload) to apply the change without dropping active connections. -
Verify the redirect. Run
curl -I https://yoursite.com/old-pageand confirm the response shows the correct status code and aLocationheader 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:
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.
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.
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.
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.
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.
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.
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.
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.
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:
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.
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.