The confusion between NGINX alias and root directives has caused more broken configurations than almost any other NGINX concept. If you have ever spent hours debugging why your static files return 404 errors, or wondered why your perfectly valid-looking configuration does not work, you are not alone.
In this guide, you will learn exactly how NGINX alias vs root differs at the implementation level. We will examine how NGINX constructs file paths internally, when to use each directive, and the critical trailing slash rules that trip up even experienced administrators. Every configuration in this article has been tested on Rocky Linux 10 with NGINX 1.26.
How NGINX Constructs File Paths
Before we can understand the difference between alias and root, we need to understand how NGINX maps a URL to a file on disk. This path construction happens in the ngx_http_map_uri_to_path() function deep in NGINXβs core module.
When a request comes in, NGINX must translate the requested URI into an actual filesystem path. According to the official NGINX documentation, the path construction formula differs between root and alias:
With root:
filesystem_path = root + full_URI
With alias:
filesystem_path = alias + (URI - location_match)
This fundamental difference is the source of all the confusion around NGINX alias vs root. Let us see it in action.
The root Directive: Appending the Full URI
The root directive specifies a base directory, and NGINX appends the entire request URI to it. This is the simpler of the two directives and should be your default choice when choosing between NGINX alias vs root.
server {
listen 80;
server_name example.com;
location /images {
root /var/www/html;
}
}
When a request comes in for /images/logo.png, NGINX constructs the path as:
/var/www/html + /images/logo.png = /var/www/html/images/logo.png
The full URI /images/logo.png is appended to the root path. This means your directory structure must include the /images folder inside /var/www/html.
root Directive Placement
The root directive can be placed in the http, server, or location context. It is commonly placed at the server level and inherited by all locations:
server {
listen 80;
root /var/www/html;
location /images {
# Inherits root /var/www/html
# /images/logo.png -> /var/www/html/images/logo.png
}
location /css {
# Inherits root /var/www/html
# /css/style.css -> /var/www/html/css/style.css
}
location /uploads {
# Override root for this location
root /var/www/uploads;
# /uploads/file.pdf -> /var/www/uploads/uploads/file.pdf
}
}
Notice the last location block: when you override root in a location, the location path is still appended. This catches many administrators by surprise.
The alias Directive: Replacing the Location Match
The alias directive replaces the matched location portion of the URI with the specified path. This is the key difference in the NGINX alias vs root comparison.
server {
listen 80;
server_name example.com;
location /images {
alias /var/www/static/images;
}
}
When a request comes in for /images/logo.png, NGINX constructs the path as:
/var/www/static/images + /logo.png = /var/www/static/images/logo.png
NGINX removes /images from the URI and appends only the remaining /logo.png to the alias path. The location match is replaced, not appended.
When to Use alias
Use alias when:
- You want to serve files from a directory that does not match the URL path
- You are mapping a URL prefix to a completely different location on disk
- You need to serve static files from outside your main document root
# Serve files from /srv/downloads when requesting /files/
location /files/ {
alias /srv/downloads/;
}
# Serve static assets from a CDN directory
location /static/ {
alias /var/cache/cdn/assets/;
}
# Serve user uploads from a separate partition
location /uploads/ {
alias /mnt/storage/user-uploads/;
}
alias Restrictions
The alias directive has more restrictions than root:
- Cannot be used in named locations: Named locations (those starting with
@) cannot usealias - Cannot be used with certain rewrites: If the URI is modified by a rewrite,
aliasmay produce unexpected results - Only valid in location context: Unlike
root,aliascannot be placed inhttporserverblocks
The Critical Trailing Slash Rule
The trailing slash is where most NGINX alias vs root confusion originates. Getting this wrong results in 404 errors that can take hours to debug.
The Rule for alias
When using alias, the trailing slashes must match between the location and the alias path:
Correct:
location /files/ {
alias /srv/downloads/;
}
Correct:
location /files {
alias /srv/downloads;
}
Wrong β will break:
location /files/ {
alias /srv/downloads; # Missing trailing slash
}
Let us see why the wrong configuration breaks. With location /files/ and alias /srv/downloads (no trailing slash):
- Request:
/files/report.pdf - Location match:
/files/ - Remaining URI:
report.pdf(note: no leading slash) - Path construction:
/srv/downloads+report.pdf=/srv/downloadsreport.pdf
The missing slash causes the path to be concatenated without a separator, resulting in a nonexistent path.
Why root Does Not Have This Problem
With root, the full URI is always appended, so the slash situation is consistent:
location /files {
root /srv;
}
# /files/report.pdf -> /srv/files/report.pdf (correct)
location /files/ {
root /srv;
}
# /files/report.pdf -> /srv/files/report.pdf (correct)
The URI always starts with a slash, so it naturally separates from the root path.
Practical Advice
To avoid trailing slash problems with alias, always follow this pattern:
location /prefix/ {
alias /path/to/directory/;
}
Both the location and the alias end with slashes. This is the safest and most readable approach.
NGINX alias vs root with try_files
The try_files directive behaves differently with alias and root, and understanding this interaction is crucial for serving static files with fallbacks.
try_files with root
server {
listen 80;
root /var/www/html;
location /assets/ {
try_files $uri $uri/ =404;
}
}
When requesting /assets/style.css:
- NGINX constructs:
/var/www/html/assets/style.css - If not found, tries:
/var/www/html/assets/style.css/ - If not found, returns 404
This works as expected because root appends the full URI.
try_files with alias
server {
listen 80;
location /assets/ {
alias /srv/static-files/;
try_files $uri $uri/ =404;
}
}
When requesting /assets/style.css:
- NGINX constructs:
/srv/static-files/style.css - If not found, tries:
/srv/static-files/style.css/ - If not found, returns 404
The key difference is that with alias, try_files correctly uses the aliased path. The /assets/ prefix is stripped when constructing the filesystem path.
Common try_files Mistake
A frequent mistake is using alias when you should use root:
# Wrong: trying to serve /assets/* from /var/www/html/assets/
location /assets/ {
alias /var/www/html/assets/;
try_files $uri $uri/ =404;
}
# Better: use root when the directory structure matches
location /assets/ {
root /var/www/html;
try_files $uri $uri/ =404;
}
When the URL path matches the filesystem structure, prefer root for simplicity.
Using alias with Regex Locations
When using alias inside a regex location, you must use capture groups. NGINX requires this to know which part of the URI to replace.
Incorrect (will cause errors)
location ~ ^/images/ {
alias /srv/static/images/; # Does not work correctly with regex
}
Correct (using capture groups)
location ~ ^/users/(\d+)/avatar\.jpg$ {
alias /srv/avatars/$1.jpg;
}
In this example:
β Request: /users/123/avatar.jpg
β Capture group $1: 123
β Resolved path: /srv/avatars/123.jpg
The regex captures the user ID, and alias uses it to construct the correct path.
Multiple Capture Groups
location ~ ^/galleries/([a-z]+)/(\d+)\.jpg$ {
alias /srv/images/$1/photo_$2.jpg;
}
- Request:
/galleries/summer/42.jpg $1:summer$2:42- Resolved path:
/srv/images/summer/photo_42.jpg
Directory Auto-Redirect Behavior
When a request matches a directory without a trailing slash, NGINX can automatically redirect to add the slash. This behavior differs slightly between root and alias.
With root
location /docs {
root /var/www;
index index.html;
}
Request to /docs (without trailing slash):
1. NGINX finds /var/www/docs is a directory
2. Returns 301 redirect to /docs/
3. New request to /docs/ serves /var/www/docs/index.html
With alias
location /documentation/ {
alias /var/www/docs/;
index index.html;
}
Request to /documentation (without trailing slash):
1. Does not match location /documentation/
2. Falls through to another location or returns 404
To handle both with and without trailing slash:
location /documentation {
alias /var/www/docs;
index index.html;
}
location /documentation/ {
alias /var/www/docs/;
index index.html;
}
Or use a rewrite:
location /documentation {
rewrite ^/documentation$ /documentation/ permanent;
}
location /documentation/ {
alias /var/www/docs/;
index index.html;
}
NGINX alias vs root: Quick Reference
| Aspect | root | alias |
|---|---|---|
| Path formula | root + full_URI | alias + (URI β location) |
| Valid contexts | http, server, location | location only |
| Trailing slash | Not critical | Must match location |
| Regex locations | Works without changes | Requires capture groups |
| Named locations | Supported | Not supported |
| With try_files | Straightforward | Works, but be careful |
| Default choice | Yes | Only when needed |
When to Use root vs alias
Use root when:
- The URL path matches your directory structure
- You want a simple, maintainable configuration
- You are setting a base path at the server level
- You need to use named locations
Use alias when:
- The URL path does not match the filesystem path
- You are serving files from a completely different location
- You need to map a URL prefix to a directory with a different name
- You are combining multiple directories under different URL prefixes
Testing Your Configuration
Always test your NGINX configuration before deploying:
# Verify configuration syntax
nginx -t
# Test a specific file request
curl -I http://localhost/images/logo.png
# Check the actual file path in error logs (enable debug logging)
# Add to nginx.conf: error_log /var/log/nginx/error.log debug;
tail -f /var/log/nginx/error.log | grep "http filename"
Installing NGINX
On RHEL-based systems (Rocky Linux, AlmaLinux, CentOS):
dnf install nginx
systemctl enable --now nginx
The static module that handles both root and alias is compiled in by default.
Conclusion
The difference between NGINX alias and root comes down to one key concept: root appends the entire URI to the path, while alias replaces the location match with the specified path.
Key takeaways:
- Default to root: Use
rootunless you specifically need to map URLs to differently-named directories - Match trailing slashes with alias: Both the location and alias path should either have or not have trailing slashes
- Use capture groups with regex: When combining
aliaswith regex locations, you must use capture groups - Test your paths: When debugging, enable debug logging to see exactly how NGINX constructs file paths
Understanding how NGINX internally constructs file paths eliminates the guesswork from your configurations. The path formula tells you exactly what will happen, and matching trailing slashes prevents the most common errors.
For related NGINX configuration topics, see our guides on NGINX location priority, NGINX rewrite rules, and tuning proxy_buffer_size.

