Use separate Nginx server blocks: a port-80 block that returns 301 to the same HTTPS path, and a TLS-enabled port-443 block that serves the site. In the HTTPS block, make missing resources end with =404; use error_page 404 /404.html; to display a custom page without changing the response to a redirect or a successful 200.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
The configuration below preserves the requested path and query string, supports a static site, and keeps the not-found status visible to browsers, crawlers and monitoring tools.
As an Amazon Associate I earn from qualifying purchases.
The request flow you want
A browser requesting http://example.com/docs/missing.html?lang=en should receive one permanent redirect:
- The port-80 Nginx server returns
301 Moved Permanentlywith aLocationheader pointing tohttps://example.com/docs/missing.html?lang=en. - The browser makes the HTTPS request.
- The TLS-enabled server checks the path. If the resource does not exist, Nginx returns
404 Not Foundand renders your custom error document.
The redirect and the 404 are separate decisions. The first response changes the transport scheme; it must not turn an absent resource into a success page. The second response describes whether the requested HTTPS resource exists.
#1 Best Overall
Why two server blocks are the clearest design
HTTP and HTTPS are different listeners with different requirements. The port-80 block only needs to receive insecure traffic and issue the permanent redirect. The port-443 block needs a TLS listener, a certificate, a private key, a document root or upstream application, and the routing rules that determine whether a request exists.
Keeping those jobs separate avoids several common errors:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minute- A redirect inside the HTTPS content location can interfere with application routing or create a redirect loop.
- A port-80 block cannot serve an HTTPS response until the browser reconnects over TLS.
- A redirect rule does not install or validate a certificate. The 443 server still needs working certificate and key paths.
- Not-found handling belongs in the HTTPS server that ultimately serves the content, not in the initial scheme redirect.
Prerequisites before editing Nginx
- A DNS record for the hostname or hostnames that should resolve to this server.
- A certificate whose names cover every HTTPS hostname you intend to serve, plus the matching private key.
- Readable certificate and key files. Protect the private key with filesystem permissions appropriate to your deployment.
- A document root containing your site and a real
404.htmlfile, or an application route that deliberately emits a 404. - Permission to validate and reload Nginx, commonly through the service manager used by your operating system.
Replace example.com, the certificate paths and /var/www/html with values from your installation. Do not copy a certificate path from an example unless that file actually exists on your server.
Step 1: Create the HTTP-to-HTTPS redirect block
Put this server block in the Nginx configuration that is loaded for your site:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
return 301 ends processing immediately and sends a permanent redirect. $request_uri contains the original path and query string, so a request such as /products?id=42 is redirected to the same path and query over HTTPS.
$host uses the host associated with the request. This is useful when the same block intentionally serves more than one hostname and you want to preserve whichever name was requested. If your site has one canonical hostname, use that fixed name instead:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
A fixed hostname is appropriate when, for example, www.example.com must always canonicalize to example.com. It also makes the redirect destination explicit. Whichever form you choose, list only hostnames that this server is meant to answer for.
Rank #2
Step 2: Configure the TLS-enabled HTTPS server
The HTTPS block must listen on 443 with SSL enabled and point to the certificate and private key:
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 root directive establishes the filesystem base for static files. The index directive identifies the default file for a directory request. Adjust both to match your site.
The try_files directive checks candidates in order:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, 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 minute$urichecks the requested path as a file.$uri/checks whether it is a directory, allowing the index handling to run.$uri.htmlsupports extensionless URLs backed by files such asabout.html.=404is the final action when none of those candidates exists.
That final parameter is essential. Without an explicit not-found result, another location, framework fallback or upstream application may generate a page with a successful status for an unknown URL.
Step 3: Add a custom 404 document without changing the status
Create an actual file at /var/www/html/404.html. It can contain your site navigation, a concise explanation and links to useful destinations. Keep it self-contained enough to render when the original resource is absent.
Then use:
error_page 404 /404.html;
location = /404.html {
internal;
}
The plain error_page 404 /404.html; form performs an internal redirect to the custom document while retaining the 404 semantics for the client response. The exact-match location serves the file only during Nginx’s internal error processing. The internal directive prevents a visitor from requesting the handler URI directly as a normal public endpoint.
Do not replace that line with:
error_page 404 =301 https://example.com/404.html;
The =301 form deliberately changes the client-visible result into a redirect. A browser may then show a 301 followed by a page that returns 200, and crawlers will no longer receive a direct 404 for the missing URL. Use the redirect form only when redirecting not-found requests is genuinely your intended behavior.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Step 4: Put the file in the active configuration and reload safely
The exact include directory differs by operating system and package, but the sequence is the same:
- Save the server blocks in a file that the main Nginx configuration includes.
- Check that the certificate, key, document root and
404.htmlpaths are correct. - Validate syntax before touching the running service:
sudo nginx -t
Proceed only when the test reports that the configuration syntax is successful and the configuration test is successful. If it reports an unknown directive, missing file or permission error, correct that problem first.
- Reload Nginx so existing connections can finish while workers adopt the new configuration:
sudo systemctl reload nginx
If your system does not use systemctl, use its Nginx service-management command instead. A reload cannot compensate for a certificate that is invalid, expired or issued for a different hostname; those TLS problems must be fixed separately.
How to verify both the redirect and the real 404
Test each stage independently. Using curl makes the status and headers visible without relying on browser UI:
Free tools Windows power users keep installed
One-click scans. No signup required.
Check the HTTP redirect
curl -I 'http://example.com/missing-page?ref=test'
Expect a single 301 response and a Location header containing the HTTPS scheme, the intended hostname, /missing-page and ref=test. If the path or query is missing, inspect the redirect expression and make sure it uses $request_uri.
Check the HTTPS missing resource
curl -i 'https://example.com/missing-page?ref=test'
The final response should have status 404 and the body of your custom page. It should not require a second redirect to the error document. A certificate warning during this test means the TLS setup is not ready for normal clients; resolve that before interpreting application routing results.
Check an existing file
curl -I 'https://example.com/index.html'
An existing file should return its normal successful status. This confirms that the 404 rule is not catching every request.
Rank #4
Inspect the complete redirect chain when needed
curl -IL 'http://example.com/missing-page?ref=test'
The chain should show the HTTP 301 followed by one HTTPS response with status 404. Additional 301 or 302 responses usually indicate canonical-host rules, application routing or proxy behavior that needs review.
Choosing 301, 302, 307 or 308
The permanent 301 in the standard pattern tells clients and caches that HTTP should no longer be used for this resource. It is the usual choice after HTTPS is configured and tested.
| Status | Typical use | Method behavior | What to consider |
|---|---|---|---|
| 301 | Permanent HTTP-to-HTTPS migration | Clients may rewrite non-GET methods according to their redirect handling | Widely supported and cacheable; clear old cached redirects when testing changes |
| 302 | Temporary redirect during a short-lived trial | Historically treated like a GET by many clients | Does not communicate a permanent canonical scheme |
| 307 | Temporary redirect when the request method and body must be preserved | Preserves the method | Useful for temporary testing of APIs or non-GET requests |
| 308 | Permanent redirect when method preservation is required | Preserves the method | Confirm that every client and intermediary in your audience handles it correctly |
For an ordinary website whose HTTP traffic is being permanently moved to HTTPS, 301 is the documented, broadly compatible choice. Select another status only for a specific temporary or method-preservation requirement.
Canonical host: $host or a fixed name
The redirect destination must also express your hostname policy. With https://$host$request_uri, a request for either name listed in server_name remains on that name. This is convenient for multi-host configurations, but it does not merge those names into one canonical URL.
With https://example.com$request_uri, every matching HTTP request goes to example.com. Use this when one hostname is canonical and the other is only an alias. If you need different canonical rules for different names, create separate server blocks rather than adding complicated conditionals to one redirect.
Whichever policy you choose, test both the bare and www forms, including a path with a query string. Canonicalization should happen predictably and should not add a second redirect after the scheme change.
Static sites versus application routing
Static files
The configuration shown above is designed for a static site. try_files checks the filesystem and ends with =404 when no candidate exists. The custom page is another static file below the configured root.
Front-controller applications
Many applications route every URL through one entry script. In that design, the Nginx location often uses a fallback such as try_files $uri $uri/ /index.php?$query_string; or proxies to an upstream. A fallback is not automatically wrong, but the application must decide whether the route exists and send a genuine 404 for an unknown route.
Do not assume that displaying a “not found” message is enough. A framework can render that message with status 200, which misleads crawlers, monitoring systems and clients. Verify the actual status with curl -i, and configure the application or upstream to emit 404 when it cannot resolve the requested resource.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Proxying to an upstream service
If the HTTPS server uses proxy_pass, decide where not-found behavior belongs. An upstream that returns 404 can normally pass that status through. If it returns a branded error page with 200, Nginx cannot infer that the content is missing; fix the upstream response or add a carefully scoped rule that handles the known absence condition.
Be cautious with proxy_intercept_errors and shared error pages. Intercepting an upstream error can be useful, but it must not accidentally convert the status. Test both an upstream 404 and an upstream 500 so that the custom 404 document is used only for not-found responses.
When a load balancer terminates TLS before Nginx
In some deployments, a load balancer, reverse proxy or ingress device accepts HTTPS from the client and forwards a request to Nginx over an internal connection. In that architecture, Nginx may receive an HTTP connection even though the original client used HTTPS.
Do not blindly place an HTTP-to-HTTPS redirect on every request that arrives at Nginx. That can create a loop: the edge redirects to HTTPS, the edge forwards internally over HTTP, and Nginx redirects again. Instead, configure the edge to provide its trusted forwarded-protocol signal and make Nginx honor it only from that trusted proxy network. The exact header name, address trust list and configuration depend on the proxy product and your network design.
Recommended Free Tools
If Nginx terminates TLS directly, the two-block configuration remains straightforward: clients reach port 80 for the redirect and port 443 for certificate validation and content delivery.
Common failure modes and fixes
Redirect loop
- Check whether a proxy already terminated TLS and whether Nginx knows the original scheme.
- Confirm that the port-443 server does not contain a blanket redirect back to HTTPS.
- Check the complete chain with
curl -ILand identify which hop repeats.
Certificate error after the redirect
- Confirm that the 443 block is loaded and that its
server_namematches the requested host. - Verify the certificate covers that host and that the key matches the certificate.
- Run
sudo nginx -tto catch unreadable or missing certificate files.
Missing URL returns 200
- Inspect
try_filesand ensure its final parameter is=404. - Look for a front-controller or proxy fallback that handles every path.
- Make the application emit 404 for an unresolved route and retest with
curl -i.
Custom page itself redirects
- Ensure
/404.htmlis a real file below the configuredroot. - Use the internal error-page form, not
=301or another external redirect. - Check that a broad location rule is not intercepting the exact
/404.htmllocation.
Query string disappears
- Use
$request_uriin the port-80 return directive. - Do not reconstruct the destination from only
$uriunless dropping the query string is intentional.
Direct request to the error URI behaves unexpectedly
The internal directive intentionally rejects an ordinary client request to /404.html. That is expected. Nginx can still use the file for its internal 404 processing.
A complete static-site example
This assembled configuration shows the two listeners and the custom error handler together:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$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;
}
}
After replacing the example values, validate with nginx -t, reload Nginx, and test an existing URL, an unknown HTTPS URL and the same unknown URL over HTTP. The expected sequence for the last test is one 301 followed by one 404.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Quick Recap
Operational checklist
- Port 80 has a dedicated server block with one permanent return rule.
- The redirect destination uses the intended canonical hostname.
$request_uripreserves the original path and query string.- Port 443 listens with TLS and points to a valid certificate and matching key.
- The HTTPS content location ends missing static files with
=404. - A real
404.htmlexists below the configured root. error_page 404 /404.html;is internal, not an external 301.- Applications and upstreams return 404 rather than a generated 200 for unknown routes.
- Proxy-terminated TLS uses a trusted forwarded-protocol signal to avoid loops.
nginx -tpasses before every reload, and both status codes have been checked withcurl.
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.




