netbirdio/netbird · warning

artifact private key must be provided via %s environment var

Error message

artifact private key must be provided via %s environment variable or --artifact-key-file flag

What it means

sign-artifact found no artifact private key: the NB_ARTIFACT_PRIV_KEY environment variable is empty/unset AND --artifact-key-file is empty. This is a pure configuration error raised before any file or cryptographic operation.

Source

Thrown at client/cmd/signer/artifactsign.go:131

func handleSignArtifact(cmd *cobra.Command, privKeyFile, artifactFile string) error {
	cmd.Println("🖋️  Signing artifact...")

	// Load private key from env var or file
	var privKeyPEM []byte
	var err error

	if envKey := os.Getenv(envArtifactPrivateKey); envKey != "" {
		// Use key from environment variable
		privKeyPEM = []byte(envKey)
	} else if privKeyFile != "" {
		// Fall back to file
		privKeyPEM, err = os.ReadFile(privKeyFile)
		if err != nil {
			return fmt.Errorf("read private key file: %w", err)
		}
	} else {
		return fmt.Errorf("artifact private key must be provided via %s environment variable or --artifact-key-file flag", envArtifactPrivateKey)
	}

	privateKey, err := reposign.ParseArtifactKey(privKeyPEM)
	if err != nil {
		return fmt.Errorf("failed to parse artifact private key: %w", err)
	}

	artifactData, err := os.ReadFile(artifactFile)
	if err != nil {
		return fmt.Errorf("read artifact file: %w", err)
	}

	signature, err := reposign.SignData(privateKey, artifactData)
	if err != nil {
		return fmt.Errorf("sign artifact: %w", err)
	}

	sigFile := artifactFile + ".sig"

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Pass --artifact-key-file <path> to the artifact private key from create-artifact-key
  2. Or export NB_ARTIFACT_PRIV_KEY containing the PEM (single-line-friendly secret) in CI
  3. Verify the secret injection: print ${#NB_ARTIFACT_PRIV_KEY} (length only, never the value)

Example fix

# before
sign-artifact --artifact-file app.tar.gz
# after
NB_ARTIFACT_PRIV_KEY="$KEY_PEM" sign-artifact --artifact-file app.tar.gz
# or
sign-artifact --artifact-key-file artifact.key --artifact-file app.tar.gz
Defensive patterns

Strategy: validation

Validate before calling

const envArtifactPrivateKey = "NB_ARTIFACT_PRIV_KEY"
hasKey := os.Getenv(envArtifactPrivateKey) != "" || privKeyFile != ""
if !hasKey {
    return fmt.Errorf("configure %s or --artifact-key-file before signing", envArtifactPrivateKey)
}

Prevention

When it happens

Trigger: Invoking sign-artifact with only --artifact-file; setting the env var to an empty string (which counts as unset in this code path); CI secret not injected so NB_ARTIFACT_PRIV_KEY is missing from the environment.

Common situations: CI job where the signing secret was not configured or renamed; local shell where the export was forgotten; secret injected as empty after masking.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/2f1dc214297a93d0. Report an issue: GitHub.