ERROR

How to Fix Nginx 400 Bad Request (Invalid Host)

Quick Fix Summary

TL;DR

Add your domain to the `server_name` directive in the Nginx server block or configure a default catch-all server.

Nginx returns a 400 Bad Request (Invalid Host) when the HTTP `Host` header in a client request does not match any configured `server_name` in your active server blocks. This is a security and routing feature to prevent request spoofing.

Diagnosis & Causes

  • Missing or incorrect `server_name` directive in Nginx config.
  • Request sent to server IP instead of domain name.
  • Proxy or CDN forwarding requests with wrong Host header.
  • DNS changes not propagated to client or load balancer.
  • Default server block not defined to catch unmatched hosts.
  • Recovery Steps

    1

    Step 1: Verify and Correct the server_name Directive

    Check your Nginx configuration and ensure the `server_name` directive includes all valid domains, IPs, or wildcards for the server block handling the request.

    bash
    sudo nginx -t
    sudo cat /etc/nginx/sites-available/your-site
    # Example config:
    server {
        listen 80;
        server_name example.com www.example.com 192.168.1.10;
        ...
    }
    2

    Step 2: Configure a Default Catch-All Server Block

    Create a default server block to handle requests with unknown Host headers, preventing the 400 error. This is crucial for environments like Kubernetes Ingress or dynamic proxies.

    nginx
    # First, define your primary server blocks.
    # Then, add this default block (usually first in config):
    server {
        listen 80 default_server;
        server_name _;
        return 444; # Silently drop connection, or proxy_pass to a default backend.
    }
    3

    Step 3: Inspect and Correct the Host Header from Upstream

    If behind a proxy (e.g., Cloudflare, HAProxy, Kubernetes Ingress), ensure it forwards the correct original `Host` header to Nginx. Test the raw request.

    bash
    curl -v -H "Host: your-correct-domain.com" http://your-server-ip/
    # In Nginx behind a proxy, often you need:
    location / {
        proxy_set_header Host $host;
        proxy_pass http://backend;
    }
    4

    Step 4: Apply Changes and Perform Final Validation

    Test the configuration syntax, reload Nginx, and verify the fix using curl with both correct and incorrect Host headers.

    bash
    sudo nginx -t
    sudo systemctl reload nginx
    # Test with correct host:
    curl -I -H "Host: example.com" http://localhost
    # Test with unknown host (should not return 400 if default_server is set):
    curl -I -H "Host: wrong.domain" http://localhost

    Architect's Pro Tip

    "In containerized environments, the 'invalid host' error often occurs because health checks from the orchestration layer (k8s, ECS) use the pod IP in the Host header. Always define a `default_server` block."

    Frequently Asked Questions

    Why do I get a 400 only sometimes, not always?

    This usually indicates a routing issue. Requests hitting the server directly via IP (or a load balancer health check) lack a matching Host header, while requests via your domain name work correctly.

    Is it safe to use a wildcard `server_name *.example.com;`?

    Yes, for subdomain routing. However, for security, avoid `server_name _;` in your primary block. Use it only in a dedicated `default_server` block with restrictive rules.

    Can this error be caused by the client or browser?

    Rarely. It's almost always a server-side configuration issue. However, misconfigured browser extensions or proxies can send malformed Host headers, triggering it.

    Related Nginx Guides