Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › HTTP Redirects

Why a Subdomain Redirects to the Parent Domain in Nginx

By Freedom251 Team · · 10 min read

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

A subdomain reaches the parent domain when NGINX does not select the subdomain’s virtual server, or when NGINX or the application behind it deliberately returns a redirect to the parent hostname. The reliable fix is to trace the actual Location header, then make the subdomain explicit in every HTTP and HTTPS server block, remove misplaced canonical redirects, and correct any upstream application URL.

What is actually redirecting the browser?

Seeing https://example.com/ in the address bar does not by itself prove that NGINX created the redirect. Three components can be involved:

As an Amazon Associate I earn from qualifying purchases.

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.
  • NGINX virtual-server selection: NGINX chooses one server block for the address and port that received the request. If the subdomain does not match that block, a parent-domain or catch-all block may answer.
  • NGINX redirect rules: A return 301, return 302, or broad rewrite can send the request to a different hostname.
  • The upstream application: A proxied application can emit its own Location: https://example.com/... header because its canonical URL or proxy settings still identify the parent domain.

Find the emitter before changing configuration. Run both tests so HTTP and TLS are examined separately:

curl -I http://app.example.com/path
curl -Ik https://app.example.com/path

Read the status and the complete Location header. A 301 or 302 whose headers are produced before the request reaches your application usually points to NGINX. If the response contains an upstream-specific header and the parent-domain Location appears only after proxying, inspect the application’s canonical URL and proxy-awareness settings instead.

How NGINX chooses a server block

The server_name directive controls virtual-server matching. NGINX supports exact names, wildcard names, and regular-expression names, with a defined priority order; once the first matching variant is found, NGINX uses that server block for the request. A typo, a name declared on the wrong listener, or an overlapping wildcard can therefore make a valid-looking subdomain appear to be ignored.

The request’s Host header is matched independently for each address-and-port combination. If no name matches, NGINX uses that listener’s default server. The NGINX administration documentation describes this behavior as: “If the Host header field does not match a server name, NGINX Plus routes the request to the default server for the port on which the request arrived.” If the default happens to be your parent-domain site, every unmatched hostname will appear to redirect or serve the parent site.

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

The minimum HTTP destination block

For an HTTP subdomain, declare the exact hostname in the block that actually proxies or serves it:

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

    location / {
        proxy_pass http://app_backend;
    }
}

Do not rely on a parent declaration such as server_name example.com; to cover app.example.com. A bare parent name and its subdomains are different names. A wildcard such as *.example.com may match, but an exact declaration is easier to audit and prevents an unintended wildcard block from winning.

The separate HTTPS destination block

HTTPS uses a different listener and TLS handshake. Repeat the exact subdomain in the TLS block and use a certificate whose names cover it:

server {
    listen 443 ssl;
    server_name app.example.com;

    ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    location / {
        proxy_pass http://app_backend;
    }
}

A configuration that works at http://app.example.com can still fail at https://app.example.com if the 443 block omits the name, uses a different include file, or presents a certificate that does not cover the subdomain. The TLS listener may then select its own default server, which can contain a parent-domain redirect.

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

Why an unmatched subdomain lands on the parent domain

Each address/port pair has one default server. The first server for a listener is commonly the default unless another block is marked default_server. Administrators often create a parent-domain block or a catch-all block such as server_name _; and place canonicalization there. That is useful for unknown hosts, but it becomes the visible destination whenever the intended subdomain block is absent or mismatched.

Common matching failures include:

  • The subdomain is misspelled in server_name.
  • The name is present on port 80 but missing on port 443, or the reverse.
  • The configuration was edited in a file that is not loaded by the active NGINX instance.
  • A wildcard or regular-expression name catches the request in an unexpected block.
  • Two blocks declare the same name, leaving one declaration ineffective or producing a startup warning.
  • IPv4 and IPv6 use different listen directives, so one address reaches a different default server.

Inspect the merged configuration, not only the file you remember editing:

sudo nginx -T

Search the output for every relevant listen, server_name, default_server, return 301, return 302, and rewrite. Also inspect included snippets and distribution-provided files. The effective configuration is the one NGINX parsed, including all include directives.

