{"record":{"id":"26dd62375d19ba11","repo":"slackhq/nebula","slug":"out-key-must-be-encrypted-interactively","errorCode":null,"errorMessage":"out-key must be encrypted interactively","messagePattern":"out-key must be encrypted interactively","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/nebula-cert/ca.go","lineNumber":229,"sourceCode":"\tvar claims ioClaims\n\tif err := reserveOutputs(&claims,\n\t\t\"out-key\", *cf.outKeyPath,\n\t\t\"out-crt\", *cf.outCertPath,\n\t\t\"out-qr\", *cf.outQRPath,\n\t); err != nil {\n\t\treturn err\n\t}\n\n\tvar passphrase []byte\n\tif !isP11 && *cf.encryption {\n\t\tpassphrase = []byte(os.Getenv(\"NEBULA_CA_PASSPHRASE\"))\n\t\tif len(passphrase) == 0 {\n\t\t\tfor i := 0; i < 5; i++ {\n\t\t\t\terrOut.Write([]byte(\"Enter passphrase: \"))\n\t\t\t\tpassphrase, err = pr.ReadPassword()\n\n\t\t\t\tif err == ErrNoTerminal {\n\t\t\t\t\treturn fmt.Errorf(\"out-key must be encrypted interactively\")\n\t\t\t\t} else if err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error reading passphrase: %s\", err)\n\t\t\t\t}\n\n\t\t\t\tif len(passphrase) > 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif len(passphrase) == 0 {\n\t\t\t\treturn fmt.Errorf(\"no passphrase specified, remove -encrypt flag to write out-key in plaintext\")\n\t\t\t}\n\t\t}\n\t}\n\n\tvar curve cert.Curve\n\tvar pub, rawPriv []byte\n\tvar p11Client *pkclient.PKClient","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cmd/nebula-cert/ca.go#L211-L247","documentation":"The nebula-cert ca command, when -encrypt is given, reads a passphrase interactively from the terminal. If the passphrase reader reports ErrNoTerminal (stdin is not a TTY), the command aborts with \"out-key must be encrypted interactively\" because encrypted key output requires a human at a terminal.","triggerScenarios":"Running `nebula-cert ca -encrypt` with stdin redirected, piped, or from a non-interactive context (cron, CI, Docker without -t) so the password reader returns ErrNoTerminal on the first prompt attempt.","commonSituations":"Automating CA generation in CI pipelines, scripting nebula-cert with echo'd passphrases, running inside a container without a TTY, or using SSH without -t.","solutions":["Run the command in an interactive terminal (allocate a TTY: docker run -it, ssh -t).","Drop the -encrypt flag so the out-key is written in plaintext (then protect the file yourself).","Use a non-interactive alternative such as generating the key programmatically with the cert library and encrypting it yourself.","Check nebula-cert's version for a -quiet-passphrase/non-interactive passphrase flag if automation requires encryption."],"exampleFix":"// before (CI script, no TTY)\nnebula-cert ca -name \"ca\" -encrypt\n\n// after\ndocker exec -it ca-container nebula-cert ca -name \"ca\" -encrypt\n// or, without a TTY:\nnebula-cert ca -name \"ca\"  # plaintext out-key","handlingStrategy":"validation","validationCode":"// before invoking nebula-cert with -encrypt, ensure a TTY exists\nif fi, _ := os.Stdin.Stat(); (fi.Mode() & os.ModeCharDevice) == 0 {\n    return fmt.Errorf(\"-encrypt requires an interactive terminal\")\n}","typeGuard":null,"tryCatchPattern":"out, err := exec.Command(\"nebula-cert\", \"ca\", \"-encrypt\", ...).CombinedOutput()\nif err != nil && strings.Contains(string(out), \"out-key must be encrypted interactively\") {\n    // retry with a TTY (docker -it / ssh -t) or without -encrypt\n    return err\n}","preventionTips":["Never run nebula-cert ca -encrypt from cron/CI without a TTY.","Use docker run -it or ssh -t when container/remote execution is needed.","Drop -encrypt and secure the plaintext key file when automation is unavoidable."],"tags":["cli","tty","passphrase"],"backgroundTag":"interactive-terminal-required","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}