# Deep Dive into Nginx Variables

Nginx is a powerful web server and reverse proxy known for its high performance and flexibility. One of its key features is the use of **variables**, which allow dynamic behaviour and customization.

{% hint style="success" %}
For a complete list of variables, refer to the [official Nginx documentation](https://nginx.org/en/docs/varindex.html).
{% endhint %}

***

### 1. Understanding Nginx Variables

Nginx provides built-in and user-defined variables that can be used in configuration files for logging, redirection, proxying, and more.

#### **Types of Variables in Nginx:**

1. **Core Variables** – Built-in variables that provide request-specific information.
2. **HTTP Variables** – Variables related to HTTP headers and requests.
3. **Server Variables** – Variables related to the server and connection.
4. **Geo Variables** – Used for geo-based filtering and restrictions.
5. **SSL Variables** – Variables related to SSL connections.
6. **Upstream Variables** – Used in reverse proxying and load balancing.
7. **Custom Variables** – User-defined variables using `set`.

Let's explore these with practical examples.

***

### 2. Core Nginx Variables

These variables provide fundamental information about the request and response.

| Variable          | Description                                                                                                 |
| ----------------- | ----------------------------------------------------------------------------------------------------------- |
| `$remote_addr`    | Client's IP address                                                                                         |
| `$remote_port`    | Client's port                                                                                               |
| `$server_addr`    | Server IP address                                                                                           |
| `$server_port`    | Port on which the request was received.                                                                     |
| `$scheme`         | Request scheme (HTTP/HTTPS)                                                                                 |
| `$request_method` | HTTP method (GET, POST, etc.)                                                                               |
| `$request_uri`    | Full request URI                                                                                            |
| $uri              | It is the normalized URI after processing rewrite rules, ensuring backend systems receive a consistent URL. |

#### Example:

**Logging User IP Address and Request URI**

```nginx
log_format custom '$remote_addr - $remote_user [$time_local] "$request_method $request_uri"';
access_log /var/log/nginx/access.log custom;
```

This logs details such as IP, request method, and URI.

***

### 3. HTTP Request Variables

These variables store information about HTTP headers and request content.

| Variable           | Description                                                                                                                                                                 |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `$http_host`       | Host header sent by the client                                                                                                                                              |
| $host              | A processed version of the "Host" header. It’s typically the same as $http\_host, but if that is empty, Nginx falls back to the server name specified in the configuration. |
| `$http_user_agent` | User-Agent of the request                                                                                                                                                   |
| `$http_referer`    | Referer URL                                                                                                                                                                 |
| `$http_cookie`     | Cookies sent in the request                                                                                                                                                 |

#### Example:

**Redirecting Mobile Users Based on User-Agent**

```nginx
if ($http_user_agent ~* "mobile") {
    return 302 https://m.example.com;
}
```

This redirects mobile users to a mobile-specific website.

***

### 4. Server and Connection Variables

These provide details about the server and its connections.

| Variable               | Description                       |
| ---------------------- | --------------------------------- |
| `$server_protocol`     | Protocol used (HTTP/1.1, HTTP/2)  |
| `$connection`          | Connection number                 |
| `$connection_requests` | Number of requests per connection |

#### Example:

**Logging HTTP Protocol Version**

```nginx
log_format protocol_logs 'Client IP: $remote_addr, Protocol: $server_protocol';
access_log /var/log/nginx/protocol.log protocol_logs;
```

This logs the protocol version used by the client.

***

### 5. Geo Variables (Location-Based Handling)

These are useful for geo-restrictions and traffic management.

#### Example:

**Blocking Requests from Specific Countries**

```nginx
geo $country {
    default ZZ;
    include /etc/nginx/geoip.conf;
}

map $country $block_access {
    US 0;
    CN 1;
    RU 1;
}

server {
    if ($block_access = 1) {
        return 403;
    }
}
```

This blocks access from China and Russia using GeoIP.

***

### 6. SSL/TLS Variables

These variables provide information about SSL connections.

| Variable          | Description           |
| ----------------- | --------------------- |
| `$ssl_protocol`   | SSL/TLS protocol used |
| `$ssl_cipher`     | Cipher suite used     |
| `$ssl_session_id` | SSL session ID        |

#### Example:

**Logging SSL Protocol and Cipher**

```nginx
log_format ssl_logs 'Client IP: $remote_addr, SSL Protocol: $ssl_protocol, Cipher: $ssl_cipher';
access_log /var/log/nginx/ssl.log ssl_logs;
```

This logs the SSL protocol and cipher used for secure connections.

***

### 7. Upstream (Reverse Proxy) Variables

When using Nginx as a reverse proxy, these variables store information about backend responses.

| Variable                  | Description                |
| ------------------------- | -------------------------- |
| `$upstream_addr`          | Backend server address     |
| `$upstream_status`        | Response code from backend |
| `$upstream_response_time` | Response time from backend |

#### Example:

**Logging Backend Response Times**

```nginx
log_format upstream_logs '$remote_addr - Backend: $upstream_addr, Status: $upstream_status, Response Time: $upstream_response_time';
access_log /var/log/nginx/upstream.log upstream_logs;
```

This logs backend response times for performance monitoring.

***

### 8. Custom Variables (User-Defined Variables)

Custom variables in Nginx are a powerful way to store and manipulate dynamic values. We can define our own variables using `set` directive or even better, using the `map` directive for conditional logic. They can be defined in the server block, location block, or even within if-statements.

#### **Where to Create Custom Variables**

* **Server or Location Blocks:** Use the **`set`** directive to define a variable that is local to the block.
* **Maps:** For more complex conditions based on input values, the **`map`** directive allows you to define a variable whose value is determined by a set of key-value pairs.
* **If Statements:** Although using `if` comes with caveats in Nginx (especially for rewrite conditions), they can be used to set temporary variables.

#### Example:

**Setting a Custom Variable for Logging**

```nginx
set $my_variable "Custom Log Data";
log_format custom_logs '$remote_addr - $my_variable';
access_log /var/log/nginx/custom.log custom_logs;
```

This logs a custom message alongside client IP addresses.

#### **Example: Using set in a Location Block**

```nginx
server {
    listen 80;
    server_name example.com;

    location / {
        # Create a custom variable based on a condition
        set $custom_message "Default Message";
        if ($request_method = "POST") {
            set $custom_message "Received a POST Request";
        }

        # Use the custom variable in logging and header responses
        add_header X-Custom-Message "$custom_message";
        log_format custom_log 'Client: $remote_addr, Message: $custom_message';
        access_log /var/log/nginx/custom.log custom_log;

        proxy_pass http://backend;
    }
}
```

#### **Example: Using map for Conditional Variable Assignment**

```nginx
# Define a variable based on the value of the $host variable.
map $host $target_backend {
    default         "http://default_backend";
    "api.example.com" "http://api_backend";
    "shop.example.com" "http://shop_backend";
}

server {
    listen 80;
    server_name example.com;

    location / {
        # Forward requests to different backends based on $host
        proxy_pass $target_backend;
    }
}
```

In this configuration, the **map** directive examines the value of `$host` and assigns an appropriate backend. This is especially useful in multi-tenant or multi-service architectures where a single Nginx instance serves multiple domains or subdomains.

***

### 9. How Nginx Handles Variables

When a request comes into Nginx, it goes through several phases (such as rewrite, access, content, and logging). During these phases, variables are either computed on the fly or already preset by the server:

* **Evaluation on Request:** Many built-in variables (for example, `$host`, `$uri`, `$remote_addr`) are evaluated at runtime based on the incoming request.
* **Normalization and Rewrite:** Variables like `$uri` are normalized after any rewrite rules are applied. This means that if you change a URL using a rewrite rule, subsequent references to `$uri` will reflect the modified path.
* **Lazy Calculation:** Nginx optimizes performance by calculating variables only when needed. If a variable isn’t used in a particular configuration block, its value may never be computed.
* **Scope and Phases:** Custom variables (defined with the `set` directive or `map`) are usually evaluated during the rewrite phase and are available in later processing phases. Remember that these variables are request-scoped and reset with every new request.

### 10. Production Considerations for Using Variables

When deploying Nginx in production, it’s essential to consider the following points regarding variable usage:

* **Performance Impact:** Although variable evaluation is lightweight, excessive use in high-traffic environments (especially complex conditional logic) can add up. Always test performance impacts in a staging environment.
* **Logging Consistency:** Use normalized variables like `$host` and `$uri` to ensure consistency across logs, which is crucial for debugging and audit trails.
* **Security:** Variables like `$http_*` (e.g., `$http_user_agent`) can be manipulated by clients. Always sanitize or validate these when used in security-critical rules.
* **Configuration Maintenance:** Clearly document any custom variables and maps in your configuration. This makes troubleshooting easier and ensures that new team members understand the logic behind dynamic routing or logging.

### Conclusion

Nginx variables are incredibly powerful for managing requests, logging, security, and performance monitoring. By leveraging these variables effectively, you can build robust, production-ready configurations.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wisdom.gitbook.io/gyan/nginx/deep-dive-into-nginx-variables.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
