{"record":{"id":"5384b410c5420750","repo":"risingwavelabs/risingwave","slug":"rw-ssl-cert-and-rw-ssl-key-must-be-set-together","errorCode":null,"errorMessage":"RW_SSL_CERT and RW_SSL_KEY must be set together","messagePattern":"RW_SSL_CERT and RW_SSL_KEY must be set together","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/utils/pgwire/src/pg_protocol.rs","lineNumber":133,"sourceCode":"/// Configures TLS encryption for connections.\n#[derive(Debug, Clone)]\npub struct TlsConfig {\n    /// The path to the TLS certificate.\n    pub cert: String,\n    /// The path to the TLS key.\n    pub key: String,\n    /// Whether to enforce SSL connections (reject non-SSL clients).\n    pub enforce_ssl: bool,\n}\n\nimpl TlsConfig {\n    pub fn new_default() -> anyhow::Result<Option<Self>> {\n        let cert = std::env::var(\"RW_SSL_CERT\").ok();\n        let key = std::env::var(\"RW_SSL_KEY\").ok();\n        let enforce_ssl = env_var_is_true(\"RW_SSL_ENFORCE\");\n\n        if cert.is_some() ^ key.is_some() {\n            return Err(anyhow::anyhow!(\n                \"RW_SSL_CERT and RW_SSL_KEY must be set together\"\n            ));\n        }\n\n        if enforce_ssl && cert.is_none() {\n            return Err(anyhow::anyhow!(\n                \"RW_SSL_ENFORCE requires RW_SSL_CERT and RW_SSL_KEY to be set\"\n            ));\n        }\n\n        let (Some(cert), Some(key)) = (cert, key) else {\n            return Ok(None);\n        };\n\n        tracing::info!(\n            \"RW_SSL_CERT={}, RW_SSL_KEY={}, RW_SSL_ENFORCE={}\",\n            cert,\n            key,","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/utils/pgwire/src/pg_protocol.rs#L115-L151","documentation":"TLS configuration in `PgLseConfig/SslConfig::new_default` reads `RW_SSL_CERT` and `RW_SSL_KEY` env vars. Setting exactly one of them is a misconfiguration, so it fails fast with an anyhow error at startup. Both must be present to enable TLS.","triggerScenarios":"Starting a RisingWave node (frontend/compute) with `RW_SSL_CERT` exported but `RW_SSL_KEY` missing, or vice versa.","commonSituations":"Deployments where the cert file is mounted but the key secret was not; updating config via k8s env where one var was renamed; copy-paste of only one var in shell profiles.","solutions":["Set both `RW_SSL_CERT` and `RW_SSL_KEY` to valid file paths.","Unset the lone variable if TLS is not intended.","In Kubernetes, ensure the secret containing both cert and key is mounted and both env vars point at the mount."],"exampleFix":"// before\nRW_SSL_CERT=/certs/server.crt ./risingwave frontend\n// after\nRW_SSL_CERT=/certs/server.crt RW_SSL_KEY=/certs/server.key ./risingwave frontend","handlingStrategy":"validation","validationCode":"let cert = std::env::var(\"RW_SSL_CERT\").ok();\nlet key = std::env::var(\"RW_SSL_KEY\").ok();\nif cert.is_some() ^ key.is_some() { panic!(\"set both RW_SSL_CERT and RW_SSL_KEY or neither\"); }","typeGuard":null,"tryCatchPattern":"match SslConfig::new_default() {\n    Err(e) if e.to_string().contains(\"must be set together\") => fix_env_and_restart(),\n    other => other?,\n}","preventionTips":["Always set RW_SSL_CERT and RW_SSL_KEY together in deployment manifests.","Validate env vars in startup scripts / init containers.","Use a single secret reference generating both vars."],"tags":["rust","tls","configuration","env"],"backgroundTag":"missing-env-var","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}