2026年11月12日

2026年11月12日

Nginx HTTP to HTTPS Redirect: How to Write return 301 and Test It

This article is a localized edition of the Japanese original. Read the Japanese original

Once your site supports HTTPS, redirect visits to http:// to the same URL on https://. Visitors arriving from old links and bookmarks then see the HTTPS version, and search engines learn that the HTTPS URL is the correct one.

In Nginx, the basic method is a single return 301 line in the server block that listens on port 80 (HTTP). The configuration in this article was tested on Nginx 1.24 and 1.30 (as of November 2026).

Prerequisite: the site works over HTTPS

Before adding the redirect, make sure your site loads at https://. If you redirect without a certificate, visitors get an error page. For getting a Let's Encrypt certificate, see "Setting up a Let's Encrypt certificate for Nginx with Certbot".

If you use Certbot

If you add --redirect when getting a certificate with Certbot's Nginx plugin, it also adds the HTTP to HTTPS redirect automatically.

sudo certbot --nginx --redirect -d example.com -d www.example.com

Settings that Certbot adds are marked # managed by Certbot. You can use them as they are. If you write the configuration yourself, use the settings in the next section.

Writing the configuration yourself

The port 80 server block redirects every request to HTTPS. The port 443 server block serves the site. Replace example.com and the certificate paths with your own.

# HTTP: redirect everything to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

# HTTPS: serve the site
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    root /var/www/example.com;
    # existing settings follow (index, location and so on)
}
  • return 301: Redirects with a 301 response, meaning "moved permanently". It is simpler than rewrite, which uses regular expressions, and easier to read.
  • $host: The host name of the request. A request to example.com goes to https://example.com, and one to www.example.com goes to https://www.example.com.
  • $request_uri: Carries over the path and query string (everything after ?) as is. http://example.com/about/?ref=1 is redirected to https://example.com/about/?ref=1.

The configuration files are usually in /etc/nginx/sites-available/ on Ubuntu and Debian (enabled by placing a link in sites-enabled/), and in /etc/nginx/conf.d/ on RHEL-based systems and nginx.org packages.

Do not put the redirect on the port 443 side

If you put return 301 https://... in the port 443 server block, or in a server block that listens on both 80 and 443, HTTPS requests are redirected to HTTPS again and the redirects never end (the browser says the page redirected you too many times). Put the redirect only in a server block that listens on port 80.

Apply the configuration

sudo nginx -t
sudo systemctl reload nginx

Run reload only after nginx -t prints test is successful.

Test the redirect

Browsers remember 301 redirects, so when testing the configuration, check with curl, which is not affected by what the browser remembers.

curl -I "http://example.com/about/?ref=1"

It works if you see 301 and Location shows the same URL on https://, like this (only the relevant lines are shown):

HTTP/1.1 301 Moved Permanently
Location: https://example.com/about/?ref=1

Check both with and without www, and both the home page and a deeper page.

While you are not sure about the configuration, you can test with return 302 (a temporary redirect) and change it to 301 after confirming it works. A 301 stays in browsers for a long time, so if you publish a mistake, visitors' browsers may keep going to the old destination even after you fix it.

Settings on the WordPress side

The Nginx redirect alone may leave the links and image URLs that WordPress outputs as http://. Fix these two things as well:

  1. In the admin screen, go to Settings → General (設定 → 一般 in the Japanese UI) and change "WordPress Address (URL)" and "Site Address (URL)" to https://
  2. Replace http:// URLs in post content and elsewhere with https:// (use something like WP-CLI's wp search-replace, and back up the database before running it)

For details, see "Serving WordPress over HTTPS at all times".

If it does not work

  • The redirect loops: If Cloudflare's SSL/TLS setting is "Flexible", Cloudflare connects to your server over HTTP, so Nginx keeps redirecting to HTTPS. Fixes such as switching Cloudflare to "Full (strict)" are explained in "Causes and fixes for too many redirects".
  • No redirect happens: Use sudo nginx -T | grep -n "listen 80" to check whether another server block also listens on port 80. A different server block (for example default on Ubuntu) may be the one responding.

Summary

  • Write return 301 https://$host$request_uri; in the port 80 server block
  • Do not put the redirect in the port 443 server block (it loops)
  • Apply with sudo systemctl reload nginx after sudo nginx -t, and check 301 and Location with curl -I
  • Also change the URLs under Settings → General in WordPress to https://

More advanced settings, such as choosing between www and non-www, protecting against invalid host names, and HSTS, are covered in "Recommended settings for HTTPS redirects in Nginx".

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