cloudflare/cloudflared · error
failed to copy to
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.
Solutions
- Run the install with root privileges: `sudo cloudflared --config <config> service install`.
- Ensure the source config file is readable by root (check permissions/ownership with ls -l).
- Verify /etc/cloudflared exists and is writable (sudo mkdir -p /etc/cloudflared).
- Check disk space and any mandatory access control (SELinux) denials in audit logs.
- 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
- Always run `cloudflared service install` with sudo/root
- Pre-create /etc/cloudflared with correct ownership (root:root, 0755)
- Ensure the source config file has read permissions for root
- Check disk space and SELinux/AppArmor denials on hosts where installs are automated
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
- error writing cert to
- chmod token file at
- configuration file must contain entries for the tunnel to…
- create config dir at
- create token file at
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/886cb177c766e65a.
Report an issue: GitHub.
Appendix: 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)