diff --git a/caddy/caddymain/run.go b/caddy/caddymain/run.go
index 281f7d5ea..e83ecc173 100644
--- a/caddy/caddymain/run.go
+++ b/caddy/caddymain/run.go
@@ -188,18 +188,25 @@ func moveStorage() {
 		log.Fatalf("[ERROR] Unable to migrate certificate storage: %v\n\nPlease follow instructions at:\nhttps://github.com/mholt/caddy/issues/902#issuecomment-228876011", err)
 	}
 	// convert mixed case folder and file names to lowercase
-	filepath.Walk(string(newPath), func(path string, info os.FileInfo, err error) error {
-		// must be careful to only lowercase the base of the path, not the whole thing!!
-		base := filepath.Base(path)
-		if lowerBase := strings.ToLower(base); base != lowerBase {
-			lowerPath := filepath.Join(filepath.Dir(path), lowerBase)
-			err = os.Rename(path, lowerPath)
-			if err != nil {
-				log.Fatalf("[ERROR] Unable to lower-case: %v\n\nPlease follow instructions at:\nhttps://github.com/mholt/caddy/issues/902#issuecomment-228876011", err)
+	var done bool // walking is recursive and preloads the file names, so we must restart walk after a change until no changes
+	for !done {
+		done = true
+		filepath.Walk(string(newPath), func(path string, info os.FileInfo, err error) error {
+			// must be careful to only lowercase the base of the path, not the whole thing!!
+			base := filepath.Base(path)
+			if lowerBase := strings.ToLower(base); base != lowerBase {
+				lowerPath := filepath.Join(filepath.Dir(path), lowerBase)
+				err = os.Rename(path, lowerPath)
+				if err != nil {
+					log.Fatalf("[ERROR] Unable to lower-case: %v\n\nPlease follow instructions at:\nhttps://github.com/mholt/caddy/issues/902#issuecomment-228876011", err)
+				}
+				// terminate traversal and restart since Walk needs the updated file list with new file names
+				done = false
+				return errors.New("start over")
 			}
-		}
-		return nil
-	})
+			return nil
+		})
+	}
 }
 
 // setVersion figures out the version information