Redirect HTTP to HTTPS in Nginx

By 

Updated on

5 min read

Nginx configuration file showing HTTP to HTTPS redirect with a 301 return directive

Redirecting HTTP to HTTPS in Nginx is done by adding a dedicated server block that listens on port 80 and issues a 301 redirect to the HTTPS version of the site.

This guide explains how to configure the redirect for a single site and for all sites on a server.

You should avoid using the if directive for redirects, as it can cause unpredictable server behavior.

Redirect HTTP to HTTPS per Site

Typically when an SSL certificate is installed on a domain, you will have two server blocks for that domain. The first one for the HTTP version of the site on port 80, and the other for the HTTPS version on port 443.

To redirect a single website to HTTPS open the domain configuration file and make the following changes:

nginx
server {
    listen 80;
    server_name linuxize.com www.linuxize.com;
    return 301 https://linuxize.com$request_uri;
}

Here is what each line does:

  • listen 80 - The server block will listen for incoming connections on port 80 for the specified domain.
  • server_name linuxize.com www.linuxize.com - Specifies the server block’s domain names. Make sure you replace it with your domain name.
  • return 301 https://linuxize.com$request_uri - Redirect the traffic to the HTTPS version of the site. The $request_uri variable is the full original request URI, including the arguments.

Usually, you will also want to redirect the HTTPS www version of the site to the non-www or vice versa. The recommended way to do the redirect is to create a separate server block for both www and non-www versions.

For example, to redirect the HTTPS www requests to non-www, you would use the following configuration:

nginx
server {
    listen 80;
    server_name linuxize.com www.linuxize.com;
    return 301 https://linuxize.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.linuxize.com;

    # . . . other code

    return 301 https://linuxize.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name linuxize.com;

    # . . . other code
}

Whenever you make changes to the configuration files you need to restart or reload the Nginx service for changes to take effect:

Terminal
sudo systemctl reload nginx

Redirect All Sites to HTTPS

If all of the websites hosted on the server are configured to use HTTPS, and you do not want to create a separate HTTP server block for each site, you can create a single catch-all HTTP server block. This block will redirect all HTTP requests to the appropriate HTTPS blocks.

To create a single catch-all HTTP block which will redirect the visitors to the HTTPS version of the site, open the Nginx configuration file and make the following changes:

nginx
server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name _;
	return 301 https://$host$request_uri;
}

Here is what each directive does:

  • listen 80 default_server — Sets this server block as the default (catch-all) block for all unmatched domains.
  • server_name __ is an invalid domain name that never matches any real domain name.
  • return 301 https://$host$request_uri — Redirects the traffic to the corresponding HTTPS server block with status code 301 (Moved Permanently). The $host variable holds the domain name of the request.

For example, if the visitor opens http://example.com/page2 in the browser, Nginx will redirect the request to https://example.com/page2.

If possible, prefer creating a redirection on a per-domain basis instead of a global HTTP to HTTPS redirection.

Troubleshooting

Redirect loops after enabling HTTPS
This usually means the HTTPS server block is also matching port 80, or a proxy in front of Nginx is stripping the X-Forwarded-Proto header. Verify that the HTTP server block only listens on port 80, and the HTTPS block only on port 443.

301 redirect not taking effect after reload
Browsers cache 301 redirects aggressively. Clear the browser cache or test with curl -I http://yourdomain.com to confirm the redirect is in place at the server level.

nginx: configuration file test failed after editing
Run sudo nginx -t before reloading to validate the configuration syntax. Check for missing semicolons, unclosed braces, or typos in directive names.

HTTPS page not loading after redirect
Confirm that an SSL certificate is installed and the HTTPS server block is listening on port 443 with the ssl parameter. Check that the certificate paths in ssl_certificate and ssl_certificate_key are correct.

Quick Reference

ConfigurationDescription
return 301 https://example.com$request_uri;Redirect a single domain to HTTPS
return 301 https://$host$request_uri;Catch-all redirect for all domains
listen 80 default_server;Mark server block as the default catch-all
server_name _;Match any domain name
sudo nginx -tTest configuration syntax
sudo systemctl reload nginxApply configuration changes

FAQ

Should I use return 301 or rewrite for the redirect?
Use return 301. It is simpler, faster, and easier to read than a rewrite rule. The rewrite directive processes a regex on every request, while return exits the request processing immediately.

What is the difference between $host and $server_name in the redirect URL?
$host contains the domain name from the incoming request’s Host header. $server_name contains the first value from the server_name directive. Use $host in catch-all blocks so each domain redirects to its own HTTPS version. Use a hardcoded domain in per-site blocks to ensure the redirect always goes to the canonical domain.

Does a 301 redirect affect SEO?
A 301 (Moved Permanently) redirect passes link equity to the destination URL and is the correct choice for permanent HTTP-to-HTTPS migrations. Search engines update their index to the HTTPS version after crawling the redirect.

Why should I avoid using if for redirects in Nginx?
The if directive in Nginx does not behave like a standard conditional. It creates an implicit nested location context that can interact unexpectedly with other directives. For redirects, a separate server block with return 301 is always the correct and predictable approach.

Conclusion

The correct way to redirect HTTP to HTTPS in Nginx is with a dedicated port 80 server block that returns a 301 to the HTTPS URL. Use a hardcoded domain in per-site configurations and $host in catch-all blocks. After editing the configuration, always run sudo nginx -t before reloading.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page