Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
VGSOURCES
Get listed

404 errorsPATCH 2026.10.15

How to Redirect HTTP to HTTPS in Nginx and Return a Proper 404

By VGSources Team 9 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use one Nginx server block on port 80 to issue a permanent redirect, and a separate TLS-enabled block on port 443 to serve the site. In the HTTPS block, make try_files end with =404 and map errors with error_page 404 /404.html;. That combination preserves the requested path and query string, serves a custom not-found page internally, and leaves the client with an actual HTTP 404 instead of a second redirect or a misleading 200 response.

The canonical two-server-block configuration

Keep insecure traffic and secure content handling separate. The port-80 block should do nothing except redirect to HTTPS:

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
server {
    listen 80;
    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

$request_uri contains the original path and query string, so a request for http://example.com/assets/missing.css?v=4 is sent to https://example.com/assets/missing.css?v=4. The 301 status tells clients and caches that the move is permanent.

The destination needs its own TLS listener, certificate, key, content root, and not-found handling:

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

A redirect does not create TLS configuration. Until the 443 block has a valid certificate and private key, the browser cannot complete the HTTPS connection that the 301 advertises.

What happens to a missing URL

  1. The client requests an HTTP URL on port 80.
  2. Nginx returns 301 with a Location pointing to the HTTPS version of the same request URI.
  3. The client makes a new request to port 443.
  4. The TLS server block checks the requested path with try_files.
  5. If no listed file or directory exists, the final =404 parameter generates a not-found response.
  6. error_page 404 /404.html; internally selects the custom document while retaining the error response semantics.

The browser therefore receives the content of /404.html with status 404. It does not receive a second 301, and it does not receive a successful 200 merely because a friendly error document was rendered.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure the redirect safely

Use a dedicated port-80 block

Put the redirect in the server block that listens on port 80. Do not place it in the HTTPS content location. A redirect embedded in the secure location can interfere with normal routing and, in a misconfigured setup, send requests around in a loop.

List every hostname that should answer on port 80 in server_name. If one hostname is canonical, use a fixed destination instead of reflecting the request host:

server {
    listen 80;
    server_name example.com www.example.com;

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

The fixed-host form is appropriate when both names must converge on example.com. The $host form keeps the requested, configured hostname in the redirect and is useful when both names are intentionally valid public hosts. Choose deliberately; the redirect target determines your canonical-host policy.

Preserve the complete request URI

Use $request_uri, not only a literal slash. It carries the path and query string that the visitor requested. Omitting it sends every URL to the home page and can break deep links, asset requests, search results, and application parameters.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a status that matches the move

Status Typical use Method behavior Operational note
301 Permanent HTTP-to-HTTPS migration Clients may change a non-GET request to GET Can be cached aggressively; the pattern in this guide uses it.
302 Temporary redirect Historically may change method to GET Use only when the move is temporary.
307 Temporary redirect while preserving method Preserves the original method Useful for temporary changes involving POST or other non-GET requests.
308 Permanent redirect while preserving method Preserves the original method Use when a permanent move must retain method semantics and your clients support it.

A permanent 301 is the clearest general-purpose choice for a site-wide HTTP-to-HTTPS migration. If an API must preserve POST, PUT, or another method across the redirect, evaluate 307 or 308 instead of assuming every client will retain the method after a 301.

Make static routing return a real 404

How try_files evaluates paths

In try_files $uri $uri/ $uri.html =404;, Nginx checks the requested URI as a file, then as a directory, then with an .html suffix. The last parameter is the result when none of those candidates exists. Because that final parameter is =404, Nginx emits status 404 rather than passing the request to a success page.

This form suits a static site that supports extensionless links and optional directory indexes. If your site does not use extensionless HTML, you can simplify the list, but retain an explicit final 404 outcome for absent resources.

Place the custom document under the configured root

Create the file at /var/www/html/404.html when the server’s root is /var/www/html. The document can contain normal HTML, styles, and images that are available at paths that themselves resolve successfully. Keep the page useful without depending on a JavaScript application or a missing API endpoint; an error page should still render when the original route is broken.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Restrict direct access to the handler URI

The exact location block uses internal;:

location = /404.html {
    internal;
}

Nginx can enter this location through its internal error processing, but an external request for /404.html is not allowed to use it as a normal public endpoint. The exact-match location also prevents a broader location from accidentally applying different handling to the error document.

Preserve the 404 status during error rendering

The plain directive is the important distinction:

error_page 404 /404.html;

This performs an internal redirect to the specified URI while retaining the not-found result sent to the client. Nginx documents that this kind of internal redirect changes the client request method to GET for methods other than GET and HEAD; that behavior affects how the error document is fetched internally, not whether the original response is a 404.

Do not substitute an external redirect when the requirement is a genuine not-found response:

error_page 404 =301 https://example.com/404.html;

The =301 form intentionally changes the client-visible result to a redirect. A crawler, browser, or monitoring system then sees 301 and may follow it to a page that returns 200. That is a different design from serving a custom representation of a 404.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Application and proxy routing require a different check

Static files can be checked directly by Nginx. An application server or reverse proxy may instead receive every unknown path and generate a generic page with status 200. That is a “soft 404”: it looks like an error to a person but reports success to clients, search engines, caches, and monitoring tools.

For an application-backed location, make the upstream framework return 404 when the route or resource does not exist. If Nginx uses a fallback to an application entry point, verify that the application distinguishes an unknown route from its normal home page. Do not add a blanket success fallback merely to make navigation appear complete.

You can still use an Nginx error_page for the final 404, but the upstream must first emit the correct status. Test both an unknown route and a known route whose underlying record is absent; they may take different application paths but should each report the status your API or site contract specifies.

When TLS terminates before Nginx

Some deployments terminate TLS at a load balancer, reverse proxy, or edge service and forward traffic to Nginx over an internal connection. In that architecture, Nginx may see an ordinary HTTP connection even though the visitor used HTTPS.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure the edge to pass a trusted indication of the original protocol and configure Nginx to use that signal. The exact header name, rewrite rule, and trust boundary depend on the proxy product and network design; they are not interchangeable. Never treat an arbitrary client-supplied forwarding header as proof that a request was secure. The edge should overwrite or authenticate the signal, and Nginx should redirect only requests that the trusted architecture identifies as originally HTTP.

If Nginx redirects every internal HTTP hop without checking the trusted protocol signal, an already-secure visitor can be redirected repeatedly. Keep the port-80 redirect for direct HTTP traffic, and adapt it to the documented forwarded-protocol mechanism when TLS is terminated upstream.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Validate the configuration before reloading

Check syntax and certificates

  1. Confirm that the certificate and private-key paths in the 443 block exist and are readable by the Nginx worker process.
  2. Run nginx -t to test configuration syntax and referenced files.
  3. Only after a successful test, reload Nginx using your operating system’s service procedure or the Nginx reload signal. A reload applies the new configuration without needlessly stopping existing workers.

A syntax test does not prove that a certificate is trusted by every client or that an upstream application returns the intended status. Those require request-level checks.

Check the redirect and query string

curl -i "http://example.com/missing-page?source=test"

For the port-80 request, verify a 301 status and a Location whose HTTPS URL still contains /missing-page?source=test. If the path or query string disappears, inspect the return directive for a missing $request_uri.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check the final response without hiding redirects

curl -i "https://example.com/missing-page?source=test"
curl -iL "http://example.com/missing-page?source=test"

The direct HTTPS request should end with status 404 and the body of your custom page. The -L request should show the initial 301 followed by the final 404. A final 200 indicates an application fallback, an incorrect error_page target, or a custom page being served by a separate success location.

Troubleshooting common failure modes

The redirect loops

  • Check whether TLS is terminated at a proxy. Nginx may be redirecting an internal HTTP hop that originated as HTTPS.
  • Confirm that the port-80 redirect is not duplicated inside the 443 content location.
  • Inspect every proxy’s forwarded-protocol handling and trust configuration.

The browser reports a certificate error after the redirect

  • Verify that the 443 server block has listen 443 ssl;.
  • Check that the certificate covers the hostname in the redirect.
  • Check the configured certificate and private-key files and their permissions.

An unknown URL returns 200

  • Inspect try_files and ensure its final parameter is =404, not an application entry point that always succeeds.
  • For proxied applications, inspect the upstream response status for the unknown route.
  • Look for a broad fallback location that replaces an upstream 404 with a generated page.

The custom page redirects instead of returning 404

  • Search the configuration for error_page 404 =301, =302, or another explicit response code.
  • Use the internal form error_page 404 /404.html; when the client must receive 404.
  • Make sure /404.html is an actual file beneath the configured root and that its exact location is not being overridden.

The custom page itself is inaccessible

  • Confirm the file exists at the path produced by the server’s root.
  • Check read permissions for the Nginx worker.
  • Remember that internal; blocks direct browser access by design; test it through a missing resource rather than requesting /404.html directly.

Configuration decisions at a glance

Decision Recommended pattern When to choose another option
HTTP redirect location Dedicated listen 80 server block with return 301 Use a temporary status only for a genuinely temporary migration.
Redirect destination https://$host$request_uri when both listed hosts remain valid Use a fixed hostname when enforcing one canonical host.
Static missing-file handling try_files ... =404 Application routes need an upstream status-aware design.
Custom error document error_page 404 /404.html; plus an exact internal location Use an external redirect only when a redirect is explicitly desired.
TLS termination Certificate and key directly in the 443 Nginx block When a trusted edge terminates TLS, adapt to its forwarded-protocol signal.

Final implementation checklist

  • The port-80 block lists the intended hostnames and contains only the HTTP-to-HTTPS redirect.
  • The redirect preserves the original path and query string with $request_uri.
  • The 443 block has a TLS listener, certificate, private key, root, and normal content locations.
  • Static routing ends with =404 when no file, directory, or intended HTML variant exists.
  • The custom document exists under the configured root.
  • The error handler uses the internal form rather than =301 or another external status.
  • Unknown application routes return 404 from the upstream instead of a generated 200 page.
  • Proxy deployments use a trusted original-protocol signal and do not redirect already-secure requests.
  • Both direct HTTPS requests and followed HTTP redirects have been tested with headers visible.

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.

404 errorsHTTP redirectsHTTPSNGINXTLSWeb server configuration

Leave a reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.