kubernetes/kops · error

error reading public key %q: %w

Error message

error reading public key %q: %w

What it means

buildHostData reads the target's SSH public key (default /root/.ssh/id_ed25519.pub style path) over SSH. If the read fails with any error other than fs.ErrNotExist — e.g. permission denied, connection reset mid-transfer — the command wraps it as "error reading public key %q".

Source

Thrown at pkg/commands/toolbox_enroll.go:179

	}

	if err := enrollHost(ctx, fullInstanceGroup, bootstrapData, restConfig, hostData, sshTarget); err != nil {
		return err
	}

	return nil
}

// buildHostData builds an instance of the Host CRD, based on information in the options and by SSHing to the target host.
func buildHostData(ctx context.Context, sshTarget *SSHHost, options *ToolboxEnrollOptions) (*v1alpha2.Host, error) {
	publicKeyPath := "/etc/kubernetes/kops/pki/machine/public.pem"

	publicKeyBytes, err := sshTarget.readFile(ctx, publicKeyPath)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			publicKeyBytes = nil
		} else {
			return nil, fmt.Errorf("error reading public key %q: %w", publicKeyPath, err)
		}
	}

	// Create the key if it doesn't exist
	publicKeyBytes = bytes.TrimSpace(publicKeyBytes)
	if len(publicKeyBytes) == 0 {
		if _, err := sshTarget.runScript(ctx, scriptCreateKey, ExecOptions{Echo: true}); err != nil {
			return nil, err
		}

		b, err := sshTarget.readFile(ctx, publicKeyPath)
		if err != nil {
			return nil, fmt.Errorf("error reading public key %q (after creation): %w", publicKeyPath, err)
		}
		publicKeyBytes = b
	}
	klog.Infof("public key is %s", string(publicKeyBytes))

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped error: fix permissions on the remote key file (`chmod 600 ~/.ssh/id_ed25519; chmod 700 ~/.ssh`) or make it readable by the SSH user
  2. Pre-create a readable public key on the host, or let kops create it by ensuring the key simply does not exist (then it generates one)
  3. Verify SSH connectivity and user: `ssh -p <port> <user>@<host> 'cat <path>'`

Example fix

// on the target host, before enrolling
// before: -rw------- root root /root/.ssh/id_ed25519.pub read via non-root user
// after
chmod 755 /root/.ssh && chmod 644 /root/.ssh/id_ed25519.pub
Defensive patterns

Strategy: try-catch

Validate before calling

ssh -p "$PORT" "$USER@$HOST" 'test -r ~/.ssh/id_ed25519.pub || test ! -e ~/.ssh/id_ed25519.pub' \
  || { echo "public key exists but is not readable by SSH user"; exit 1; }

Try / catch

err := RunToolboxEnroll(ctx, f, out, opts)
if err != nil && strings.Contains(err.Error(), "error reading public key") {
    log.Printf("fix remote key permissions or SSH user; cause: %v", err)
    return err
}

Prevention

When it happens

Trigger: The remote key file exists but is unreadable by the SSH user; SFTP/SSH channel errors; the path is a directory; transient network failure during readFile.

Common situations: Enrolling hosts where the SSH user isn't root (default is root, but custom configs differ) and cannot read /root/.ssh; hardened images with restrictive permissions on .ssh; flaky networks.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/a69c41a13bb0af8f. Report an issue: GitHub.