Redirect directives that intentionally change the hostname

A misplaced return directive

The simplest hostname redirect is a return in a dedicated server block for the old hostname:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
server {
    listen 80;
    server_name old.example.com;
    return 301 https://example.com$request_uri;
}

This preserves the original path and query string through $request_uri. It is appropriate when old.example.com really should move to the parent domain. It is not appropriate in the block intended to serve app.example.com. If that return was copied into a shared include or placed in a catch-all block that also handles the subdomain, the browser will be sent to the parent by design.

NGINX’s rewrite-conversion guidance recommends the separate-server approach for a hostname redirect and calls the if-based alternative “wrong, cumbersome, and ineffective.” Keep simple host canonicalization in its own server block; do not use a broad conditional to decide which hostname should receive every request.

Broad or overlapping rewrites

A rewrite can alter the URI and, when a replacement contains a host, generate a hostname redirect. Server-context rewrites run once before NGINX selects a location. The last flag starts a new location search, while break stops rewrite processing in the current context. Multiple rules can therefore apply in sequence, send a request through a second location, or create a redirect cycle.

For a direct host change, prefer return because the destination is explicit and there is no pattern-matching side effect. If a rewrite is necessary, narrow its condition to the intended hostname and path, then test both the old and destination URLs with curl.

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

HTTP and HTTPS can make the symptom look inconsistent

HTTP and HTTPS are separate listener contexts. A request to http://app.example.com may match an exact port-80 block, while the HTTPS request is handled by a 443 default block. This explains the common pattern “the subdomain works on HTTP but redirects to the parent on HTTPS.” The reverse can happen when only the TLS block is configured.

Check all of the following for both listeners:

  • The exact server_name app.example.com; declaration.
  • The address family and port in each listen directive.
  • The certificate and private-key paths in the TLS block.
  • Any default_server marker and its redirect behavior.
  • Whether an included file adds a parent-domain return or wildcard name.

When testing TLS, curl -Ik shows headers while allowing a certificate verification failure to be observed rather than hiding the response. Once the certificate and name are correct, repeat the test without -k to verify normal client validation.

When the upstream application emits the parent URL

NGINX can select the correct subdomain block and still pass along a redirect generated by the application. Frameworks commonly build absolute URLs from a configured base URL, an environment variable, or proxy headers. If that setting remains https://example.com, a login redirect, trailing-slash redirect, or canonical URL response can send users away from the subdomain.

Use the first response from the proxy to distinguish this case. If NGINX’s access log shows the request reaching the upstream and the upstream response contains Location: https://example.com/..., correct the application’s canonical URL/base URL and its trusted proxy or forwarded-host configuration. Do not assume that adding another NGINX rewrite will solve an upstream-generated destination; it may hide the cause or create a loop.

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

If the upstream must remain unaware of the public hostname, an explicitly designed proxy redirect policy can translate its location headers. Apply that only after confirming the application’s behavior and documenting the intended public host. A blanket replacement can corrupt paths, ports, or unrelated redirects.

Absolute redirects and server_name_in_redirect

Some redirects are generated by NGINX itself rather than by an explicit return. For example, NGINX may add a trailing slash to a directory-style URI. The server_name_in_redirect directive controls whether absolute redirects use the primary server name from the selected server_name directive.

If the selected block lists the parent domain as its primary name, an absolute redirect can expose that name even when the request arrived through another hostname. Verify which block was selected and inspect the directive before changing it globally. Correct host matching is the first fix; changing redirect-name behavior globally can affect unrelated virtual servers.

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

