In an nginx `location` block, what is the difference between the `root` and `alias` directives, and what filesystem path does `location /images/ { alias /data/pics; }` produce for a request to /images/logo.png?
answer
- one appends, one substitutes
- root keeps the whole request path
- alias drops the matched prefix
- trailing slashes must agree
- picslogo.png is the tell
basics
~20 sRoot appends the whole request path to its value; alias replaces the matched location prefix with its value. With alias /data/pics and location /images/, the request /images/logo.png becomes /data/picslogo.png, because the missing trailing slash concatenates the two.
solid answer
~40 s`root` and `alias` differ in what happens to the matched prefix. `root /data;` means "the document root is /data": nginx appends the **entire** request path, so `/images/logo.png` resolves to `/data/images/logo.png`. `alias /data/pics/;` means "this location *is* that directory": nginx strips the matched location prefix and appends only the remainder, so `/images/logo.png` resolves to `/data/pics/logo.png`. In the broken example the alias has no trailing slash while the location does, so nginx replaces `/images/` with `/data/pics` and glues the remainder straight on — `/data/picslogo.png`, a 404 on a file you can see with your own eyes. The rule is simple: with a prefix location, the location and the alias must both end in a slash or both not.
code
nginx · 14 lines# root: the full request path is appended
location /images/ {
root /data; # /images/logo.png -> /data/images/logo.png
}
# alias: the matched prefix is replaced
location /pics/ {
alias /data/images/; # /pics/logo.png -> /data/images/logo.png
}
# broken: slashes disagree
location /broken/ {
alias /data/images; # /broken/logo.png -> /data/imageslogo.png (404)
}go deeper
Be able to state the one-line difference out loud: root appends the whole request path, alias replaces the part the location matched. Give the resulting file path for a concrete example.
Explain the trailing-slash rule and compute the fused path /data/picslogo.png on the spot. Say that the error log prints the constructed open() path, which identifies the mistake instantly.
Show the production instinct: recognise that a location prefix without a trailing slash turns alias into a traversal, and describe how you would audit an estate's alias blocks for that pattern.
Take a position on convention. Argue for standardising on root plus a disk layout that mirrors URL prefixes, so the alias trailing-slash and traversal classes cannot occur, and say how you would enforce it in config review or linting.
## Two directives, two different mental models Both `root` and `alias` answer "where on disk does this URI live?", but they compose differently with the location that selected them. **`root` = document root.** Nginx takes the directive's value and appends the **full, normalized request path**: ```nginx location /images/ { root /data; # /images/logo.png -> /data/images/logo.png } ``` The `/images/` segment survives, because `root` knows nothing about which location matched. This is why `location /images/ { root /data/images; }` produces `/data/images/images/logo.png` and a puzzling 404 — a mistake made constantly by people who read `root` as "this directory". **`alias` = substitution.** Nginx removes the part of the path that the location matched and appends only what is left: ```nginx location /images/ { alias /data/pics/; # /images/logo.png -> /data/pics/logo.png } ``` Use `alias` when the URL path and the disk path genuinely differ; use `root` when the tail of the disk path repeats the URL prefix. ## The off-by-one that gives the leaf its reputation ```nginx location /images/ { alias /data/pics; # note: no trailing slash } ``` Substitution is textual. Nginx replaces the matched `/images/` with `/data/pics` and appends `logo.png`, yielding `/data/picslogo.png`. There is no error at startup, `nginx -t` passes, and the only symptom is a 404 for files that exist. The error log is the giveaway: it records the *constructed* path, so you see `open() "/data/picslogo.png" failed (2: No such file or directory)` and the bug names itself. The discipline: **the location prefix and the alias value must agree about the trailing slash.** Both with, or both without. ## The version of this bug that is a security problem Now drop the slash on the *location* side instead: ```nginx location /static { alias /var/www/static/; } ``` The prefix `/static` also matches a request for `/static../secrets/db.yml`. Nginx normalizes `.` and `..` only as whole path segments, and `static..` is not one, so the path survives normalization intact. Substitution then yields `/var/www/static/../secrets/db.yml`, which the kernel resolves to `/var/www/secrets/db.yml`. This is the well-known nginx alias traversal misconfiguration, and the fix is the same slash discipline: write `location /static/ { alias /var/www/static/; }`. ## Alias inside a regex location When the location is a regular expression, there is no fixed prefix to strip, so the alias value should be built from captures: ```nginx location ~ ^/users/(?<uid>\d+)/avatar$ { alias /data/avatars/$uid.png; } ``` Without a capture, an alias under a regex location is guesswork. ## Choosing between them - If the last segments of the disk path equal the URL prefix (`/images/` under `/data/images`), use `root /data;` — fewer moving parts and no slash trap. - If they differ (`/images/` served from `/data/pics/`), you need `alias`. - `root` may be set at `http`, `server` or `location` level and inherits downward; `alias` is meaningful only inside a `location`, because its whole definition is "replace what this location matched". ## Diagnosing it in ten seconds Never reason about the path in your head. Read `error_log` at `error` level — nginx prints the exact `open()` path it tried. A doubled segment (`/data/images/images/...`) means `root` where you meant `alias`; a fused segment (`/data/picslogo.png`) means a missing trailing slash on `alias`; a path climbing out of the tree means a missing trailing slash on the `location`.
- Why does `location /static { alias /var/www/static/; }` — with no slash on the location — turn into a path traversal?The prefix `/static` also matches `/static../secrets`. Nginx normalizes `..` only as a whole path segment, and `static..` is not one, so it survives. Substitution yields `/var/www/static/../secrets`, which the kernel resolves outside the intended tree. Writing `location /static/` with the trailing slash removes the match and the bug.
- When would you deliberately choose `root` over `alias` even though both can be made to work?Whenever the disk layout ends with the same segments as the URL prefix. `root` has no prefix-stripping step, so it has no trailing-slash trap and no traversal variant, and it inherits cleanly from `server` level. Reserve `alias` for the case it exists for: a URL prefix that genuinely maps to a differently named directory.
- How do you use `alias` inside a regular-expression location?There is no fixed prefix to strip, so the alias value must be constructed from the regex's captures — for example `location ~ ^/users/(?<uid>\d+)/avatar$ { alias /data/avatars/$uid.png; }`. Without a capture the alias is effectively a constant path and every request in that location resolves to the same file.
saying these in an interview costs you the question
- Says root and alias are interchangeable spellings
- Writes location /images/ with root /data/images
- Thinks the trailing slash on alias is cosmetic
- Believes nginx normalizes away static.. before matching
- Uses alias in a regex location with no capture