October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk10 min

How to Restrict Directories in Nginx While Keeping Direct File Access

Use separate Nginx locations for the directory URI and direct files. This guide shows how to hide listings, control Basic Auth inheritance, handle index redirects and trailing slashes, protect sensitive files, and verify every response.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate the directory request from the file requests. Protect the slash-terminated directory URI with its own location, then use a more-specific file-serving location with auth_basic off; only when known files are meant to remain public. Keep autoindex off; so visitors cannot generate a listing, and test index redirects separately because Nginx can internally redirect a directory request to an index file handled by another location.

If every file must be private, do not disable authentication in the file location. The correct configuration depends on whether you are restricting a listing, the files themselves, or both.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Define the access policy before writing locations

“Restrict the directory” can describe several different policies. Nginx does not have a single directory-permission switch; it applies directives to the URI location selected for each request. Decide what each request should do first.

Request Typical policy Configuration implication
/downloads Redirect to the canonical slash URI, or challenge immediately Add an explicit no-slash location if its behavior matters
/downloads/ Require credentials, deny access, or show a deliberate listing Use an exact location for the directory endpoint
/downloads/report.pdf Public, authenticated, IP-limited, or allowlisted Use a file location whose access directives match that policy
/downloads/index.html Often deserves the same protection as the directory endpoint Remember that an index request can be internally redirected
/downloads/missing.pdf Return a normal not-found response Use try_files with an explicit =404
/downloads/subfolder/ Listing disabled, index protected, or access denied Do not assume an exact location for the top-level directory covers nested slash paths

The examples below use /downloads/ and a document root of /srv/www. Replace those values with your URI and filesystem layout.

How Nginx selects the location

Nginx first looks for an exact location such as location = /downloads/. If none matches, it remembers the longest matching prefix, such as location /downloads/ or location ^~ /downloads/. Regular-expression locations may then be considered unless the selected prefix uses ^~. An exact match wins over a prefix, so the exact directory rule below handles /downloads/ while the broader file rule handles paths below it.

The trailing slash is significant. /downloads does not match location = /downloads/, and it does not match a prefix that includes the slash. It may therefore fall through to a server-wide location, be redirected by another rule, or be served as a different filesystem path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Location selection can happen more than once. The index module processes a slash-ended request and may internally redirect it to /downloads/index.html. A try_files directive can also perform an internal redirect. The new URI is matched again, which is why a file location can receive a request that began as a directory request.

Baseline: restrict the directory endpoint but allow known files

This is the smallest useful pattern when the directory URL requires Basic Authentication but direct links to existing files should work without inherited credentials.

server {
    root /srv/www;

    # The directory endpoint is protected and does not generate a listing.
    location = /downloads/ {
        auth_basic "Restricted directory";
        auth_basic_user_file /etc/nginx/.htpasswd;
        autoindex off;
        try_files $uri $uri/ =404;
    }

    # Existing files below /downloads/ are public.
    location ^~ /downloads/ {
        auth_basic off;
        try_files $uri =404;
    }
}

What each directive does

  • location = /downloads/ applies only to the slash-terminated directory URI. It does not automatically protect files or the no-slash form.
  • auth_basic enables HTTP Basic Authentication for that location. The quoted text is the authentication realm shown by clients.
  • auth_basic_user_file points to the password file. The Nginx worker must be able to read it; an unreadable file causes authentication requests to fail.
  • autoindex off prevents the autoindex module from producing a generated listing. Nginx documents that this module processes requests ending in a slash and produces a directory listing when enabled; its default is off, but stating the policy explicitly prevents surprises from inherited configuration.
  • try_files $uri $uri/ =404 checks the mapped filesystem path and returns a not-found response when neither a file nor directory exists. The root directive maps /downloads/file.pdf to /srv/www/downloads/file.pdf.
  • location ^~ /downloads/ is the broader rule for direct paths. auth_basic off; cancels Basic Authentication inherited from a server or higher-level location. It should appear here only if these files are intentionally public.
  • The file rule uses try_files $uri =404, so a guessed path cannot be converted into a fallback application request or an unintended default file.

With this configuration, a request for /downloads/ receives a challenge, while a request for an existing /downloads/report.pdf is served without that challenge. A missing file returns 404. The no-slash URI and index behavior still need an explicit decision.

Choose the file policy explicitly

Protect every file

If the directory is private, keep authentication on the broader location instead of turning it off:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
location ^~ /downloads/ {
    auth_basic "Private downloads";
    auth_basic_user_file /etc/nginx/.htpasswd;
    autoindex off;
    try_files $uri $uri/ =404;
}

This covers the directory path, files, and nested paths that match the prefix. Add a separate exact location for /downloads if the no-slash form must receive the same challenge rather than a redirect or a response from another server rule.

Allow only selected public files

A broad public prefix is convenient but grants access to every readable file below it. If only a small allowlist is public, use exact locations for those files and keep the broader location protected:

location ^~ /downloads/ {
    auth_basic "Private downloads";
    auth_basic_user_file /etc/nginx/.htpasswd;
    autoindex off;
    try_files $uri $uri/ =404;
}

location = /downloads/public-manual.pdf {
    auth_basic off;
    try_files $uri =404;
}

location = /downloads/status.json {
    auth_basic off;
    try_files $uri =404;
}

Exact file locations take precedence over the protected prefix. This approach is safer when a directory contains mixed public and private material.

Expose a listing deliberately

To make a directory listing a feature, set autoindex on; in the location that should generate it. A listing reveals filenames, sizes, and modification information, so do not enable it merely to make known files downloadable. Keep authentication, IP controls, or both if the names themselves are sensitive.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make index behavior predictable

The index module handles slash-ended requests. If /downloads/index.html exists and index index.html; is in effect, Nginx can internally redirect the directory request to that file. The second location lookup may select the public file prefix from the baseline example, making the index page public even though /downloads/ is protected.

There are three common policies:

Protect the index page

Add an exact location for the index file and repeat the authentication directives there:

location = /downloads/index.html {
    auth_basic "Restricted directory";
    auth_basic_user_file /etc/nginx/.htpasswd;
    try_files $uri =404;
}

This exact match wins when the index module internally redirects to that URI. Apply the same technique to any other index filename that can be selected by your index directive.

Make the index page public

Leave the public file location in place, but recognize that anyone who can guess or receive the index URL can read it. Do not put secrets, deployment data, or private links in that document.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Block the index page

Use an exact deny rule when the directory must not serve an index at all:

location = /downloads/index.html {
    return 404;
}

Alternatively, configure a different index policy and verify the resulting status with a request to both the directory URI and the index URI. Simply setting autoindex off; does not block a real index file; it only disables generated listings.

Handle the missing trailing slash

Browsers and crawlers may request /downloads without the final slash. If you want one canonical URL, add an explicit redirect:

location = /downloads {
    return 301 /downloads/;
}

A redirect reveals that the endpoint exists before authentication. If that disclosure is undesirable, protect the no-slash location instead of issuing an unauthenticated redirect:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
location = /downloads {
    auth_basic "Restricted directory";
    auth_basic_user_file /etc/nginx/.htpasswd;
    return 301 /downloads/;
}

Whether a redirect should be challenged depends on your threat model and on whether endpoint existence is sensitive. Test both forms; do not assume the exact slash location will catch the no-slash request.

Use IP restrictions, Basic Auth, or both

Basic Authentication is useful for a small private area. IP rules are more appropriate when access should come from a known network. Nginx’s allow and deny directives can be combined with authentication through satisfy.

Allow a network and deny everyone else

location ^~ /downloads/ {
    allow 192.0.2.0/24;
    deny all;
    autoindex off;
    try_files $uri $uri/ =404;
}

Access-control directives are inherited only when the current level defines none of them. Define the complete allow/deny policy in the location where you need it so a broader server rule does not silently change the result.

Accept either an approved IP or valid credentials

location ^~ /downloads/ {
    allow 192.0.2.0/24;
    deny all;
    auth_basic "Downloads";
    auth_basic_user_file /etc/nginx/.htpasswd;
    satisfy any;
    autoindex off;
    try_files $uri $uri/ =404;
}

satisfy any; permits the request when one access check succeeds: the client is from the allowed network or supplies valid credentials. With satisfy all;, both checks must succeed. Choose one deliberately; the two modes provide materially different access boundaries.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify filesystem mapping with root and alias

root appends the request URI to the configured root. With root /srv/www;, /downloads/report.pdf maps to /srv/www/downloads/report.pdf.

