Skip to content

How to Redirect HTTP to HTTPS in Nginx

DodaTech 2 min read

In this tutorial, you'll learn about How to Redirect HTTP to HTTPS in Nginx. We cover key concepts, practical examples, and best practices.

The Problem

Your Nginx server listens on both port 80 (HTTP) and 443 (HTTPS), but visitors who use http:// still connect over an unencrypted connection. You need to redirect all HTTP traffic to HTTPS.

Quick Fix

Step 1: Basic HTTP to HTTPS redirect

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

server {
    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;
}

The return 301 sends a permanent redirect. $server_name preserves the hostname, and $request_uri preserves the full path and query string.

Step 2: Redirect with HSTS header

server {
    listen 443 ssl;
    server_name example.com;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}

HSTS tells browsers to always use HTTPS for your domain, preventing future HTTP requests before they are made.

Step 3: Redirect all domain variants

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

The default_server and server_name _ catch any request that does not match another server block. This covers all domain names pointing to this server.

Step 4: Redirect without breaking ACME challenges

server {
    listen 80;
    server_name example.com;
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}

Certbot needs port 80 accessible for the ACME HTTP-01 challenge. This block redirects everything except the challenge path.

Step 5: Test the redirect

curl -I http://example.com

Expected:

HTTP/1.1 301 Moved Permanently
Location: https://example.com/

Step 6: Apply the configuration

sudo nginx -t
sudo systemctl reload nginx

Alternative Solutions

Use rewrite instead of return:

server {
    listen 80;
    server_name example.com;
    rewrite ^ https://$server_name$request_uri permanent;
}

return is slightly faster because it avoids regex processing.

Common Errors

Redirect not working: If return 301 does not redirect, ensure the listen 80 block exists and the server is reloaded: sudo nginx -t && sudo systemctl reload nginx.

HSTS blocking HTTP site: Once HSTS is set, browsers refuse to connect over HTTP even if you remove the redirect. Clear HSTS in the browser at chrome://net-internals/#hsts.

Certbot renewal failure: The ACME challenge on port 80 must remain accessible. Ensure the location /.well-known/acme-challenge/ block is not redirected.

Mixed content warnings: HTTPS pages loading HTTP assets (images, scripts) show mixed content warnings. Update all asset URLs to use HTTPS or protocol-relative URLs (//example.com/file.js).

Test Configuration Changes First

sudo nginx -t
# nginx: the configuration file syntax is ok
# nginx: configuration file test is successful
sudo systemctl reload nginx

Always run nginx -t before reloading the configuration. This validates syntax, checks file paths, and verifies that SSL certificates are accessible before applying changes.

Prevention

  • Always redirect from port 80 — do not accidentally leave HTTP serving content.
  • Combine HSTS with the redirect to enforce HTTPS at the browser level.
  • Test with curl -I after every config change.
  • Keep ACME challenge paths accessible on port 80 for certificate renewal.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro