The Static File Server is a core HTTP handler in Caddy that serves static files from the file system. This document provides an overview of the file server's architecture, configuration options, and integration with other Caddy components. For detailed information about file serving mechanics and precompressed file handling, see File Serving and Precompression. For directory browsing capabilities, see Directory Browsing.
The file server implements the http.handlers.file_server module and operates as middleware in the HTTP request processing chain.
The Static File Server is implemented by the FileServer struct, which serves both regular files and directory listings. It integrates with Caddy's file system abstraction layer to support multiple storage backends and coordinates with the response encoding system for optimal content delivery.
Diagram: FileServer Architecture
Sources: modules/caddyhttp/fileserver/staticfiles.go263-580 modules/caddyhttp/fileserver/browse.go78-213
The FileServer type is the main handler implementation, registered as the http.handlers.file_server module. It contains configuration for file serving behavior and coordinates all file operations.
Diagram: FileServer Configuration Structure
Sources: modules/caddyhttp/fileserver/staticfiles.go97-177 modules/caddyhttp/fileserver/browse.go52-72
| Field | Type | Purpose |
|---|---|---|
FileSystem | string | File system identifier from global registry; defaults to {http.vars.fs} |
Root | string | Site root path; defaults to {http.vars.root} or current working directory |
Hide | []string | Patterns for files/directories to hide; supports globs and placeholders |
IndexNames | []string | Files to try as directory indexes; default: ["index.html", "index.txt"] |
Browse | *Browse | Directory browsing configuration; nil disables browsing |
CanonicalURIs | *bool | Enforce trailing slash conventions; default true |
StatusCode | WeakString | Override response status code; supports placeholders |
PassThru | bool | Invoke next handler on 404 instead of returning error |
PrecompressedRaw | ModuleMap | Precompressed file encoder modules |
PrecompressedOrder | []string | Preference order for precompressed encodings |
EtagFileExtensions | []string | Extensions for sidecar files containing precomputed Etags |
Sources: modules/caddyhttp/fileserver/staticfiles.go97-177
The ServeHTTP method orchestrates the entire file serving process, from path sanitization through response delivery.
Diagram: ServeHTTP Request Processing
Sources: modules/caddyhttp/fileserver/staticfiles.go263-580
The file server performs several security checks before serving files:
: and 8.3 short names containing ~SanitizedPathJoin to clean and join the root and request pathSources: modules/caddyhttp/fileserver/staticfiles.go266-277
The file server uses Go's fs.FS interface for file system operations, allowing multiple storage backends through Caddy's file system registry:
The file system is resolved using the FileSystem field (default: {http.vars.fs}), which allows dynamic selection per request through variable substitution.
Sources: modules/caddyhttp/fileserver/staticfiles.go282-287
When a directory is requested, the file server attempts to serve an index file before considering directory browsing or returning 404.
Index File Search Process:
IndexNames (default: ["index.html", "index.txt"])SanitizedPathJoin(filename, indexPage)fs.Stat on the index pathSources: modules/caddyhttp/fileserver/staticfiles.go318-354
The file server enforces URI conventions to ensure consistent linking and prevent broken relative URLs:
/dir/)/file.html)This behavior is controlled by the CanonicalURIs field (default: true). Redirects are issued only when:
Sources: modules/caddyhttp/fileserver/staticfiles.go383-415
Files and directories can be hidden from access using glob patterns. The Hide field accepts:
"secret" hides any file/directory named "secret" anywhere"./secret" hides only the specific path"*.tmp" or "/foo/*/bar"The fileHidden function evaluates these patterns, using:
filepath.MatchSources: modules/caddyhttp/fileserver/staticfiles.go664-713
The file server integrates with the precompressed file system to serve pre-encoded variants:
Diagram: Precompressed File Selection
Supported precompressed formats (via http.precompressed.* modules):
.br) - http.precompressed.br.zst) - http.precompressed.zstd.gz) - http.precompressed.gzipSources: modules/caddyhttp/fileserver/staticfiles.go430-485
The file server sets several standard HTTP headers:
| Header | Purpose | Source |
|---|---|---|
Vary: Accept-Encoding | Cache key differentiation | Always set for static files |
Etag | Cache validation | Calculated from modtime + size, or from sidecar file |
Last-Modified | File modification time | From fs.FileInfo.ModTime() |
Content-Type | MIME type | From mime.TypeByExtension() |
Content-Encoding | Applied encoding | When serving precompressed files |
Content-Length | Response size | For precompressed non-range requests |
Etag Calculation:
The default Etag is generated using calculateEtag(), which creates a strong validator by combining modification time (nanoseconds) and file size in base-36:
"<modTimeNano_base36><size_base36>"
Alternatively, Etags can be read from sidecar files with extensions specified in EtagFileExtensions.
Sources: modules/caddyhttp/fileserver/staticfiles.go418-532 modules/caddyhttp/fileserver/staticfiles.go724-750
The file server coordinates with the Encode middleware (Response Encoding) for dynamic compression:
Vary: Accept-Encoding to enable proper cachingThe separation allows flexible deployment:
Sources: modules/caddyhttp/fileserver/staticfiles.go423-428
The file server maps file system errors to appropriate HTTP status codes:
The PassThru option allows the file server to delegate to subsequent handlers when files are not found, enabling fallback behaviors.
Sources: modules/caddyhttp/fileserver/staticfiles.go586-612 modules/caddyhttp/fileserver/staticfiles.go715-722
The StatusCode field allows overriding the response status code, useful when serving error pages:
handle_errors)statusOverrideResponseWriter wrapperSources: modules/caddyhttp/fileserver/staticfiles.go544-571 modules/caddyhttp/fileserver/staticfiles.go787-805
The file server registers as a Caddy module in the http.handlers namespace:
This allows it to be loaded and configured through JSON config, Caddyfile directives, or the Admin API.
Sources: modules/caddyhttp/fileserver/staticfiles.go41-43 modules/caddyhttp/fileserver/staticfiles.go180-185
Refresh this wiki