A complete troubleshooting procedure

  1. Verify DNS and the endpoint. Confirm that the subdomain resolves to the intended server and that both HTTP and HTTPS reach the NGINX instance you are editing. A stale record or alternate load balancer can make a correct configuration appear ineffective.
  2. Capture the redirect. Run curl -I http://app.example.com/path and curl -Ik https://app.example.com/path. Record the status, exact Location, and other response headers.
  3. Dump the active configuration. Run sudo nginx -T. Locate every declaration for the subdomain, parent domain, wildcard, default_server, return, and rewrite on ports 80 and 443.
  4. Make matching explicit. Add the exact subdomain to the intended HTTP and TLS blocks. Ensure the blocks are loaded and that IPv4/IPv6 listeners are covered as intended.
  5. Separate canonical redirects. Keep a parent-domain redirect only in the server block for the hostname that should move. Remove it from the subdomain’s destination block and narrow any wildcard catch-all.
  6. Validate before reloading. Run sudo nginx -t. Only after a successful test, reload with sudo nginx -s reload.
  7. Check logs. Review access and error logs around a fresh request. Confirm which virtual server handled it, whether a proxy connection occurred, and whether the upstream supplied a Location header.
  8. Fix the application if necessary. Update its canonical URL/base URL and trusted forwarded-host or scheme settings when the upstream creates the parent-domain redirect.
  9. Retest without browser history. Test with curl or a clean private window. Browsers can cache permanent 301 responses, so an old redirect may persist after the server is fixed.

Choosing the right fix

Observed source Typical cause Corrective action Path and query handling
NGINX default server No exact match on the received address and port Add the subdomain to the correct listener and review the default block Preserved when the destination serves the request; a redirect preserves them only if its target includes $request_uri
NGINX return Parent-domain return in the subdomain block, shared include, or catch-all Move the return to a dedicated old-host block or remove it from the destination block $request_uri carries the original path and query string
NGINX rewrite Broad pattern, overlapping rules, or a second location search Replace a simple host redirect with return; otherwise narrow conditions and flags Depends on the replacement; test the exact resulting Location
Upstream application Canonical URL or proxy-header settings name the parent domain Correct application URL and trusted proxy configuration, or deliberately map upstream locations Depends on the application’s generated URL; verify path, query, scheme, and port
NGINX-generated absolute redirect Selected block’s primary name and server_name_in_redirect behavior Fix block selection and review the directive in the affected virtual server Usually keeps the URI, but verify the returned header

Configuration patterns that avoid accidental parent redirects

Serve a subdomain and redirect only the parent

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

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

    location / {
        proxy_pass http://app_backend;
    }
}

The first block has a deliberate policy for the parent hostname; the second has no host-changing return and can proxy the subdomain. In a real deployment, create equivalent 443 blocks with the appropriate certificate coverage and an explicit server_name app.example.com.

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

Use a catch-all safely

A catch-all can reject unknown hosts or send them to a chosen canonical site, but it should not accidentally include names that have a dedicated application. Keep server_name _; in its own default block, inspect its redirect, and test a deliberately unknown hostname as well as the production subdomain. This confirms that the catch-all is doing what you intended without stealing a valid name.

Common failed fixes

  • Editing only the parent block: A parent-domain declaration does not add the subdomain to the matching set.
  • Changing only port 80: The TLS listener can continue selecting its own default server.
  • Adding more rewrites: Additional rules can obscure whether NGINX or the upstream is responsible and may create loops.
  • Ignoring included files: nginx -T, not a single site file, shows the configuration NGINX actually loaded.
  • Testing only in a normal browser window: Cached 301 responses can make a fixed server look broken.
  • Assuming the visible hostname identifies the source: Inspect the original response headers and logs; an application can generate the same-looking redirect.

What the final verification should show

After the fix, an HTTP request should either reach the intended application or follow a deliberately documented HTTP-to-HTTPS policy while retaining app.example.com. The HTTPS request should select the subdomain’s TLS block, present a certificate covering that name, and return content or an intentional path redirect whose Location remains on the expected host. A request with an unknown hostname should follow the separate catch-all policy rather than proving that the subdomain still depends on it.

The key distinction is simple: a wrong server block is a matching problem; a parent-domain Location from a selected block is a redirect-rule problem; and a parent-domain Location from the proxied response is an application configuration problem. The status line, merged configuration, and logs tell you which one you have.

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.

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

HTTP RedirectsHTTPSNGINXreverse proxyserver_nameSubdomainsWeb server troubleshooting

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
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

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.