How to Do 301 Redirects with Nginx


Hi everyone, this is Neo.

A few friends running independent sites came to me in a panic recently: after a site redesign, their traffic took a cliff dive. When we dug in, the cause was clear — the URL structure changed, but the old links were never handled and were all returning 404.

That’s an “operational disaster”! All the SEO we worked so hard on, all the backlinks we built — gone because of one redesign?

Don’t panic. Today Neo is going to walk you through how to use Nginx — that Swiss Army knife of web servers — to do 301 redirects and seamlessly “graft” old traffic onto new pages. Whether you want to turn www.yoursite.com/zh-CN/ into zh-cn.yoursite.com, or simply force HTTP to HTTPS, this article has you covered.


Why 301? Why Nginx?

Before we write any code, let’s get two concepts straight:

  1. 301 Moved Permanently: This tells Google and other search engines, “Hey, my home base has moved — the new address is here, please transfer all the authority (credibility) I’ve accumulated to the new address.” It’s the most SEO-friendly type of redirect.
  2. Nginx: Most independent sites (except Shopify, which is SaaS) that deploy on their own servers (like AWS or Alibaba Cloud) run Nginx. It handles concurrency incredibly well and is a beast at redirects too.

Core Practice: Seamless Switch from “Directory” to “Subdomain”

This is a concrete need one friend with a multilingual site ran into: He wanted all requests starting with https://www.yoursite.com/zh-CN/ to automatically jump to https://zh-cn.yoursite.com/.

The benefits are obvious: subdomains look more professional, and you can run independent SEO strategies per country.

Option 1: Use the rewrite Directive (Flexible and Powerful)

This is the most universal approach, suited for scenarios that need regex matching.

Open your Nginx config file (usually at /etc/nginx/nginx.conf or /etc/nginx/sites-available/yoursite.conf), and find the server block for your main domain:

server {
    listen 443 ssl;
    server_name www.yoursite.com;

    # SSL certificate config omitted...

    # [Neo's key notes] This is the core config
    # Explanation: match all paths starting with /zh-CN/
    rewrite ^/zh-CN/(.*)$ https://zh-cn.yoursite.com/$1 permanent;

    # Similarly, handle Bulgarian
    rewrite ^/bg/(.*)$ https://bg.yoursite.com/$1 permanent;

    # Other regular config...
    location / {
        proxy_pass http://backend_server;
    }
}

Neo’s take:

  • ^/zh-CN/(.*)$: This is a regex.
    • ^ marks the start.
    • (.*) “captures” everything after it (like about-us) and stores it in the variable $1.
  • permanent: This keyword is critical — it tells Nginx to return a 301 status code instead of the default 302 (temporary redirect).

Option 2: Use the return Directive (Better Performance)

If you’re after maximum performance, or your matching rules are simple, location combined with return is the better choice. Nginx’s official docs also recommend this approach because it’s more efficient than rewrite.

server {
    listen 443 ssl;
    server_name www.yoursite.com;

    # Precision strike for the Chinese directory
    location ~ ^/zh-CN/(.*)$ {
        return 301 https://zh-cn.yoursite.com/$1;
    }

    # Precision strike for Bulgarian
    location ~ ^/bg/(.*)$ {
        return 301 https://bg.yoursite.com/$1;
    }

    # Default traffic handling
    location / {
        # Your normal business logic
    }
}

Why is this approach better? Because the return directive immediately stops Nginx from doing any further processing of the current request and returns the response directly. rewrite, on the other hand, may trigger other internal rule checks, consuming a tiny but real amount of CPU. For high-concurrency independent sites, these micro-optimizations add up.


3 Redirect Scenarios Every Independent Site Operator Needs

Beyond the “directory to subdomain” case above, you’ll hit these three classic situations in daily operations:

Scenario 1: Force HTTP to HTTPS (Security and Compliance)

Without HTTPS, Google Chrome now shows a direct “Not secure” warning, which badly hurts conversions.

server {
    listen 80;
    server_name www.yoursite.com yoursite.com;
    
    # $host keeps the domain the user requested, $request_uri keeps the path and query params
    return 301 https://$host$request_uri;
}

Scenario 2: Unify WWW and Non-WWW (Consolidate Authority)

yoursite.com and www.yoursite.com look like two different websites to search engines! Splitting your authority is a cardinal sin. Usually you pick one as the primary (say, the www version) and redirect the other to it.

# A dedicated server block that handles the "transfer"
server {
    listen 443 ssl;
    server_name yoursite.com; # listen for the non-www domain

    # SSL config...

    # 301 redirect to the www domain
    return 301 https://www.yoursite.com$request_uri;
}

Scenario 3: Handling a Delisted Bestseller

If your bestseller best-shoes-2024 is delisted, don’t delete the page outright! Users who click in and hit a 404 will close the tab instantly. Strategy: redirect to a similar product page, or the parent category page.

location = /products/best-shoes-2024 {
    return 301 https://www.yoursite.com/collections/shoes;
}

Note the = here — it means exact match, which is the most efficient.


Neo’s Pitfall Guide: Blood-and-Tears Lessons from the Trenches

There are a few traps you must avoid when working with Nginx redirects:

  1. Browser cache is the devil: A 301 is a permanent redirect, and browsers cache it for a long time. If you misconfigure (say, create an infinite loop), even after you fix the server config, your browser may still remember the wrong jump.

    • Workaround: When testing, always use Chrome’s Incognito Mode, or test with return 302 first and only switch to 301 once you’ve confirmed everything works.
  2. Redirect Loops: For example, you redirect A to B, and in B’s config you redirect B back to A. The browser throws “too many redirects.”

    • Workaround: After configuring, check the headers with a command-line tool like curl -I https://www.yoursite.com/zh-CN/ to see where it actually goes.
  3. The three-step activation ritual: Many beginners edit the file and refresh the page, see nothing change, and assume they wrote it wrong. In fact, you skipped the critical steps:

    • Step 1: Edit the config file.
    • Step 2: Check the syntax! Run sudo nginx -t. Only continue if you see successful — otherwise your site will go down.
    • Step 3: Reload the service. Run sudo systemctl reload nginx.

Summary

Getting 301 redirects right is the basic skill of technical SEO for independent sites. It not only rescues traffic lost in redesigns, but also consolidates authority and lifts rankings.

  • Simple redirects: go with return 301.
  • Complex rules: use rewrite.
  • Testing principle: test with 302 first, switch to 301 once confirmed, and verify in an incognito browser.

Hope this article helps your independent site transition smoothly — and your traffic surge!


References: