diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go
index 7afcc9ef1..4622af2da 100644
--- a/modules/caddyhttp/fileserver/caddyfile.go
+++ b/modules/caddyhttp/fileserver/caddyfile.go
@@ -17,9 +17,9 @@ package fileserver
 import (
 	"encoding/json"
 
-	"github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite"
 	"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
 	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
+	"github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite"
 )
 
 func init() {
@@ -71,11 +71,6 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
 		}
 	}
 
-	// if no root was configured explicitly, use site root
-	if fsrv.Root == "" {
-		fsrv.Root = "{http.var.root}"
-	}
-
 	// hide the Caddyfile (and any imported Caddyfiles)
 	if configFiles := h.Caddyfiles(); len(configFiles) > 0 {
 		for _, file := range configFiles {
@@ -104,7 +99,6 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
 
 	matcherSet := map[string]json.RawMessage{
 		"file": h.JSON(MatchFile{
-			Root:     "{http.var.root}",
 			TryFiles: try,
 		}, nil),
 	}
diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go
index b09125045..99e217ed6 100644
--- a/modules/caddyhttp/fileserver/matcher.go
+++ b/modules/caddyhttp/fileserver/matcher.go
@@ -18,6 +18,7 @@ import (
 	"fmt"
 	"net/http"
 	"os"
+	"path"
 	"time"
 
 	"github.com/caddyserver/caddy/v2"
@@ -87,8 +88,13 @@ func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
 			}
 		}
 	}
+	return nil
+}
+
+// Provision sets up m's defaults.
+func (m *MatchFile) Provision(_ caddy.Context) error {
 	if m.Root == "" {
-		m.Root = "{http.var.root}"
+		m.Root = "{http.vars.root}"
 	}
 	return nil
 }
@@ -141,7 +147,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
 	switch m.TryPolicy {
 	case "", tryPolicyFirstExist:
 		for _, f := range m.TryFiles {
-			suffix := repl.ReplaceAll(f, "")
+			suffix := path.Clean(repl.ReplaceAll(f, ""))
 			fullpath := sanitizedPathJoin(root, suffix)
 			if fileExists(fullpath) {
 				return suffix, fullpath, true
@@ -153,7 +159,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
 		var largestFilename string
 		var largestSuffix string
 		for _, f := range m.TryFiles {
-			suffix := repl.ReplaceAll(f, "")
+			suffix := path.Clean(repl.ReplaceAll(f, ""))
 			fullpath := sanitizedPathJoin(root, suffix)
 			info, err := os.Stat(fullpath)
 			if err == nil && info.Size() > largestSize {
@@ -169,7 +175,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
 		var smallestFilename string
 		var smallestSuffix string
 		for _, f := range m.TryFiles {
-			suffix := repl.ReplaceAll(f, "")
+			suffix := path.Clean(repl.ReplaceAll(f, ""))
 			fullpath := sanitizedPathJoin(root, suffix)
 			info, err := os.Stat(fullpath)
 			if err == nil && (smallestSize == 0 || info.Size() < smallestSize) {
@@ -185,7 +191,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
 		var recentFilename string
 		var recentSuffix string
 		for _, f := range m.TryFiles {
-			suffix := repl.ReplaceAll(f, "")
+			suffix := path.Clean(repl.ReplaceAll(f, ""))
 			fullpath := sanitizedPathJoin(root, suffix)
 			info, err := os.Stat(fullpath)
 			if err == nil &&
diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go
index cdac453ca..cfb79f8a6 100644
--- a/modules/caddyhttp/fileserver/staticfiles.go
+++ b/modules/caddyhttp/fileserver/staticfiles.go
@@ -57,6 +57,10 @@ func (FileServer) CaddyModule() caddy.ModuleInfo {
 
 // Provision sets up the static files responder.
 func (fsrv *FileServer) Provision(ctx caddy.Context) error {
+	if fsrv.Root == "" {
+		fsrv.Root = "{http.vars.root}"
+	}
+
 	if fsrv.IndexNames == nil {
 		fsrv.IndexNames = defaultIndexNames
 	}
diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go
index 2ddefd02e..7fc8aea2e 100644
--- a/modules/caddyhttp/matchers.go
+++ b/modules/caddyhttp/matchers.go
@@ -22,7 +22,6 @@ import (
 	"net/http"
 	"net/textproto"
 	"net/url"
-	"path"
 	"path/filepath"
 	"regexp"
 	"strings"
@@ -151,12 +150,13 @@ func (MatchPath) CaddyModule() caddy.ModuleInfo {
 // Match returns true if r matches m.
 func (m MatchPath) Match(r *http.Request) bool {
 	for _, matchPath := range m {
-		compare := r.URL.Path
+		// as a special case, if the first character is a
+		// wildcard, treat it as a quick suffix match
 		if strings.HasPrefix(matchPath, "*") {
-			compare = path.Base(compare)
+			return strings.HasSuffix(r.URL.Path, matchPath[1:])
 		}
 		// can ignore error here because we can't handle it anyway
-		matches, _ := filepath.Match(matchPath, compare)
+		matches, _ := filepath.Match(matchPath, r.URL.Path)
 		if matches {
 			return true
 		}
diff --git a/modules/caddyhttp/replacer.go b/modules/caddyhttp/replacer.go
index cc29789b0..f7f69a4e1 100644
--- a/modules/caddyhttp/replacer.go
+++ b/modules/caddyhttp/replacer.go
@@ -173,6 +173,6 @@ const (
 	cookieReplPrefix     = "http.request.cookie."
 	hostLabelReplPrefix  = "http.request.host.labels."
 	pathPartsReplPrefix  = "http.request.uri.path."
-	varsReplPrefix       = "http.var."
+	varsReplPrefix       = "http.vars."
 	respHeaderReplPrefix = "http.response.header."
 )
diff --git a/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go b/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
index 0368fded7..66779e429 100644
--- a/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
+++ b/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
@@ -79,7 +79,7 @@ func (Transport) CaddyModule() caddy.ModuleInfo {
 // Provision sets up t.
 func (t *Transport) Provision(_ caddy.Context) error {
 	if t.Root == "" {
-		t.Root = "{http.var.root}"
+		t.Root = "{http.vars.root}"
 	}
 	return nil
 }
diff --git a/modules/caddyhttp/templates/caddyfile.go b/modules/caddyhttp/templates/caddyfile.go
index d948da060..1336a6048 100644
--- a/modules/caddyhttp/templates/caddyfile.go
+++ b/modules/caddyhttp/templates/caddyfile.go
@@ -53,10 +53,5 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
 			}
 		}
 	}
-
-	if t.IncludeRoot == "" {
-		t.IncludeRoot = "{http.var.root}"
-	}
-
 	return t, nil
 }
diff --git a/modules/caddyhttp/templates/templates.go b/modules/caddyhttp/templates/templates.go
index 1cd347cf4..05a2f633a 100644
--- a/modules/caddyhttp/templates/templates.go
+++ b/modules/caddyhttp/templates/templates.go
@@ -50,6 +50,9 @@ func (t *Templates) Provision(ctx caddy.Context) error {
 	if t.MIMETypes == nil {
 		t.MIMETypes = defaultMIMETypes
 	}
+	if t.IncludeRoot == "" {
+		t.IncludeRoot = "{http.vars.root}"
+	}
 	return nil
 }