iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
Use a dedicated port-80 server block for a permanent redirect, then let a separate TLS-enabled server block handle content and missing routes. The reliable pattern is return 301 https://$host$request_uri; on port 80, try_files ... =404 for static routing, and error_page 404 /404.html; for a custom page that still produces an HTTP 404.
The configuration pattern that solves both problems
HTTP-to-HTTPS redirection and not-found handling are separate jobs. Port 80 should do nothing except send the client to HTTPS. Port 443 should terminate TLS, locate the requested resource, and return either the resource or a genuine 404. Combining those responsibilities in one content location is a common cause of redirect loops, lost paths, and error pages that return status 200.
Recommended Free Tools
Create two server blocks. The first listens on port 80 and issues a permanent redirect. The second listens on 443 with SSL/TLS enabled and serves the site:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/example.crt;
ssl_certificate_key /etc/nginx/ssl/example.key;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ $uri.html =404;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
}
The redirect uses $request_uri, which carries the original path and query string. A request for http://example.com/docs/start?print=1 therefore becomes https://example.com/docs/start?print=1, rather than being reduced to the home page. The HTTPS block must have a usable certificate and private key; a redirect alone does not configure TLS.
#1 Best Overall
This is the same basic arrangement shown in the NGINX deployment documentation, which uses return 301 https://$server_name$request_uri;. Either variable can be appropriate, but they have different host-selection behavior, explained below.
Build the port-80 redirect server
Use a permanent redirect for a permanent policy
Put the redirect in the server block that listens on port 80:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
return stops request processing immediately, so NGINX does not attempt to find a file, invoke an application, or generate a fallback response on the insecure connection. The status 301 tells clients and caches that the move is permanent. During a short migration test, a temporary status such as 302 can avoid committing that result to caches; change to 301 once the destination and certificates are confirmed.
Preserve the complete request target
Do not replace $request_uri with a hard-coded slash unless every URL is intentionally being collapsed to the home page. $request_uri includes the path and query string as received by NGINX. It is the part of this pattern that keeps deep links, search parameters, and file names intact.
Keep insecure and secure processing separate
A redirect placed inside the HTTPS content location is not an HTTP-to-HTTPS redirect; the request has already reached TLS. Such rules can bounce an already-secure request, interfere with application routing, or create a loop when a proxy is involved. Keep the port-80 block dedicated to the upgrade and put site logic in the 443 block.
Rank #2
Configure the HTTPS server before testing the redirect
Supply a TLS listener, certificate, and key
The secure block needs listen 443 ssl;, a certificate path, and a matching private-key path. The example uses:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/example.crt;
ssl_certificate_key /etc/nginx/ssl/example.key;
Use paths that exist on the server and contain credentials for the names in server_name. If the certificate is absent, unreadable, expired, or does not cover the requested host, the browser can fail the HTTPS connection before NGINX has an opportunity to return a page. HTTP redirection cannot repair a broken TLS configuration.
Define the document root and index
For a static site, set the root and, if needed, the index file:
root /var/www/html;
index index.html;
NGINX resolves a URI against this root when it checks for a file or directory. Confirm that the NGINX worker can read the files and traverse each parent directory. A permissions problem can look like a missing resource, so check the error log when an expected file unexpectedly returns 404.
Make missing static resources return a real 404
Use try_files with =404
The static-content pattern is:
location / {
try_files $uri $uri/ $uri.html =404;
}
NGINX checks the candidates from left to right. First it tests the URI as a file, then as a directory, then as an HTML file with the same stem. If none exists, the final parameter, =404, ends processing with status 404. That final value is important: without an explicit error result, another fallback can turn an unknown URL into a generated page with a different status.
Free tools Windows power users keep installed
One-click scans. No signup required.
For example, a request for /guide can resolve to a real file, a directory index, or /guide.html. A request for /does-not-exist reaches =404 and remains not found. The rule is suitable for a static site whose URL convention allows the optional .html candidate; remove that candidate if extensionless mapping is not part of the site design.
Do not disguise an application fallback as success
Frameworks and reverse-proxy applications often have a catch-all route that renders a page for every path. If that route returns status 200 for an unknown resource, search engines, monitoring systems, and clients see a successful response even though the page is absent. Configure the application or upstream router to emit 404 for an unknown route. If NGINX itself determines that a static resource is absent, retain the explicit =404 result.
Render a custom page without changing the status
Use an internal error-page redirect
Add this to the HTTPS server:
error_page 404 /404.html;
location = /404.html {
internal;
}
error_page 404 /404.html; performs an internal redirect to the custom document while retaining the not-found response semantics. The client receives the custom content with status 404; the browser does not receive a second public redirect. NGINX’s core-module documentation notes that this internal redirect changes the client request method to GET for methods other than GET and HEAD, which is why an error document should be a safe, read-only resource.
Place the file under the configured root
With root /var/www/html;, create the actual file at /var/www/html/404.html. Keep its references to stylesheets, images, and scripts valid under the same HTTPS origin. A missing custom file can trigger another internal error and leave the client with an unhelpful default response, so verify the file exists and is readable.
Prevent direct access to the handler URI
The exact location and internal; directive allow NGINX to use /404.html during error processing but reject a normal external request to that URI. This keeps the handler from becoming a separately browsable page while preserving its use as the error representation. Do not remove internal; merely to make the page testable; test it through a missing URL instead.
Rank #4
Do not use an external 301 for the error document
This alternative has a different meaning:
error_page 404 =301 https://example.com/404.html;
The =301 form explicitly changes the client-visible result to a redirect. A client first receives 301 and then requests the error page, which is not a proper 404 response for the original missing URL. Use the plain internal form when the requirement is a custom page with a 404 status. Use an external redirect only when changing the URL and status is intentional.
Choose the right redirect and host behavior
| Decision | Recommended choice | What it means |
|---|---|---|
| Permanent HTTP-to-HTTPS migration | 301 |
Clients are told the move is permanent. |
| Temporary testing or staged migration | 302, or another temporary redirect selected for the client behavior you require |
Use while the destination is still being validated; change to a permanent status after testing. |
| Method-preserving permanent redirect | 308 |
Use only when preserving the request method across the permanent move is required and all clients support the intended behavior. |
| Method-preserving temporary redirect | 307 |
Use only when a temporary move must retain the method. |
| Host in the Location header | $host |
Builds the destination from the host selected for the request. |
| One fixed canonical hostname | A literal approved hostname | Always sends clients to that one host, which is useful when consolidating www and non-www names. |
The simplest two-name example accepts both example.com and www.example.com and preserves whichever host arrived in the request by using $host. That is not the same as canonicalization. If the site must always use one hostname, write that hostname explicitly in the redirect and create server-name coverage for the alternatives. Do not assume that listing two names automatically selects one canonical form.
The NGINX deployment example uses $server_name instead. That variable reflects the name selected by the server block, whereas $host reflects the request host after NGINX’s host-selection rules. Choose deliberately, especially when several names, aliases, or a fixed canonical domain are involved.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Account for TLS termination at a proxy or load balancer
Some deployments terminate TLS at a load balancer, CDN, or reverse proxy and forward traffic to NGINX over HTTP. In that architecture, NGINX may see an internal HTTP connection even though the visitor used HTTPS. A blanket port-80 redirect based only on the connection between the proxy and NGINX can redirect an already-secure visitor repeatedly.
Use the proxy’s trusted forwarded-protocol signal and configure the trust boundary so NGINX can distinguish an original HTTPS request from an original HTTP request. The exact header name, trusted proxy addresses, and configuration depend on the intermediary; there is no single header setup that is safe for every architecture. Never trust an arbitrary client-supplied forwarding header without restricting which proxy may set it.
When TLS terminates directly in NGINX, the two-block configuration above is sufficient: port 80 redirects, and port 443 serves the site. When TLS terminates upstream, document that decision and test both the edge response and the origin response so the redirect is enforced once, not at every hop.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Validate the configuration safely
Check syntax before reloading
- Save the server blocks in the enabled NGINX configuration location used by the distribution.
- Run
nginx -t. Resolve every reported syntax error, missing file, certificate path, or duplicate/conflicting server definition before proceeding. - Reload NGINX using the service manager for the host, for example
systemctl reload nginx, so existing connections are not unnecessarily dropped.
The exact configuration directory and service command vary by operating system, but the order does not: test first, then reload. A reload that fails validation leaves the previous working configuration in place; do not assume that editing a file changed the running process.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteTest the redirect and its URI preservation
Use a request that includes both a deep path and a query string:
curl -I 'http://example.com/docs/start?print=1'
Expect a 301 response with a Location value equivalent to https://example.com/docs/start?print=1. Check that the scheme changed, the path remained intact, and the query string was not dropped. Repeat the test for each hostname accepted by the port-80 server_name list.
Test an existing and a missing HTTPS resource
curl -s -o /dev/null -w '%{http_code}n' 'https://example.com/index.html'
curl -s -o /dev/null -w '%{http_code}n' 'https://example.com/does-not-exist'
The first request should return the status your site intends for an existing document. The second must return 404, not 200 and not 301. To inspect headers and confirm the custom body, use curl -i on the missing HTTPS URL. The response should contain the 404 status while displaying the contents of 404.html.
Check direct access to the error handler
curl -i 'https://example.com/404.html'
Because the location is marked internal, a direct client request should not be treated as a normal public document. Test the missing URL as the primary behavior; the handler URI itself is deliberately restricted.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallTest through the real edge path
If a proxy terminates TLS, run the same checks against the public hostname rather than only against the origin address. Confirm that an original HTTPS request does not receive another HTTPS redirect and that an original HTTP request receives exactly one upgrade. Inspect proxy and NGINX logs together when the observed status differs between edge and origin.
Troubleshoot common failures
The browser reports a redirect loop
- Check whether a redirect rule was added to the HTTPS content location instead of only to the port-80 server.
- If a load balancer terminates TLS, verify that NGINX receives and trusts the intermediary’s original-protocol signal.
- Look for multiple layers redirecting in opposite directions, such as an edge forcing one hostname while NGINX forces another.
The redirect loses the path or query string
- Confirm that the
returntarget ends with$request_uri. - Check for a second redirect generated by the application or proxy that replaces the original target.
- Compare the first response’s
Locationheader with the URL supplied tocurl, rather than relying only on a browser’s final address.
The missing URL returns 200
- Inspect the
location /rule for a catch-all application fallback. - Ensure the static rule ends with
=404when no candidate exists. - Configure the upstream application to return 404 for unknown routes instead of rendering its normal home page.
The missing URL returns 301
- Search for
error_page 404 =301or another explicit redirect attached to the 404 handler. - Replace it with
error_page 404 /404.html;when the original URL must remain a 404. - Check whether a separate canonical-host rule is redirecting the request before the error handler runs.
The custom page is not displayed
- Verify that
/var/www/html/404.htmlmatches the configured root and is readable by NGINX. - Confirm that the exact location is spelled
location = /404.htmland is inside the intended HTTPS server block. - Review the error log for a second missing file, permission denial, or a conflicting location that takes precedence.
HTTPS fails before any page appears
- Check the certificate and key paths in the 443 server block.
- Confirm that the certificate covers the hostname the redirect produces.
- Run
nginx -tand inspect startup or reload errors before debugging application routing.
Production checklist
- Port 80 has its own server block with
return 301(or a deliberately temporary status during testing). - The redirect target contains
$request_uriso paths and query strings survive. - Port 443 has a TLS listener, certificate, private key, server names, and the intended document root.
- Static routing uses
try_filesand ends in=404when no file or directory matches. - The custom file exists under the root and is served through
error_page 404 /404.html;. - The exact
/404.htmllocation is markedinternalwhen the handler should not be publicly browsable. - No
=301is attached to the 404 error page unless an external redirect is genuinely intended. - Application fallbacks return 404 for absent resources rather than a generated 200 page.
- If a proxy terminates TLS, only trusted forwarded-protocol information controls redirect decisions.
nginx -tpasses before reload, and both edge and origin behavior have been checked with a deep URL, query string, existing resource, and missing resource.
With those boundaries in place, the client sees one permanent upgrade from HTTP to HTTPS, the original request target remains intact, and an unknown HTTPS URL receives a custom response with the correct 404 status.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

