Configuration: static file serving
This page documents directives that configure static file serving, directory listings, compression, caching behavior, and custom error pages for requests resolved to the filesystem (via root).
Info
Static file serving is handled by the http-static module. For related features, see Routing and URL processing, HTTP cache, HTTP response control, URL rewriting, and HTTP compression.
Directives
Index and directory listings
index <filename: string>...- This directive specifies one or more filenames to try when a request path resolves to a directory. Files are tried in order; the first existing file replaces the directory path in the file context. Only applies when the resolved path is a directory and no
path_infois present. Default:index index.html index.htm index.xhtml
- This directive specifies one or more filenames to try when a request path resolves to a directory. Files are tried in order; the first existing file replaces the directory path in the file context. Only applies when the resolved path is a directory and no
directory_listing [bool: boolean](http-static)- This directive specifies whether auto-generated HTML directory listings are enabled when a request path resolves to a directory and no index file is found. Default:
directory_listing false
- This directive specifies whether auto-generated HTML directory listings are enabled when a request path resolves to a directory and no index file is found. Default:
Configuration example:
example.com {
root /srv/www/example
index index.html index.htm
directory_listing
}Note
- Only generates a listing if no
indexfile was found for the directory. - Dotfiles (names starting with
.) are excluded from the listing, except.maindescwhich is read as a description. - A
.maindescfile in the directory, if present, is displayed as a<pre>block below the file table.
Caching headers
etag [bool: boolean](http-static)- This directive specifies whether ETag generation for static file responses is enabled. ETags are weak ETags (
W/"...") generated from an xxHash3 hash of the file path, size, and modification time. Default:etag true
- This directive specifies whether ETag generation for static file responses is enabled. ETags are weak ETags (
file_cache_control <value: string>(http-static)- This directive specifies the
Cache-Controlresponse header for all static file responses. The value is passed through as-is. Default: not set
- This directive specifies the
Configuration example:
example.com {
root /srv/www/example
etag
file_cache_control "public, max-age=3600"
}Note
- When compression is used, a suffix is appended to the ETag (e.g.
W/"abc123-br"for Brotli). If-None-Matchrequests that match the current ETag return304 Not Modified.- Pre-compressed sidecar files receive their own ETag based on the sidecar file’s own metadata.
MIME types
mime_type <extension: string> <mime-type: string>(http-static)- This directive maps a file extension (with or without leading dot) to a MIME type. Custom MIME type mappings override the built-in database for matching extensions. Multiple
mime_typedirectives can be used to map different extensions. Default: built-in MIME database
- This directive maps a file extension (with or without leading dot) to a MIME type. Custom MIME type mappings override the built-in database for matching extensions. Multiple
Configuration example:
example.com {
root /srv/www/example
mime_type ".wasm" "application/wasm"
mime_type ".webmanifest" "application/manifest+json"
}Note
- If the extension is not found in custom mappings, the built-in database is used as a fallback.
- If neither custom nor built-in mappings match, the response is sent with no
Content-Typeheader.
Error pages
error_page <status-code: integer>... <file-path: string>- This directive specifies one or more HTTP status codes followed by a file path to serve as the error response body. The last argument is always the file path; all preceding arguments are status codes. Default: built-in error pages
Configuration example:
example.com {
root /srv/www/example
error_page 404 /custom/404.html
error_page 500 502 503 504 /custom/50x.html
}Note
- Only applies when an error response is being generated and no custom response has already been set.
- The file path is absolute or relative to the current working directory.
- If the specified error page file does not exist, the directive is skipped and the built-in error page is used.
- Multiple status codes can be mapped to the same error page in a single directive.
Observability
Metrics
Static file serving
| Metric | Type | Attributes | Description |
|---|---|---|---|
ferron.static.files_served | Counter | ferron.compression ("identity", "gzip", "br", "deflate", "zstd"), ferron.cache_hit ("true" or "false") | Number of static files served |
ferron.static.bytes_sent | Histogram | ferron.compression ("identity", "gzip", "br", "deflate", "zstd"), ferron.cache_hit ("true" or "false") | Bytes sent for static file responses. Buckets: 1KB, 10KB, 100KB, 1MB, 10MB, 100MB |
ferron.static.responses | Counter | http.response.status.code (HTTP response status code), ferron.static.outcome (static file serving outcome) | Static-file responses across normal, conditional, range, and error paths |
Logs
WARN: logged when anerror_pagefile cannot be opened. The directive is skipped and the built-in error page is used instead.
Best practices
The following best-practice check is reported by ferron doctor for directives on this page.
directory_listingenabled — Auto-generated directory indexes expose file structure. Enable only for intentionally public file listings.