Nginx root and alias both point requests at files on disk, but they build the final filesystem path in different ways. Use root when the URI path matches your directory layout, and use alias when a URI prefix should map to a completely different directory.
Most Nginx root vs alias mistakes show up as 404 or 403 errors even when the file exists. The fix is usually not a bigger rewrite. It is understanding which part of the request URI Nginx appends, which part it replaces, and which location block actually handles the request.
Understand Nginx Root vs Alias Path Mapping
The difference is easiest to see through path mapping. The root directive appends the request URI to the configured directory, as described in the official root directive documentation. The alias directive replaces the matching location prefix with a different filesystem path, as shown in the official alias directive documentation.
| Directive | Where It Belongs | How Nginx Builds the Path | Best Use |
|---|---|---|---|
root | http, server, location, or if in location | Appends the full request URI to the configured directory. | Normal document roots where the URL structure matches the directory tree. |
alias | location | Replaces the matched location prefix with the configured directory. | Serving a URI prefix from a separate directory outside the main site root. |
How Nginx Root Builds File Paths
With root, Nginx keeps the request URI and adds it to the configured path. A request for /images/logo.png under this server block maps to /var/www/example.com/public/images/logo.png.
server {
listen 80;
server_name example.com;
root /var/www/example.com/public;
location /images/ {
try_files $uri =404;
}
}
| Request URI | Nginx Filesystem Check |
|---|---|
/images/logo.png | /var/www/example.com/public/images/logo.png |
/images/icons/menu.svg | /var/www/example.com/public/images/icons/menu.svg |
How Nginx Alias Builds File Paths
With alias, Nginx removes the matched URI prefix and uses the alias directory instead. A request for /downloads/report.pdf under this location maps to /srv/example-downloads/report.pdf, not to the main site root.
server {
listen 80;
server_name example.com;
root /var/www/example.com/public;
location /downloads/ {
alias /srv/example-downloads/;
try_files $uri =404;
}
}
| Request URI | Nginx Filesystem Check |
|---|---|
/downloads/report.pdf | /srv/example-downloads/report.pdf |
/downloads/archive/app.tar.gz | /srv/example-downloads/archive/app.tar.gz |
If the
locationpath ends with a slash, thealiaspath should normally end with a slash too. Matching the slash style avoids joined paths such as/srv/example-downloadsreport.pdf.
Choose Nginx Root or Alias for the Right Job
Use root for the normal site directory. Use alias for exceptions where a URL prefix points somewhere else. This keeps the server block easier to read and reduces path surprises later.
| Task | Better Directive | Why |
|---|---|---|
Serve /css/site.css from /var/www/example.com/public/css/site.css | root | The URI path and directory path already match. |
Serve /downloads/file.zip from /srv/downloads/file.zip | alias | The URI prefix should not appear in the filesystem path. |
| Serve a full static site from one document root | root | The same base directory handles normal page and asset requests. |
| Expose one app-owned upload directory under a public URI prefix | alias | The upload directory often lives outside the site document root. |
Map / to the main site directory | root | alias is location-only and is usually unnecessary for the root location. |
When the issue is not only path mapping, check the surrounding routing too. Exact locations, prefix locations, regex locations, and ^~ prefixes can make a different block handle the request before the block you expected.
Before changing a live server block, keep a rollback copy of the working config and test the edited file with
nginx -t. A wrongrootoraliascan break asset paths or expose a different directory than intended.
Configure Nginx Root for a Normal Document Root
A normal website usually needs one root directive at the server level. The location then checks the requested URI under that document root.
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
This is the clean pattern for static sites, simple web roots, and most frontend builds where the public files live under one directory. The try_files line checks the requested file, then a matching directory, then returns a clean 404 when neither exists.
Test the Nginx configuration before reloading the service:
sudo nginx -t
A successful syntax test prints these lines:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
On systemd-based Linux hosts, reload Nginx only after the syntax test passes:
sudo systemctl reload nginx
Check the local response with the expected host header:
curl -fsSI -H "Host: example.com" http://127.0.0.1/ | sed -n '1p'
Relevant headers include a successful response from the server block:
HTTP/1.1 200 OK
Configure Nginx Alias for a Separate Directory
An alias location is useful when one URL prefix should serve files from a directory that does not live under the main document root. Downloads, generated reports, user uploads, and shared static assets are common examples.
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.html index.htm;
location /downloads/ {
alias /srv/example-downloads/;
try_files $uri =404;
}
}
In that configuration, /downloads/report.pdf maps to /srv/example-downloads/report.pdf. If you used root /srv/example-downloads; inside the same location, Nginx would look for /srv/example-downloads/downloads/report.pdf instead, because root keeps the full URI path.
Verify the file exists at the path that alias should use:
sudo test -f /srv/example-downloads/report.pdf && echo "file exists"
Expected output:
file exists
Run the syntax test, reload Nginx on systemd-based Linux hosts after it passes, then check the aliased URL:
curl -fsSI -H "Host: example.com" http://127.0.0.1/downloads/report.pdf | sed -n '1p'
Relevant headers should show a successful file response:
HTTP/1.1 200 OK
Match Trailing Slashes in Nginx Alias Blocks
Most alias mistakes come from mismatched trailing slashes. For a prefix location such as /assets/, keep the alias directory slash-aligned with the location prefix.
location /assets/ {
alias /srv/app/assets/;
}
That maps /assets/app.css to /srv/app/assets/app.css. If the alias path misses the trailing slash, Nginx joins the remaining URI part directly onto the directory name.
| Config Shape | Request | Path Nginx Tries |
|---|---|---|
location /assets/ with alias /srv/app/assets/; | /assets/app.css | /srv/app/assets/app.css |
location /assets/ with alias /srv/app/assets; | /assets/app.css | /srv/app/assetsapp.css |
When a 404 only appears under an aliased prefix, check the slash style before changing permissions, cache settings, or application code.
Use Nginx Root vs Alias with try_files
The try_files directive often exposes root and alias mistakes because it asks Nginx to prove that a file exists before serving it. Keep the fallback as a URI or named location, not as a raw filesystem path.
Use Nginx Root with a Static Site Fallback
For normal document roots, a single-page app or frontend build can fall back to /index.html when the requested file is missing.
server {
listen 80;
server_name app.example.com;
root /var/www/app/public;
location / {
try_files $uri $uri/ /index.html;
}
}
The fallback /index.html is a URI, so Nginx checks it under the configured root and serves /var/www/app/public/index.html.
Use Nginx Alias with a Named Fallback
For aliased file areas, a named location is often cleaner than sending users to another filesystem-looking path. This keeps missing file handling separate from the file mapping itself.
location /uploads/ {
alias /srv/app/uploads/;
try_files $uri @missing_upload;
}
location @missing_upload {
return 404;
}
Do not use a raw path such as /srv/app/uploads/fallback.png as the final try_files argument. Nginx treats final fallbacks as internal redirects or status codes, not as arbitrary filesystem paths to serve directly.
Use Nginx Alias Carefully in Regex Locations
Simple prefix locations are easier to read and maintain. If you use alias inside a regex location, make the regex captures explicit in the alias path so the final filename is not lost.
location ~ ^/users/([a-z0-9_-]+)/files/(.+)$ {
alias /srv/users/$1/files/$2;
}
In this example, a request for /users/alice/files/avatar.png maps to /srv/users/alice/files/avatar.png. Without the second capture in the alias path, Nginx would not know which filename from the regex match should be served.
Use regex aliases only when the URI pattern really needs capture groups. For ordinary prefixes such as
/uploads/, a plain prefix location is safer and easier to debug.
Verify Nginx Root and Alias Configuration
Before changing more directives, test the syntax and then confirm the active configuration that Nginx actually loaded. This catches broken snippets, edits made in the wrong file, or disabled site files.
sudo nginx -t
A passing syntax test prints these lines:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
After the syntax test passes, dump the active config and filter for the relevant path directives:
sudo nginx -T 2>/dev/null | grep -E 'server_name|location |root |alias |try_files'
Relevant lines include the server name, matching location, path directive, and file check:
server_name example.com www.example.com;
root /var/www/example.com/public;
location /downloads/ {
alias /srv/example-downloads/;
try_files $uri =404;
If the output does not show the file you edited, check your package layout. Debian and Ubuntu packages commonly use /etc/nginx/sites-available/ with sites-enabled/ symlinks, while Fedora, RHEL-family, and nginx.org packages commonly load files from /etc/nginx/conf.d/.
On systemd-based Linux hosts, reload Nginx after the syntax test passes:
sudo systemctl reload nginx
Troubleshoot Common Nginx Root vs Alias Errors
Path-mapping errors can look like ordinary 404 or 403 problems. Start with the path Nginx tried, then decide whether the issue is mapping, permissions, or location selection.
Fix 404 Errors from the Wrong Nginx Root Path
If a file exists on disk but the browser gets a 404, read the error log and look at the exact path in the open() failure.
Most packaged Linux builds write the main Nginx error log to /var/log/nginx/error.log. If your config sets a different error_log path, inspect that file instead.
sudo tail -n 20 /var/log/nginx/error.log
A root-vs-alias mistake often leaves a stable pattern like this in the log:
open() "/var/www/example.com/public/downloads/report.pdf" failed (2: No such file or directory)
If the real file is /srv/example-downloads/report.pdf, the fix is not to create another downloads directory under the web root. Use an alias location for /downloads/. For broader 404 troubleshooting, use the fix Nginx 404 Not Found guide.
Fix 403 Errors After Changing Nginx Alias
A correct alias can still return 403 when Nginx cannot read the file, cannot traverse a parent directory, or is asked to list a directory without an index file. Check the path permissions from the root of the filesystem to the target file.
namei -l /srv/example-downloads/report.pdf
The Nginx worker user needs execute permission on each parent directory and read permission on the file. If the request points at a directory, either add an index file or intentionally enable autoindex for that location. For a full permissions and directory-index workflow, use the fix Nginx 403 Forbidden guide.
Fix Joined Paths from a Missing Nginx Alias Slash
If the error log shows a path where the directory and filename were joined together, match the slashes in the location and alias path.
location /assets/ {
alias /srv/app/assets/;
}
Retest with nginx -t, reload Nginx, then request the same asset again with curl -fsSI. Do not change file ownership until the mapped path itself is correct.
Fix Requests Handled by the Wrong Nginx Location
If the right root or alias exists but the request still maps somewhere else, another location block may be winning. Exact matches, prefix matches, regex locations, and ^~ prefixes can change which block handles the request.
curl -sSI -H "Host: example.com" http://127.0.0.1/assets/app.css | sed -n '1p'
If the status code or headers do not match the expected block, review the nearby location rules and compare exact, prefix, regex, and ^~ matches before changing the root or alias path.
Fix Nginx try_files Fallbacks That Break Alias Locations
A final try_files argument should be a status code, a named location, or a URI that Nginx can process again. It should not be a raw filesystem path.
location /uploads/ {
alias /srv/app/uploads/;
try_files $uri @missing_upload;
}
location @missing_upload {
return 404;
}
If the fallback needs to serve a real file, route to a URI that maps through a normal root location, or use a named location that returns the intended response.
Use Nginx Root and Alias Safely
- Use one server-level
rootfor the main site when the URI and directory layout match. - Use
aliasonly for specificlocationblocks that map to a different directory. - Match trailing slashes between prefix locations and alias directories.
- Keep
try_filesfallbacks as URIs, status codes, or named locations. - Check the active config with
nginx -Twhen edits do not affect the live response. - Use
curl -fsSIwith a host header to test the exact server block before relying on DNS or a CDN layer.
For reverse-proxy paths, do not treat root and alias as substitutes for upstream URI rewriting. Use the Nginx proxy_pass trailing slash guide when the path changes at the upstream proxy layer instead of the static-file layer.
Conclusion
The safest Nginx root vs alias workflow is to keep one normal document root, reserve alias for deliberate URI-to-directory remapping, and verify the active config before changing permissions or application code. Use nginx -t, nginx -T, local curl checks, and error-log paths whenever a request maps to the wrong file.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>