diff --git a/cmd/commandfuncs.go b/cmd/commandfuncs.go
index 2adf95bb3..5c20c22ff 100644
--- a/cmd/commandfuncs.go
+++ b/cmd/commandfuncs.go
@@ -171,6 +171,9 @@ func cmdStart(fl Flags) (int, error) {
 func cmdRun(fl Flags) (int, error) {
 	caddy.TrapSignals()
 
+	logger := caddy.Log()
+	setResourceLimits(logger)
+
 	configFlag := fl.String("config")
 	configAdapterFlag := fl.String("adapter")
 	resumeFlag := fl.Bool("resume")
@@ -196,18 +199,18 @@ func cmdRun(fl Flags) (int, error) {
 		config, err = os.ReadFile(caddy.ConfigAutosavePath)
 		if errors.Is(err, fs.ErrNotExist) {
 			// not a bad error; just can't resume if autosave file doesn't exist
-			caddy.Log().Info("no autosave file exists", zap.String("autosave_file", caddy.ConfigAutosavePath))
+			logger.Info("no autosave file exists", zap.String("autosave_file", caddy.ConfigAutosavePath))
 			resumeFlag = false
 		} else if err != nil {
 			return caddy.ExitCodeFailedStartup, err
 		} else {
 			if configFlag == "" {
-				caddy.Log().Info("resuming from last configuration",
+				logger.Info("resuming from last configuration",
 					zap.String("autosave_file", caddy.ConfigAutosavePath))
 			} else {
 				// if they also specified a config file, user should be aware that we're not
 				// using it (doing so could lead to data/config loss by overwriting!)
-				caddy.Log().Warn("--config and --resume flags were used together; ignoring --config and resuming from last configuration",
+				logger.Warn("--config and --resume flags were used together; ignoring --config and resuming from last configuration",
 					zap.String("autosave_file", caddy.ConfigAutosavePath))
 			}
 		}
@@ -225,7 +228,7 @@ func cmdRun(fl Flags) (int, error) {
 	if pidfileFlag != "" {
 		err := caddy.PIDFile(pidfileFlag)
 		if err != nil {
-			caddy.Log().Error("unable to write PID file",
+			logger.Error("unable to write PID file",
 				zap.String("pidfile", pidfileFlag),
 				zap.Error(err))
 		}
@@ -236,7 +239,7 @@ func cmdRun(fl Flags) (int, error) {
 	if err != nil {
 		return caddy.ExitCodeFailedStartup, fmt.Errorf("loading initial config: %v", err)
 	}
-	caddy.Log().Info("serving initial configuration")
+	logger.Info("serving initial configuration")
 
 	// if we are to report to another process the successful start
 	// of the server, do so now by echoing back contents of stdin
@@ -272,15 +275,15 @@ func cmdRun(fl Flags) (int, error) {
 	switch runtime.GOOS {
 	case "windows":
 		if os.Getenv("HOME") == "" && os.Getenv("USERPROFILE") == "" && !hasXDG {
-			caddy.Log().Warn("neither HOME nor USERPROFILE environment variables are set - please fix; some assets might be stored in ./caddy")
+			logger.Warn("neither HOME nor USERPROFILE environment variables are set - please fix; some assets might be stored in ./caddy")
 		}
 	case "plan9":
 		if os.Getenv("home") == "" && !hasXDG {
-			caddy.Log().Warn("$home environment variable is empty - please fix; some assets might be stored in ./caddy")
+			logger.Warn("$home environment variable is empty - please fix; some assets might be stored in ./caddy")
 		}
 	default:
 		if os.Getenv("HOME") == "" && !hasXDG {
-			caddy.Log().Warn("$HOME environment variable is empty - please fix; some assets might be stored in ./caddy")
+			logger.Warn("$HOME environment variable is empty - please fix; some assets might be stored in ./caddy")
 		}
 	}
 
diff --git a/cmd/main.go b/cmd/main.go
index c41738be0..11334cb21 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -69,30 +69,6 @@ func Main() {
 		os.Exit(caddy.ExitCodeFailedStartup)
 	}
 
-	logger := caddy.Log()
-
-	// Configure the maximum number of CPUs to use to match the Linux container quota (if any)
-	// See https://pkg.go.dev/runtime#GOMAXPROCS
-	undo, err := maxprocs.Set(maxprocs.Logger(logger.Sugar().Infof))
-	defer undo()
-	if err != nil {
-		caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err))
-	}
-
-	// Configure the maximum memory to use to match the Linux container quota (if any) or system memory
-	// See https://pkg.go.dev/runtime/debug#SetMemoryLimit
-	_, _ = memlimit.SetGoMemLimitWithOpts(
-		memlimit.WithLogger(
-			slog.New(zapslog.NewHandler(logger.Core())),
-		),
-		memlimit.WithProvider(
-			memlimit.ApplyFallback(
-				memlimit.FromCgroup,
-				memlimit.FromSystem,
-			),
-		),
-	)
-
 	if err := defaultFactory.Build().Execute(); err != nil {
 		var exitError *exitError
 		if errors.As(err, &exitError) {
@@ -488,6 +464,30 @@ func printEnvironment() {
 	}
 }
 
+func setResourceLimits(logger *zap.Logger) {
+	// Configure the maximum number of CPUs to use to match the Linux container quota (if any)
+	// See https://pkg.go.dev/runtime#GOMAXPROCS
+	undo, err := maxprocs.Set(maxprocs.Logger(logger.Sugar().Infof))
+	defer undo()
+	if err != nil {
+		caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err))
+	}
+
+	// Configure the maximum memory to use to match the Linux container quota (if any) or system memory
+	// See https://pkg.go.dev/runtime/debug#SetMemoryLimit
+	_, _ = memlimit.SetGoMemLimitWithOpts(
+		memlimit.WithLogger(
+			slog.New(zapslog.NewHandler(logger.Core())),
+		),
+		memlimit.WithProvider(
+			memlimit.ApplyFallback(
+				memlimit.FromCgroup,
+				memlimit.FromSystem,
+			),
+		),
+	)
+}
+
 // StringSlice is a flag.Value that enables repeated use of a string flag.
 type StringSlice []string