caddyserver/caddy · error

starting caddy administration endpoint: %v

Error message

starting caddy administration endpoint: %v

What it means

When a config change alters admin endpoint settings, run() calls replaceLocalAdminServer to tear down the old admin listener and bind the new one. Any failure — the new address cannot be parsed/bound, port in use, permission denied — is wrapped as 'starting caddy administration endpoint'. Because this happens inside the load, the whole config change fails and the old state is restored.

Source

Thrown at caddy.go:568

			newCfg.storage = stor
		}

		if newCfg.storage == nil {
			newCfg.storage = DefaultStorage
		}
		certmagic.Default.Storage = newCfg.storage

		return nil
	}()
	if err != nil {
		return ctx, err
	}

	// start the admin endpoint (and stop any prior one)
	if replaceAdminServer {
		err = replaceLocalAdminServer(newCfg, ctx)
		if err != nil {
			return ctx, fmt.Errorf("starting caddy administration endpoint: %v", err)
		}
	}

	// Load and Provision each app and their submodules
	err = func() error {
		for appName := range newCfg.AppsRaw {
			if _, err := ctx.App(appName); err != nil {
				return err
			}
		}
		return nil
	}()
	return ctx, err
}

// ProvisionContext creates a new context from the configuration and provisions storage
// and app modules.
// The function is intended for testing and advanced use cases only, typically `Run` should be

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Check the wrapped error — it names the bind failure and address.
  2. Free the target port or pick another one; for unix sockets, mkdir -p the parent dir and check permissions.
  3. For privileged ports grant cap_net_bind_service or run from systemd with the capability.
  4. Keep the admin address stable across config loads unless a change is really needed.

Example fix

// before
"admin": { "listen": "unix//run/caddy/admin.sock" }  // /run/caddy missing

// after (ensure dir exists)
mkdir -p /run/caddy && chown caddy /run/caddy  # then reload
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight the admin bind before loading a config that changes it.
if cfg.Admin.Listen != "" {
    na, err := caddy.ParseNetworkAddress(cfg.Admin.Listen)
    if err != nil || na.PortRangeSize() != 1 { return errors.New("bad admin address") }
    ln, err := net.Listen(na.Network, na.JoinHostPort(0, 0))
    if err != nil { return fmt.Errorf("admin bind would fail: %w", err) }
    ln.Close()
}

Prevention

When it happens

Trigger: Loading a config whose admin.listen changes to an address already bound by another process or the current admin server in a way that can't be transitioned; binding a privileged port without capability; unix socket path whose directory does not exist; remote admin ('remote_admin') TLS material being invalid.

Common situations: Repointing admin to a unix socket with a missing /run/caddy directory; another service squatting on the target port; SELinux denying the socket bind; changing admin origin/host to an interface Caddy cannot bind.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/fcad007518546d40. Report an issue: GitHub.