{"record":{"id":"d537352d75660f66","repo":"crowdsecurity/crowdsec","slug":"missing-tls-key-file","errorCode":null,"errorMessage":"missing TLS key file","messagePattern":"missing TLS key file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/appsec/run.go","lineNumber":32,"sourceCode":"\t\"github.com/crowdsecurity/go-cs-lib/trace\"\n\n\t\"github.com/crowdsecurity/crowdsec/pkg/apiclient\"\n\t\"github.com/crowdsecurity/crowdsec/pkg/appsec\"\n\t\"github.com/crowdsecurity/crowdsec/pkg/csnet\"\n\t\"github.com/crowdsecurity/crowdsec/pkg/pipeline\"\n)\n\nfunc (w *Source) listenAndServe(ctx context.Context, t *tomb.Tomb) error {\n\tw.logger.Infof(\"%d appsec runner to start\", len(w.AppsecRunners))\n\n\tserverError := make(chan error, 2)\n\n\tstartServer := func(listener net.Listener, canTLS bool) {\n\t\tvar err error\n\n\t\tif canTLS && (w.config.CertFilePath != \"\" || w.config.KeyFilePath != \"\") {\n\t\t\tif w.config.KeyFilePath == \"\" {\n\t\t\t\tserverError <- errors.New(\"missing TLS key file\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif w.config.CertFilePath == \"\" {\n\t\t\t\tserverError <- errors.New(\"missing TLS cert file\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\terr = w.server.ServeTLS(listener, w.config.CertFilePath, w.config.KeyFilePath)\n\t\t} else {\n\t\t\terr = w.server.Serve(listener)\n\t\t}\n\n\t\tswitch {\n\t\tcase errors.Is(err, http.ErrServerClosed):\n\t\t\tbreak\n\t\tcase err != nil:\n\t\t\tserverError <- err","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/appsec/run.go#L14-L50","documentation":"The appsec HTTP server can be started with TLS. TLS is only attempted when at least one of cert_file/key_file is set; if key_file is empty while cert_file is set, ServeTLS cannot be configured and the server startup goroutine emits this error on serverError.","triggerScenarios":"In run(), startServer is called with canTLS and w.config.CertFilePath set but w.config.KeyFilePath empty — the config supplied cert_file but no key_file.","commonSituations":"appsec acquisition TLS stanza where the user filled in cert_file but forgot key_file, or a secret-mount/env substitution left the key path empty in containers.","solutions":["Add the key_file path next to cert_file in the appsec datasource config","Verify the key file actually exists and the path resolves in the container/mount","If you don't want TLS, remove cert_file so the server starts in plain HTTP mode"],"exampleFix":"// before (acquisition.yaml)\nsource: appsec\n cert_file: /etc/ssl/crowdsec/tls.cert\n// after\nsource: appsec\n cert_file: /etc/ssl/crowdsec/tls.cert\n key_file: /etc/ssl/crowdsec/tls.key","handlingStrategy":"validation","validationCode":"if (cfg.CertFilePath != \"\" || cfg.KeyFilePath != \"\") && cfg.KeyFilePath == \"\" {\n    return errors.New(\"cert_file set without key_file\")\n}","typeGuard":null,"tryCatchPattern":"go func() {\n    if err := <-serverError; err != nil {\n        if strings.Contains(err.Error(), \"missing TLS\") { /* fix cert/key pair in config */ }\n    }\n}()","preventionTips":["Always configure cert_file and key_file as a pair","Verify both files exist and are readable at startup","Remove both keys if plain HTTP is intended"],"tags":["appsec","tls","configuration","https"],"backgroundTag":"missing-required-config-field","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}