slackhq/nebula · error

error while reading ca-key: %s

Error message

error while reading ca-key: %s

What it means

signCert reads the CA private key via readInput("ca-key", *sf.caKeyPath, &claims) and wraps any read failure with this message. It means the CA key file (or stdin payload) could not be loaded at all — before any decryption is attempted — so signing cannot proceed.

Source

Thrown at cmd/nebula-cert/sign.go:139

	); err != nil {
		return err
	}
	if err := reserveOutputs(&claims,
		"out-key", *sf.outKeyPath,
		"out-crt", *sf.outCertPath,
		"out-qr", *sf.outQRPath,
	); err != nil {
		return err
	}

	var curve cert.Curve
	var caKey []byte

	if !isP11 {
		var rawCAKey []byte
		rawCAKey, err = readInput("ca-key", *sf.caKeyPath, &claims)
		if err != nil {
			return fmt.Errorf("error while reading ca-key: %s", err)
		}

		// naively attempt to decode the private key as though it is not encrypted
		caKey, _, curve, err = cert.UnmarshalSigningPrivateKeyFromPEM(rawCAKey)
		if errors.Is(err, cert.ErrPrivateKeyEncrypted) {
			var passphrase []byte
			passphrase = []byte(os.Getenv("NEBULA_CA_PASSPHRASE"))
			if len(passphrase) == 0 {
				// ask for a passphrase until we get one
				for i := 0; i < 5; i++ {
					errOut.Write([]byte("Enter passphrase: "))
					passphrase, err = pr.ReadPassword()

					if errors.Is(err, ErrNoTerminal) {
						return fmt.Errorf("ca-key is encrypted and must be decrypted interactively")
					} else if err != nil {
						return fmt.Errorf("error reading password: %s", err)
					}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Check the file exists at the -ca-key path (ls -l)
  2. Fix read permissions on the CA key (chmod/chown or run as the owning user)
  3. Supply the key on stdin when using stdio mode
  4. Point -ca-key at the correct original CA key rather than a public/derived file

Example fix

// before
nebula-cert sign -ca-key ./ca.key ...   # file actually at ./pki/ca.key
// after
nebula-cert sign -ca-key ./pki/ca.key ...
Defensive patterns

Strategy: validation

Validate before calling

st, err := os.Stat(*sf.caKeyPath)
if err != nil { return fmt.Errorf("ca-key missing: %w", err) }
if st.IsDir() || st.Size() == 0 { return fmt.Errorf("ca-key %q is empty", *sf.caKeyPath) }
if f, err := os.Open(*sf.caKeyPath); err == nil { f.Close() }

Try / catch

if err := signCert(args, out, errOut, StdinPasswordReader{}); err != nil {
    if strings.HasPrefix(err.Error(), "error while reading ca-key") {
        log.Fatalf("check -ca-key %q exists and is readable: %v", *sf.caKeyPath, err)
    }
}

Prevention

When it happens

Trigger: `nebula-cert sign -ca-key /path/ca.key ...` where the ca-key file is missing, unreadable (permissions), empty, or in stdio mode the key was not provided on stdin

Common situations: wrong -ca-key path; key file lost or not copied to the signing host; permissions changed after provisioning; running in CI without piping the key into stdin

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/9a501943d6211e7b. Report an issue: GitHub.