cloudflare/cloudflared · error

failed to copy %s to %s: %w

Error message

failed to copy %s to %s: %w

What it means

Wraps a failure from copyFile when buildArgsForConfig copies the user's config to the canonical service path /etc/cloudflared/config.yml during service installation. If the file cannot be read or written (permissions, missing source, disk full), install aborts with the source and destination paths in the message.

Source

Thrown at cmd/cloudflared/linux_service.go:340

	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
	if autoUpdate {
		systemdTemplates = []ServiceTemplate{
			systemdAllTemplates[cloudflaredService],
			systemdAllTemplates[cloudflaredUpdateService],
			systemdAllTemplates[cloudflaredUpdateTimer],
		}
	} else {
		systemdTemplates = []ServiceTemplate{

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Run the install with root privileges: `sudo cloudflared --config <config> service install`.
  2. Ensure the source config file is readable by root (check permissions/ownership with ls -l).
  3. Verify /etc/cloudflared exists and is writable (sudo mkdir -p /etc/cloudflared).
  4. Check disk space and any mandatory access control (SELinux) denials in audit logs.
  5. As a workaround, manually copy the config: `sudo cp <config> /etc/cloudflared/config.yml` then install using that path.

Example fix

# before
$ cloudflared --config ~/myconfig.yml service install
# ERROR: failed to copy /home/user/myconfig.yml to /etc/cloudflared/config.yml

# after
$ sudo cloudflared --config ~/myconfig.yml service install
Defensive patterns

Strategy: validation

Validate before calling

// Go: preflight write-access check before service install
if os.Geteuid() != 0 {
    return fmt.Errorf("service install requires root; re-run with sudo")
}
if err := os.MkdirAll("/etc/cloudflared", 0755); err != nil {
    return fmt.Errorf("cannot create /etc/cloudflared: %w", err)
}
f, err := os.OpenFile("/etc/cloudflared/.write-test", os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
    return fmt.Errorf("/etc/cloudflared not writable: %w", err)
}
f.Close()
os.Remove("/etc/cloudflared/.write-test")

Try / catch

// Go
out, err := exec.Command("cloudflared", "--config", cfg, "service", "install").CombinedOutput()
if err != nil && strings.Contains(string(out), "failed to copy") {
    // fall back to manual copy: sudo cp cfg /etc/cloudflared/config.yml then reinstall
}

Prevention

When it happens

Trigger: `cloudflared service install` with a --config file whose source path differs from serviceConfigPath, where copyFile(src.Source(), "/etc/cloudflared/config.yml") fails — unwritable /etc/cloudflared directory (not running as root), unreadable source file, or I/O error.

Common situations: Running service install without sudo so the /etc/cloudflared directory is not writable; config file in a home directory with restrictive permissions; read-only or full filesystem; SELinux/AppArmor blocking writes to /etc.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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