Redirect HTTP to HTTPS while preserving subdomains in Nginx

Keep the requested host, path, and query string while handling named virtual hosts, certificates, and redirect methods correctly.

Best practices
Illustration of server operations and request logs

For a known domain family, redirect to https://$host$request_uri. The host retains the requested subdomain, and the request URI retains the path and query string.

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

A request to http://api.example.com/items?page=2 therefore redirects to https://api.example.com/items?page=2. This assumes HTTPS is available on the standard port; include the intended port explicitly if it is not.

Account for other named HTTP servers

A default server handles unmatched names. It does not override another block whose server_name matches the request. This fallback, for example, rejects unknown hosts:

server {
    listen 80 default_server;
    server_name _;
    return 444;
}

Keep only one default for the same listening address and port. If existing named HTTP blocks already handle your domains, add the redirect to those blocks or consolidate them. Naming a file 00-redirect.conf does not make it intercept all named virtual hosts. _ is an ordinary placeholder name, not a wildcard operator.

Restrict redirects to domains you intend to serve rather than reflecting arbitrary unrecognized hostnames. Add corresponding IPv6 listeners if the deployment serves IPv6.

Prepare the HTTPS endpoints first

Each subdomain needs the appropriate HTTPS routing and a certificate valid for that hostname. For example, in the API server's existing HTTPS configuration:

listen 443 ssl;
server_name api.example.com;
ssl_certificate     /etc/nginx/ssl/example.com-wildcard.crt;
ssl_certificate_key /etc/nginx/ssl/example.com-wildcard.key;

A typical *.example.com certificate covers api.example.com, but not the apex example.com or a deeper name such as v1.api.example.com. Nginx's wildcard server_name matching is broader than that certificate rule. Ensure the certificate covers every hostname the redirect accepts.

Test the first response and final HTTPS page separately. Guance HTTP synthetic tests can check the endpoints after configuration, with redirect-following behavior chosen for the assertion you need.

Add HSTS only after HTTPS works

On the HTTPS server:

add_header Strict-Transport-Security "max-age=31536000" always;

This example asks browsers to remember HTTPS for a year. Start with a shorter lifetime during rollout. Do not add includeSubDomains until all affected subdomains support HTTPS. Recovery requires a valid HTTPS response with an updated policy; clients that cannot reach it may retain the earlier policy until expiry.

FAQ

Why use $host rather than $server_name?

$host comes from the request's host information, with a configured-name fallback. $server_name identifies the configured server name, so it may not represent the particular subdomain requested. $host is not a byte-for-byte copy of the raw Host header and normally does not include its port.

Will a 301 preserve a POST body?

Some clients change POST to GET after 301/302. Prefer HTTPS directly for forms and APIs. When method preservation is required, consider 307 for a temporary redirect or 308 for a permanent one and test the client behavior.

Must Certbot's generated redirect look exactly like this?

No. A host check followed by return can also be valid. Check which names and listeners it applies to before replacing generated configuration.

References: request routing, server names.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting