Requests and static files

Serve static files safely

Map request URIs to files with root, alias, index, and tryfiles while avoiding accidental exposure.

8 minute lesson

~~~

Serving files is about one mapping: how does a request URI become a filesystem path? Nginx gives you two directives for it, and they behave differently.

root appends the full request URI to a directory. alias replaces the matching location prefix with another path.

server {
  listen 80;
  server_name static.example.com;
  root /var/www/site/public;

  location / {
    index index.html;
    try_files $uri $uri/ =404;
  }

  location /downloads/ {
    alias /srv/files/;
  }
}

With root, a request for /css/site.css reads /var/www/site/public/css/site.css — directory plus the whole URI. With alias, a request for /downloads/report.pdf reads /srv/files/report.pdf — the /downloads/ prefix is swapped for /srv/files/. If you had used root /srv/files/ there, Nginx would look for /srv/files/downloads/report.pdf, which is almost never what you meant.

try_files $uri $uri/ =404 checks the exact file first, then a directory of that name (which triggers index), then gives up with a 404. It’s the standard pattern for static sites because it never invents paths: the request either maps to a real file or fails cleanly.

Directory listing stays off unless you have a deliberate reason to enable it. autoindex defaults to off, so a directory without an index file returns 403 instead of exposing its contents. Leave it that way.

Keep private files out of the root

The root directory is a public boundary. Anything inside it can be requested by URL, so keep secrets, dotfiles, and build artifacts outside. Publish a public/ directory and keep .env, source code, and backups one level up where no URI can reach them.

Verify the behavior with three requests:

curl -I http://static.example.com/index.html   # 200
curl -I http://static.example.com/missing.css  # 404
curl -I http://static.example.com/.env         # 404 - lives outside the root

The failure mode to watch for is a misplaced trailing slash with alias. location /downloads/ paired with alias /srv/files (no trailing slash) produces paths like /srv/filesreport.pdf, and every request 404s. Keep both the location prefix and the alias path ending in /, then re-test with a known file.

Serve a small public directory containing index.html and one asset. Verify a missing path returns 404 and a sibling private file cannot be requested.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →