100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
DevOps

Nginx Variables

How Nginx's dollar-sign variables are lazily computed per request, the difference between commonly confused ones like $uri and $request_uri, and how map builds custom derived variables cleanly.

ConfigurationIntermediate8 min readJul 10, 2026
Analogies

What Nginx Variables Actually Are

Nginx variables, written with a leading dollar sign like $host or $remote_addr, are not general-purpose programming variables — they are lazily evaluated per-request values computed by Nginx core or loaded modules. A variable like $request_time doesn't hold a static value set once; it's recomputed fresh for every single request that references it, and referencing a variable that no module defines (a typo, essentially) causes Nginx to fail at configuration load time with an 'unknown variable' error rather than silently defaulting to an empty string.

🏏

Cricket analogy: It's like a scoreboard's 'current run rate' figure: it isn't a number typed in once, it's recalculated fresh every ball based on the live match state, and referencing a stat the scoring system doesn't track at all just breaks the display.

Commonly Used Built-in Variables

$host holds the request's Host header (falling back to the server_name if absent), $remote_addr is the client's IP address, $request_uri is the full original URI including query string, $args is just the query string, $uri is the normalized current URI (which changes after an internal rewrite), and $document_root reflects whatever root directive is active for the current location. Because $uri updates after a rewrite while $request_uri never does, mixing them up in logging or proxy headers is a frequent source of confusing debug data.

🏏

Cricket analogy: It's like the difference between a player's 'current form rating' that updates after every innings ($uri, updates after processing) versus their 'debut match record' that's permanently fixed and never changes ($request_uri, frozen at the original request).

Using map to Derive Custom Variables

The map directive, used in the http context, creates a new variable whose value is computed by matching another variable against a lookup table, for example mapping $http_user_agent to a boolean $is_bot flag, or mapping $http_origin to an allowed CORS header value. This is far more efficient and readable than chains of nested if statements, which Nginx documentation explicitly warns against using inside location blocks because if interacts unpredictably with other directives in that context.

🏏

Cricket analogy: It's like a lookup table mapping bowler names to their preferred field settings — instead of a coach shouting nested conditional instructions mid-over, the table is pre-defined and instantly applied.

nginx
http {
    map $http_user_agent $is_bot {
        default 0;
        "~*(bot|crawl|spider)" 1;
    }

    map $http_origin $cors_origin {
        default "";
        "https://app.example.com" $http_origin;
        "https://admin.example.com" $http_origin;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            if ($is_bot) {
                return 403;
            }
            add_header Access-Control-Allow-Origin $cors_origin always;
            proxy_pass http://backend;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Original-URI $request_uri;
        }
    }
}

Use map in the http context to precompute derived variables once per request efficiently, instead of scattering nested if blocks across location contexts — the official Nginx documentation calls if inside location blocks 'evil' precisely because of how unpredictably it interacts with other directives.

Referencing an undefined variable, such as a typo like $remote_addrr, is a hard configuration error — Nginx refuses to start rather than silently treating it as empty. Always run nginx -t immediately after introducing a new variable reference to catch typos before reloading a production instance.

  • Nginx variables are lazily evaluated per-request, not static values assigned once at config load time.
  • $host is the effective hostname, $remote_addr is the client IP, $request_uri is the full original URI plus query string.
  • $uri reflects the current, possibly-rewritten URI, while $request_uri always stays frozen as the original.
  • $args holds just the query string; $document_root reflects the active root directive for the current location.
  • map computes a new variable from a lookup table in the http context, far cleaner than nested if statements.
  • Nginx's own docs warn that if inside a location block behaves unpredictably and should be avoided when possible.
  • Referencing an undefined variable is a hard startup error, not a silent empty-string fallback.

Practice what you learned

Was this page helpful?

Topics covered

#DevOps#NginxStudyNotes#NginxVariables#Nginx#Variables#Actually#Commonly#StudyNotes#SkillVeris#ExamPrep