cloudflare/cloudflared · error

could not write token to configuration directory: %w

Error message

could not write token to configuration directory: %w

What it means

In token-based `cloudflared service install` on Linux, after creating the service config directory cloudflared writes the tunnel token there via writeTokenToConfigDir. If that write fails for any reason, installLinuxService aborts and wraps the failure with this message; the underlying cause (from error 115's chain) is preserved via %w. A deferred removeTokenFile cleans up the partial directory.

Source

Thrown at cmd/cloudflared/linux_service.go:287

		// no config exists).
		if extraArgs, err = buildArgsForConfig(c, log); err != nil {
			return err
		}
	} else {
		// If passed one argument e.g., "$ cloudflared service install <token>"
		// write the token to the config directory and install the service
		// using --token-file pointing to that file. This is the quick setup
		// the tunnel UI suggests.

		// Ensure token file is removed if install fails
		defer func() {
			if err != nil {
				removeTokenFile(serviceConfigDir, log)
			}
		}()

		if err = writeTokenToConfigDir(c, serviceConfigDir); err != nil {
			return fmt.Errorf("could not write token to configuration directory: %w", err)
		}

		extraArgs = buildArgsForTokenFile(serviceConfigDir)
	}

	templateArgs.ExtraArgs = extraArgs

	// Check if the "no update flag" is set
	autoUpdate := !c.IsSet(noUpdateServiceFlag.Name)

	switch {
	case inits.IsSystemd():
		log.Info().Msgf("Using Systemd")
		err = installSystemd(&templateArgs, autoUpdate, log)
	case inits.IsOpenRC():
		log.Info().Msgf("Using OpenRC")
		err = installOpenRC(&templateArgs, autoUpdate)
	default:

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Re-run the install with elevated privileges: `sudo cloudflared service install --token <token>` — /etc/cloudflared typically requires root.
  2. Inspect the wrapped underlying error in the output (permission denied vs no space) and address it specifically.
  3. Verify the config directory is writable: `ls -ld /etc/cloudflared && sudo -u <user> touch /etc/cloudflared/.probe`.
  4. Ensure the filesystem is writable and has free space (df -h; mount).
  5. As a fallback, place the token file manually and run service install pointing at it, or run the tunnel in the foreground with --token.

Example fix

// before
cloudflared service install --token <token>
// error: could not write token to configuration directory
// after
sudo cloudflared service install --token <token>
Defensive patterns

Strategy: validation

Validate before calling

// preflight before token-based service install
if os.Geteuid() != 0 {
	return errors.New("token-based service install requires root to write /etc/cloudflared")
}
if unix.Access("/etc", unix.W_OK) != nil {
	return errors.New("/etc is not writable (read-only fs?)")
}

Type guard

func tokenWritablePreflight(dir string) bool {
	return os.Geteuid() == 0 && unix.Access(filepath.Dir(dir), unix.W_OK) == nil
}

Try / catch

if err := writeTokenToConfigDir(ctx, dir); err != nil {
	var pe *fs.PathError
	if errors.As(err, &pe) && errors.Is(pe.Err, os.ErrPermission) {
		return fmt.Errorf("re-run with sudo: %w", err)
	}
	return fmt.Errorf("could not write token to configuration directory: %w", err)
}

Prevention

When it happens

Trigger: Running `cloudflared service install --token <token>` when the token cannot be written to /etc/cloudflared (or the chosen config dir): permission denied for the non-root user, read-only filesystem, disk full, or directory creation/write failure.

Common situations: Forgetting sudo/root before service install (system config dir requires root); /etc on a read-only root filesystem in immutable containers; full disk on small VPS instances; SELinux policies blocking writes to /etc/cloudflared.

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/519d202d6f33299e. Report an issue: GitHub.