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
- Pass --artifact-key-file <path> to the artifact private key from create-artifact-key
- Or export NB_ARTIFACT_PRIV_KEY containing the PEM (single-line-friendly secret) in CI
- 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
- Assert the CI secret is injected by checking its length, never its value
- Document one canonical way to supply the key (env secret) and stick to it
- Fail job setup early on missing secrets rather than mid-signing
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
- read private key file: %w
- address must be in [unix|tcp|npipe]://[path|host:port|name]
- unsupported daemon address protocol: %v
- --expiration must be a positive duration (e.g., 720h, 365d,
- failed to create artifact key: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/2f1dc214297a93d0.
Report an issue: GitHub.