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 thanrewrite, which uses regular expressions, and easier to read.$host: The host name of the request. A request toexample.comgoes tohttps://example.com, and one towww.example.comgoes tohttps://www.example.com.$request_uri: Carries over the path and query string (everything after?) as is.http://example.com/about/?ref=1is redirected tohttps://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:
- In the admin screen, go to Settings → General (設定 → 一般 in the Japanese UI) and change "WordPress Address (URL)" and "Site Address (URL)" to
https:// - Replace
http://URLs in post content and elsewhere withhttps://(use something like WP-CLI'swp 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 exampledefaulton 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 nginxaftersudo nginx -t, and check301andLocationwithcurl -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)