Redirect one domain to another with Nginx
Preserve paths and query strings in a domain redirect, rewrite changed paths, and retain valid TLS on the old hostname.
For a whole-site domain move, return a redirect to the new hostname and append $request_uri to preserve the original path and query string:
server {
listen 80;
server_name old-example.com;
return 301 https://new-example.com$request_uri;
}
A request for /a?x=1 points to https://new-example.com/a?x=1. Using an explicit https target avoids carrying plain HTTP forward to the new site.
Choose the redirect status deliberately
301 and 308 indicate a permanent move; 302 and 307 are temporary. Unlike 301/302, 307/308 preserve the request method. For API requests, test client behavior and consider whether old clients should continue calling the old hostname at all.
A permanent redirect is a migration signal for search engines, not a guarantee of rankings or an immediate transfer of every indexing signal. Preserve meaningful page-to-page destinations instead of redirecting all old URLs to the homepage.
Rewrite paths only when the structure changed
server {
listen 80;
server_name old-example.com;
rewrite ^/blog/(.*)$ https://new-example.com/articles/$1 permanent;
return 301 https://new-example.com$request_uri;
}
The first matching rewrite redirects /blog/post to /articles/post; other paths use the fallback. permanent produces 301 and redirect produces 302. Original arguments are retained unless the replacement ends in ?:
rewrite ^/blog/(.*)$ https://new-example.com/articles/$1? permanent;
That alternative drops the original query string. Test encoded paths and parameters that matter to the application.
A server-level return runs during the rewrite phase before location selection. If specific locations need exceptions, put the catch-all return inside location / instead.
Keep HTTPS working on the old domain
server {
listen 443 ssl;
server_name old-example.com;
ssl_certificate /etc/nginx/ssl/old-example.com-fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/old-example.com.key;
return 301 https://new-example.com$request_uri;
}
TLS negotiation happens before the browser can receive the redirect. The old hostname therefore still needs a valid certificate and reachable DNS. An expired certificate cannot be repaired by a redirect response that the client will not trust.
Validate real old links
sudo nginx -t && sudo systemctl reload nginx
curl -I 'http://old-example.com/a?x=1'
curl -IL 'https://old-example.com/blog/post?source=docs'
Inspect every status and Location, plus the final response. server_name may list several old names, but their certificates must cover HTTPS access. Keep the new site's server configuration distinct to avoid a redirect loop.
After the migration, compare old and new 404s and fix broken mappings rather than assuming a successful homepage redirect covers the site.
FAQ
Should a domain migration always use 301?
Use a permanent redirect for a permanent move. 301 is widely used; 308 is also permanent and preserves the method. Search behavior is more nuanced than “302 never transfers signals”; choose the code based on the actual move and request semantics.
Should I use return or rewrite?
Use return for an unchanged URI with a different origin. Use rewrite when a regular expression needs to transform the path. Prefer readability over an unmeasured performance claim.
Why did the browser's address bar stay unchanged?
A reverse proxy using proxy_pass fetches a response on the client's behalf. It does not itself instruct the browser to navigate. An HTTP redirect does.
References: return and rewrite, TLS server configuration.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan