How to Force HTTPS Redirects in Nginx
Forcing HTTPS in nginx is a single directive in the port-80 server block: return 301 https://$host$request_uri;. It redirects every HTTP request to its HTTPS equivalent before any content is served. Here's the full config and why each part matters.
The nginx HTTPS redirect config
Replace the content-serving port-80 server block with a minimal redirect block:
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
That is the entire block. Nothing else belongs in a redirect-only server block - no
root, no location, no try_files. Keeping it minimal avoids accidentally serving
any content over HTTP before the redirect fires.
Why $host$request_uri and not a hardcoded domain
$hostpreserves the hostname from the incoming request, sohttp://example.com/pageredirects tohttps://example.com/pageandhttp://www.example.com/pageredirects tohttps://www.example.com/page- no hard-coding needed, works for every virtual host.$request_uricarries the full path plus query string (/page?id=5), so users land on the exact URL they requested rather than the root.
Apply the change safely
Always validate before reloading - a config error would drop traffic:
nginx -t # check syntax
nginx -s reload # graceful reload (keeps existing connections alive)
Then confirm the redirect is live:
curl -I http://localhost/
# HTTP/1.1 301 Moved Permanently
# Location: https://localhost/
A 301 (Permanent) in the response tells browsers to cache the redirect, so
subsequent visits go straight to HTTPS without hitting port 80 at all.
Add HSTS for belt-and-braces protection
A 301 redirect stops most passive eavesdropping, but the very first request still travels over HTTP. HTTP Strict Transport Security (HSTS) tells the browser never to attempt HTTP again for your domain:
server {
listen 443 ssl;
server_name example.com;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# ... rest of TLS config
}
Set max-age to at least one year (31536000 seconds). Only add preload once
you are confident the site will stay HTTPS-only - it is very hard to undo.
Production edge note
Many production stacks terminate TLS at a CDN or load balancer (Cloudflare, AWS ALB),
so the application server never sees raw HTTPS. The redirect logic moves to the edge
config (Cloudflare Page Rules, ALB listener rules), but the principle - bounce port 80
to 443 before serving anything - is identical. Nginx's return 301 pattern is the
right mental model wherever you configure it.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Replacing an HTTP server block with a 301 redirect to HTTPS
- Using
nginx -tto validate config beforenginx -s reload - Adding HSTS headers on the HTTPS server block to enforce the redirect at the browser level
FAQ
How do I redirect HTTP to HTTPS in nginx?
Add a server block that listens on port 80 and contains only return 301 https://$host$request_uri;. Remove any root/location directives from that block so nothing is served over HTTP. Then run nginx -t && nginx -s reload.
What is the difference between 301 and 302 for HTTPS redirects?
A 301 (Permanent) tells browsers to cache the redirect and go directly to HTTPS on future visits. A 302 (Temporary) is re-checked every time. Use 301 for HTTPS enforcement so browsers stop hitting port 80 entirely.
Why use `$host$request_uri` instead of a hardcoded URL in the nginx redirect?
$host preserves the incoming hostname so the redirect works for any virtual host without hard-coding a domain, and $request_uri carries the full path and query string so users land exactly where they intended.
How do you force HTTPS in nginx?
In the port-80 server block add: return 301 https://$host$request_uri; so every HTTP request redirects to HTTPS, and keep the real config in the port-443 block. Reload nginx and test with curl -I.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →