http.handlers.file_server
Overview
The file server constructs the path to serve by joining the site root and the sanitized request path. Files within the root and links with targets outside the site root may be accessed.Configuration
The file system implementation to use. By default, Caddy uses the local disk file system.If a non-default filesystem is used, it must first be registered in the globals section.
The path to the root of the site. Default is
{http.vars.root} if set, or current working directory otherwise.A site root is not a sandbox. Although the file server sanitizes the request URI to prevent directory traversal, files and folders within the root may be directly accessed based on the request path.
List of files or folders to hide. The file server will pretend they don’t exist. Accepts glob patterns like
*.ext or /foo/*/bar.Because site roots can be dynamic, this list uses file system paths, not request paths. The base of relative paths is the current working directory.Examples:hidden- Hides all files/folders named “hidden” anywhere./hidden- Hides only the “hidden” file/folder in current directory*.secret- Hides all files ending with .secret
The names of files to try as index files if a folder is requested.
Enables file listings if a directory was requested and no index file is present.When enabled, the file server may serve a JSON array of the directory listing when the
Accept header includes application/json:Use redirects to enforce trailing slashes for directories or remove them for files.Canonicalization will not happen if the last element of the request’s path (the filename) was changed in an internal rewrite.
If enabled and a requested file is not found, invoke the next handler in the chain instead of returning a 404 error.This is useful for SPAs (Single Page Applications) where you want to serve index.html for any non-existent routes.
Override the status code written when successfully serving a file. Useful when explicitly serving a file as an error page display.Supports placeholders. By default, the status code will be 200, or 206 for partial content.
Precompressed Files
Selection of encoders to use to check for precompressed sidecar files.Module namespace: If a request comes in with
http.precompressedAccept-Encoding: gzip, and file.txt.gz exists, Caddy will serve the precompressed file with Content-Encoding: gzip.If the client has no strong preference (q-factor), choose encodings in this order.
Etag Configuration
List of file extensions to try to read Etags from. If set, file Etags will be read from sidecar files with these suffixes, instead of generating our own.Etag values in the files must be quoted as per RFC 7232.
Response Headers
The file server sets the following headers:- Etag - Calculated from file modification time and size
- Last-Modified - File’s modification time
- Content-Type - Determined from file extension (no MIME sniffing)
- Content-Encoding - Set if serving precompressed files
- Vary: Accept-Encoding - Always set for proper caching
If-MatchIf-Unmodified-SinceIf-Modified-SinceIf-None-MatchRangeIf-Range
Configuration Examples
Basic File Server
With Browse Enabled
Hiding Files
With Precompressed Files
SPA Configuration
Custom Index Files
Security Considerations
Important Security Notes:
- The site root is not a sandbox. Files within the root can be accessed based on the request path.
- On Windows, the file server rejects:
- Paths with Alternate Data Streams (ADS)
- Paths with “8.3” short names
- Use the
hidedirective to prevent access to sensitive files - The file server does not perform MIME sniffing on content
Path Sanitization
The file server usespath.Clean() to sanitize request paths before joining with the root:
- Multiple slashes are collapsed
- Dot elements (
.and..) are resolved and removed - Paths are cleaned to prevent directory traversal
/foo/../barbecomes/bar/foo//barbecomes/foo/bar/./foobecomes/foo
Etag Calculation
Etags are calculated using:The file server uses millisecond-precision modification times (on ext4 and similar filesystems), which qualifies as a strong validator per RFC 9110.
Platform-Specific Behavior
Windows
On Windows, the file server:- Trims trailing dots and spaces from paths (Windows ignores them)
- Rejects paths with
:characters (ADS) - Rejects paths with
~in short segments (8.3 short names)
Error Handling
The file server returns:- 404 Not Found - File doesn’t exist (or is hidden)
- 403 Forbidden - Permission denied
- 400 Bad Request - Invalid path
- 503 Service Unavailable - Too many open files (with
Retry-Afterheader) - 405 Method Not Allowed - Method other than GET/HEAD (except in error context)