alias maps a location to a different filesystem path rather than appending the complete URI. This is useful when the public URI and storage directory do not have the same names, but it makes path calculations easier to get wrong. Validate every try_files path after changing from root to alias, and check that the Nginx worker has execute permission on each parent directory and read permission on the file.

A successful location match does not guarantee a successful file read. Filesystem permissions, symbolic links, mandatory access controls, and the configured user can still produce 403 or 404 responses. Keep private content outside unrelated web roots when possible, and expose only the path that the policy requires.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep sensitive files out of the downloadable tree

Never rely on directory authentication alone to protect operational files. Password files, private keys, deployment manifests, source archives, editor backups, and application configuration should not be readable through a public prefix.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use explicit exact deny locations for known sensitive names when your public location uses ^~:

location = /downloads/.htpasswd {
    return 404;
}

location = /downloads/deploy-manifest.yml {
    return 404;
}

location = /downloads/server.key {
    return 404;
}

The ^~ modifier prevents later regular-expression locations from being considered for matching requests. Consequently, a generic dot-file regular expression may not protect a file beneath that prefix. Either add exact deny rules for sensitive paths, or redesign the prefix and regular-expression ordering with a complete understanding of Nginx’s location algorithm. Filesystem permissions remain the final safeguard.

Validate configuration and responses

Make configuration validation part of every change. First test syntax and referenced files, then reload through the service manager used by the host:

  1. Run nginx -t. Do not reload if it reports an error.
  2. Reload Nginx with the host’s service manager, for example systemctl reload nginx when that is how the server is managed.
  3. Check the directory without a slash: curl -i https://example.test/downloads.
  4. Check the canonical slash endpoint: curl -i https://example.test/downloads/. Confirm the expected 401 challenge, redirect, 403 response, or listing.
  5. Request a known file: curl -i https://example.test/downloads/report.pdf. Confirm whether it is public or challenged according to policy.
  6. Request the index explicitly: curl -i https://example.test/downloads/index.html. Compare it with the slash-ended request.
  7. Request a missing name: curl -i https://example.test/downloads/not-present.txt. Confirm the intended 404 rather than an application fallback.
  8. Repeat the checks for a nested directory, a nested file, a URL containing percent-encoded characters, and dot-segment input if those forms are relevant to your security policy.

For Basic Authentication, inspect the response headers as well as the status. An unauthenticated challenge normally includes WWW-Authenticate. An IP denial may return 403 without that challenge. These differences help identify which access check handled the request.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot common failures

Symptom Likely cause Correction
The folder is protected, but index.html is public The slash request internally redirected to a public file location Add an exact protected index location or protect the broader file prefix
/downloads behaves differently from /downloads/ The exact slash location does not match the no-slash URI Add an explicit redirect or a separately protected no-slash location
Known files unexpectedly require credentials Authentication is inherited and no public override exists Add auth_basic off; only in the intended public file location
A public prefix exposes more files than intended The prefix grants access to every readable path below it Use a protected broad location with exact public file exceptions
A directory listing appears autoindex on; is inherited or enabled elsewhere Set autoindex off; in the relevant locations and inspect included configuration
A file returns 404 even though it exists The root/alias mapping or permissions are wrong Calculate the resulting filesystem path, check parent-directory traversal permission, and verify with try_files
Authentication always fails Nginx cannot read the password file or the file format is invalid Check ownership and permissions for the Nginx worker account, then rerun nginx -t
A regex deny rule does not block a sensitive file The request matched a ^~ prefix, which skips regex locations Add an exact deny rule or revise location precedence deliberately
Nested directories do not follow the top-level policy The exact location matches only one URI Add a suitable nested-path rule and test slash-ended subdirectories separately

Production checklist

  • Write down whether the directory endpoint, files, index documents, and nested paths are public, authenticated, IP-limited, or denied.
  • Handle both /downloads and /downloads/.
  • Keep autoindex off; unless a listing is an intentional feature.
  • Use auth_basic off; only where public access is deliberate.
  • Protect or remove password files, keys, manifests, source archives, and backup files.
  • Confirm whether index.html should be challenged, public, or blocked after internal redirection.
  • Check every root or alias mapping and the Nginx worker’s filesystem permissions.
  • Use try_files with an explicit error result so missing names do not fall through unexpectedly.
  • Run nginx -t before reloading.
  • Verify status codes and WWW-Authenticate behavior for directory, file, index, missing-file, and unauthorized-IP requests.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

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

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.