NGINX / Server Setup

NGINX Alias vs Root: End the Confusion Once and For All

by , , revisited on


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

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:

  1. Cannot be used in named locations: Named locations (those starting with @) cannot use alias
  2. Cannot be used with certain rewrites: If the URI is modified by a rewrite, alias may produce unexpected results
  3. Only valid in location context: Unlike root, alias cannot be placed in http or server blocks

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:

  1. NGINX constructs: /var/www/html/assets/style.css
  2. If not found, tries: /var/www/html/assets/style.css/
  3. 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:

  1. NGINX constructs: /srv/static-files/style.css
  2. If not found, tries: /srv/static-files/style.css/
  3. 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 root unless 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 alias with 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.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.