What is the Difference between $host and $http_host Nginx Variables?

Published July 5, 2024

Problem: Understanding Nginx Variables $host vs $http_host

When using Nginx, you may see two variables that look similar: $host and $http_host. These variables have different uses and can act differently based on the situation. Knowing how they differ is important for setting up servers and handling requests in Nginx correctly.

What Are $host and $http_host in Nginx?

$host Variable in Nginx

The $host variable in Nginx represents the server name for the request being processed. Nginx sets the value of $host using this order:

  1. The host name from the request line
  2. The host name from the "Host" request header field
  3. The server name matching the request

If none of these sources provide a valid host name, Nginx uses an empty string as the value for $host.

$http_host Variable in Nginx

The $http_host variable matches the "Host" header field in the HTTP request. This header is sent by the client (usually a web browser) and contains the domain name of the server.

Unlike $host, $http_host does not go through Nginx's processing. It reflects the exact value of the "Host" header as received in the HTTP request. If the "Host" header is absent from the request, $http_host will be an empty string.

Key Differences Between $host and $http_host

Order of Precedence

Nginx sets the value of $host in a specific order. It first checks the host name in the request line. If not available, it looks at the "Host" header field. If both are absent, it uses the server name that matches the request. This order helps Nginx handle different types of requests.

$http_host is used when the "Host" header is in the HTTP request. If the header is missing, $http_host remains empty. Unlike $host, $http_host doesn't have a backup option and directly reflects the client's request.

Behavior with Server Names and Hostnames

The $host variable works with the server_name directive in Nginx. When a request comes in, Nginx matches it against the server_name values in its configuration. If it finds a match, that value becomes part of the $host variable. This allows for different server block configurations based on domain names.

$http_host is linked to the request header fields. It mirrors the "Host" header sent by the client. This makes $http_host useful for logging the exact hostname the client used to access the server, which might be different from the server name Nginx uses internally.

Using $host and $http_host in Nginx Configuration

$host in Nginx Server Blocks

The $host variable is useful in Nginx server blocks with server_name directives. Here's an example:

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

    location / {
        root /var/www/$host;
    }
}

This configuration uses $host for flexible document root paths. For requests to "example.com", Nginx serves files from "/var/www/example.com". For "www.example.com", it uses "/var/www/www.example.com".

This approach:

  • Handles multiple domains in one server block
  • Simplifies configuration for sites with similar structures
  • Makes adding new domains easier

$http_host for Logging and Redirects

$http_host is useful for logging and redirects. Here's how to use it in access logs:

log_format custom '$remote_addr - $remote_user [$time_local] '
                  '"$request" $status $body_bytes_sent '
                  '"$http_referer" "$http_user_agent" "$http_host"';

access_log /var/log/nginx/access.log custom;

This configuration adds $http_host to your access logs, showing the hostname clients use to access your server.

For redirects, $http_host helps maintain the original hostname:

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

    if ($http_host = "www.example.com") {
        return 301 $scheme://example.com$request_uri;
    }
}

This setup redirects "www.example.com" to "example.com", keeping the original protocol ($scheme) and path ($request_uri). Using $http_host maintains the exact hostname from the client's request, which is important for accurate redirects.