cloudflare/cloudflared · error

configuration file %s must contain entries for the tunnel to

Error message

configuration file %s must contain entries for the tunnel to run and its associated credentials (tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE)

What it means

Thrown by buildArgsForConfig in cmd/cloudflared/linux_service.go when installing cloudflared as a Linux service. Before the service can run autonomously, the config file must name the tunnel (TunnelID) and its credentials file (credentials-file). If either entry is missing or empty, service installation is aborted because the systemd/OpenRC unit would launch a tunnel it cannot identify or authenticate.

Source

Thrown at cmd/cloudflared/linux_service.go:332

}

func buildArgsForConfig(c *cli.Context, log *zerolog.Logger) ([]string, error) {
	if err := ensureConfigDirExists(serviceConfigDir); err != nil {
		return nil, err
	}

	src, _, err := config.ReadConfigFile(c, log)
	if err != nil {
		return nil, err
	}

	// can't use context because this command doesn't define "credentials-file" flag
	configPresent := func(s string) bool {
		val, err := src.String(s)
		return err == nil && val != ""
	}
	if src.TunnelID == "" || !configPresent(tunnel.CredFileFlag) {
		return nil, fmt.Errorf("configuration file %s must contain entries for the tunnel to run and its associated credentials (tunnel: TUNNEL-UUID, credentials-file: CREDENTIALS-FILE)", src.Source())
	}
	if src.Source() != serviceConfigPath {
		if exists, err := config.FileExists(serviceConfigPath); err != nil || exists {
			return nil, fmt.Errorf("possible conflicting configuration in %[1]s and %[2]s. Either remove %[2]s or run `cloudflared --config %[2]s service install`", src.Source(), serviceConfigPath)
		}

		if err := copyFile(src.Source(), serviceConfigPath); err != nil {
			return nil, fmt.Errorf("failed to copy %s to %s: %w", src.Source(), serviceConfigPath, err)
		}
	}

	return []string{
		"--config", "/etc/cloudflared/config.yml", "tunnel", "run",
	}, nil
}

func installSystemd(templateArgs *ServiceTemplateArgs, autoUpdate bool, log *zerolog.Logger) error {
	var systemdTemplates []ServiceTemplate

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Add `tunnel: <TUNNEL-UUID>` and `credentials-file: /path/to/<UUID>.json` to the config file passed to `cloudflared service install`.
  2. Alternatively install with a token: `cloudflared service install <TOKEN>` for remotely-managed tunnels.
  3. Verify the config file being picked up (check the path in the error message) — use `cloudflared --config /path/config.yml tunnel ingress validate` to confirm entries parse.
  4. Re-run `cloudflared --config /path/config.yml service install` after fixing the file.

Example fix

// before: config.yml
// ingress:
//   - hostname: app.example.com
//     service: http://localhost:8080

// after: config.yml
// tunnel: 6ff42ae2-765d-4adf-8336-94d036a6e840
// credentials-file: /etc/cloudflared/6ff42ae2-765d-4adf-8336-94d036a6e840.json
// ingress:
//   - hostname: app.example.com
//     service: http://localhost:8080
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate config before service install
cfg, err := config.LoadConfig(configPath)
if err != nil {
    return err
}
if cfg.TunnelID == "" {
    return fmt.Errorf("config %s is missing 'tunnel:' entry required for service install", configPath)
}
if cfg.CredFileFlag == "" || !config.FileExists(cfg.CredFileFlag) {
    return fmt.Errorf("config %s is missing a valid 'credentials-file:' entry", configPath)
}

Try / catch

// Go
cmd := exec.Command("cloudflared", "--config", configPath, "service", "install")
out, err := cmd.CombinedOutput()
if err != nil && strings.Contains(string(out), "must contain entries for the tunnel") {
    // add tunnel/credentials-file keys to the config or use token-based install
    return fmt.Errorf("config incomplete for service install: %s", out)
}

Prevention

When it happens

Trigger: Running `cloudflared service install` where the effective config source (flag --config file or token-based config) has src.TunnelID == "" or no non-empty value for tunnel.CredFileFlag. Typical when the config file lacks `tunnel:` and/or `credentials-file:` keys, or only `ingress:` rules are present.

Common situations: Users write a config with only ingress rules and try to install it as a service; migrating from `cloudflared tunnel run` (flag-based) to service install without adding tunnel/credentials-file keys; copying an example config that omits credentials; using a remotely-managed tunnel token but an incomplete local config file.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/2c8b8e1e588e280c. Report an issue: GitHub.