diff --git a/modules/caddyhttp/fileserver/browse.go b/modules/caddyhttp/fileserver/browse.go
index 90263560c..7804d19b7 100644
--- a/modules/caddyhttp/fileserver/browse.go
+++ b/modules/caddyhttp/fileserver/browse.go
@@ -210,7 +210,7 @@ func (fsrv *FileServer) isSymlinkTargetDir(f fs.FileInfo, root, urlPath string)
 		return false
 	}
 	target := caddyhttp.SanitizedPathJoin(root, path.Join(urlPath, f.Name()))
-	targetInfo, err := fsrv.fileSystem.Stat(target)
+	targetInfo, err := fs.Stat(fsrv.fileSystem, target)
 	if err != nil {
 		return false
 	}
diff --git a/modules/caddyhttp/fileserver/browsetplcontext.go b/modules/caddyhttp/fileserver/browsetplcontext.go
index 49788ee25..cd24fc232 100644
--- a/modules/caddyhttp/fileserver/browsetplcontext.go
+++ b/modules/caddyhttp/fileserver/browsetplcontext.go
@@ -65,7 +65,7 @@ func (fsrv *FileServer) directoryListing(entries []fs.DirEntry, canGoUp bool, ro
 		fileIsSymlink := isSymlink(info)
 		if fileIsSymlink {
 			path := caddyhttp.SanitizedPathJoin(root, path.Join(urlPath, info.Name()))
-			fileInfo, err := fsrv.fileSystem.Stat(path)
+			fileInfo, err := fs.Stat(fsrv.fileSystem, path)
 			if err == nil {
 				size = fileInfo.Size()
 			}
diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go
index 1a0424c15..df56092b0 100644
--- a/modules/caddyhttp/fileserver/caddyfile.go
+++ b/modules/caddyhttp/fileserver/caddyfile.go
@@ -77,11 +77,11 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
 				if err != nil {
 					return nil, err
 				}
-				statFS, ok := unm.(fs.StatFS)
+				fsys, ok := unm.(fs.FS)
 				if !ok {
-					return nil, h.Errf("module %s (%T) is not a supported file system implementation (requires fs.StatFS)", modID, unm)
+					return nil, h.Errf("module %s (%T) is not a supported file system implementation (requires fs.FS)", modID, unm)
 				}
-				fsrv.FileSystemRaw = caddyconfig.JSONModuleObject(statFS, "backend", name, nil)
+				fsrv.FileSystemRaw = caddyconfig.JSONModuleObject(fsys, "backend", name, nil)
 
 			case "hide":
 				fsrv.Hide = h.RemainingArgs()
diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go
index a5dab6eb9..87a152433 100644
--- a/modules/caddyhttp/fileserver/matcher.go
+++ b/modules/caddyhttp/fileserver/matcher.go
@@ -64,7 +64,7 @@ type MatchFile struct {
 	// The file system implementation to use. By default, the
 	// local disk file system will be used.
 	FileSystemRaw json.RawMessage `json:"file_system,omitempty" caddy:"namespace=caddy.fs inline_key=backend"`
-	fileSystem    fs.StatFS
+	fileSystem    fs.FS
 
 	// The root directory, used for creating absolute
 	// file paths, and required when working with
@@ -264,7 +264,7 @@ func (m *MatchFile) Provision(ctx caddy.Context) error {
 		if err != nil {
 			return fmt.Errorf("loading file system module: %v", err)
 		}
-		m.fileSystem = mod.(fs.StatFS)
+		m.fileSystem = mod.(fs.FS)
 	}
 	if m.fileSystem == nil {
 		m.fileSystem = osFS{}
@@ -418,7 +418,7 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
 		for _, pattern := range m.TryFiles {
 			candidates := makeCandidates(pattern)
 			for _, c := range candidates {
-				info, err := m.fileSystem.Stat(c.fullpath)
+				info, err := fs.Stat(m.fileSystem, c.fullpath)
 				if err == nil && info.Size() > largestSize {
 					largestSize = info.Size()
 					largest = c
@@ -439,7 +439,7 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
 		for _, pattern := range m.TryFiles {
 			candidates := makeCandidates(pattern)
 			for _, c := range candidates {
-				info, err := m.fileSystem.Stat(c.fullpath)
+				info, err := fs.Stat(m.fileSystem, c.fullpath)
 				if err == nil && (smallestSize == 0 || info.Size() < smallestSize) {
 					smallestSize = info.Size()
 					smallest = c
@@ -459,7 +459,7 @@ func (m MatchFile) selectFile(r *http.Request) (matched bool) {
 		for _, pattern := range m.TryFiles {
 			candidates := makeCandidates(pattern)
 			for _, c := range candidates {
-				info, err := m.fileSystem.Stat(c.fullpath)
+				info, err := fs.Stat(m.fileSystem, c.fullpath)
 				if err == nil &&
 					(recentInfo == nil || info.ModTime().After(recentInfo.ModTime())) {
 					recent = c
@@ -498,7 +498,7 @@ func parseErrorCode(input string) error {
 // NOT end in a forward slash, the file must NOT
 // be a directory.
 func (m MatchFile) strictFileExists(file string) (os.FileInfo, bool) {
-	info, err := m.fileSystem.Stat(file)
+	info, err := fs.Stat(m.fileSystem, file)
 	if err != nil {
 		// in reality, this can be any error
 		// such as permission or even obscure
diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go
index 25bcf5a26..0639d979f 100644
--- a/modules/caddyhttp/fileserver/staticfiles.go
+++ b/modules/caddyhttp/fileserver/staticfiles.go
@@ -83,14 +83,14 @@ type FileServer struct {
 	// disk file system.
 	//
 	// File system modules used here must adhere to the following requirements:
-	// - Implement fs.StatFS interface.
+	// - Implement fs.FS interface.
 	// - Support seeking on opened files; i.e.returned fs.File values must
 	//   implement the io.Seeker interface. This is required for determining
 	//   Content-Length and satisfying Range requests.
 	// - fs.File values that represent directories must implement the
 	//   fs.ReadDirFile interface so that directory listings can be procured.
 	FileSystemRaw json.RawMessage `json:"file_system,omitempty" caddy:"namespace=caddy.fs inline_key=backend"`
-	fileSystem    fs.StatFS
+	fileSystem    fs.FS
 
 	// The path to the root of the site. Default is `{http.vars.root}` if set,
 	// or current working directory otherwise. This should be a trusted value.
@@ -175,7 +175,7 @@ func (fsrv *FileServer) Provision(ctx caddy.Context) error {
 		if err != nil {
 			return fmt.Errorf("loading file system module: %v", err)
 		}
-		fsrv.fileSystem = mod.(fs.StatFS)
+		fsrv.fileSystem = mod.(fs.FS)
 	}
 	if fsrv.fileSystem == nil {
 		fsrv.fileSystem = osFS{}
@@ -244,7 +244,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
 		zap.String("result", filename))
 
 	// get information about the file
-	info, err := fsrv.fileSystem.Stat(filename)
+	info, err := fs.Stat(fsrv.fileSystem, filename)
 	if err != nil {
 		err = fsrv.mapDirOpenError(err, filename)
 		if errors.Is(err, fs.ErrNotExist) {
@@ -270,7 +270,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
 				continue
 			}
 
-			indexInfo, err := fsrv.fileSystem.Stat(indexPath)
+			indexInfo, err := fs.Stat(fsrv.fileSystem, indexPath)
 			if err != nil {
 				continue
 			}
@@ -350,7 +350,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
 			continue
 		}
 		compressedFilename := filename + precompress.Suffix()
-		compressedInfo, err := fsrv.fileSystem.Stat(compressedFilename)
+		compressedInfo, err := fs.Stat(fsrv.fileSystem, compressedFilename)
 		if err != nil || compressedInfo.IsDir() {
 			fsrv.logger.Debug("precompressed file not accessible", zap.String("filename", compressedFilename), zap.Error(err))
 			continue
@@ -490,7 +490,7 @@ func (fsrv *FileServer) mapDirOpenError(originalErr error, name string) error {
 		if parts[i] == "" {
 			continue
 		}
-		fi, err := fsrv.fileSystem.Stat(strings.Join(parts[:i+1], separator))
+		fi, err := fs.Stat(fsrv.fileSystem, strings.Join(parts[:i+1], separator))
 		if err != nil {
 			return originalErr
 		}
@@ -613,13 +613,13 @@ func (wr statusOverrideResponseWriter) WriteHeader(int) {
 	wr.ResponseWriter.WriteHeader(wr.code)
 }
 
-// osFS is a simple fs.StatFS implementation that uses the local
+// osFS is a simple fs.FS implementation that uses the local
 // file system. (We do not use os.DirFS because we do our own
 // rooting or path prefixing without being constrained to a single
 // root folder. The standard os.DirFS implementation is problematic
 // since roots can be dynamic in our application.)
 //
-// osFS also implements fs.GlobFS, fs.ReadDirFS, and fs.ReadFileFS.
+// osFS also implements fs.StatFS, fs.GlobFS, fs.ReadDirFS, and fs.ReadFileFS.
 type osFS struct{}
 
 func (osFS) Open(name string) (fs.File, error)          { return os.Open(name) }
@@ -640,6 +640,7 @@ var (
 	_ caddy.Provisioner           = (*FileServer)(nil)
 	_ caddyhttp.MiddlewareHandler = (*FileServer)(nil)
 
+	_ fs.StatFS     = (*osFS)(nil)
 	_ fs.GlobFS     = (*osFS)(nil)
 	_ fs.ReadDirFS  = (*osFS)(nil)
 	_ fs.ReadFileFS = (*osFS)(nil)