Iḿ trying to reload the server settings via the webui.
this results in a message: Action failed No ECDSA key found in PEM
but it does not tell me which key is invalid making investigation hard
Expected Behavior
at lease to tell me where the error is.
Actual Behavior
Action failed No ECDSA key found in PEM
Reproduction Steps
WebUI → Actions → Reload → Server Settings
Stalwart Version
v0.16.x
Installation Method
Built from source
Database Backend
PostgreSQL
Blob Storage
S3-compatible
Search Engine
Meilisearch
Directory Backend
Internal
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
Let me look into this error to give a useful answer.
The error “No ECDSA key found in PEM” occurs during the Server Settings reload and points to a problem with one of your manually configured TLS certificate objects – specifically, the privateKey field of a Certificate object contains PEM data that does not include a valid ECDSA private key (e.g. it may be an RSA key, a malformed PEM block, a file path that can’t be read, or an environment variable reference that resolved to something unexpected).
Here is how to narrow it down:
Go to Settings > TLS > Certificates in the WebUI and open each Certificate object one by one.
Check the privateKey field of each certificate. The PEM block must begin with -----BEGIN EC PRIVATE KEY----- (or -----BEGIN PRIVATE KEY----- for PKCS#8-wrapped ECDSA keys). If you have an RSA key pair, the error message would be different – so any certificate configured with an ECDSA public cert must have a matching ECDSA private key.
If the field contains a file path (e.g. file:///etc/certs/key.pem) or an environment variable reference, verify that the path/variable is accessible to the server process and that the file actually contains the ECDSA private key.
Also check any AcmeProvider objects – the ACME account key is an ECDSA key and could be the culprit if it was not generated correctly.
Once you fix the offending certificate’s privateKey, the reload should succeed. Unfortunately the current error message does not include the certificate ID, which makes this harder than it should be – a human staff member may be able to confirm whether improved error context is planned.
That error isn’t about your TLS certificates, it’s about an OIDC provider’s signing key, so your Let’s Encrypt setup is unrelated. You have an OIDC provider configured with an EC signature algorithm (ES256/ES384) but the signature key you supplied isn’t being recognized as an EC private key.
The most common cause is key format: the parser only accepts a PKCS8 key (-----BEGIN PRIVATE KEY-----), not the traditional SEC1 -----BEGIN EC PRIVATE KEY----- form.
If your key is SEC1, convert it with openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pk8.pem and use that, or switch the algorithm to match the key you have.
That makes sense.
I have fiddled with the OIDC settings but decided to leave it for now.
Is there a way to disable OIDC again? I do not see how in the WebUI at least.
You can remove it under Settings, Authentication, OIDC Provider in the web UI: delete (or clear) that provider entry, then run Reload Settings. Once the provider carrying the bad EC key is gone, the “No ECDSA key found in PEM” error on reload goes away with it.
If you can’t spot the entry there, use the settings search for “oidc” or “openid”; the same keys can also be removed with stalwart-cli if you’d rather do it from the shell.
Sorry, my bad, the instructions were to remove an external OIDC provider but you are using the internal one. The WebUI won’t let you save the internal OIDC settings unless you provide valid encryption keys, which can be generated using openssl.
Regarding the ECSDA error, Stalwart only accepted PKCS8 keys but v0.16.12 will also allow SEC1 private keys. In the meantime, make sure you save the key as PKCS8, convert it with openssl pkcs8 -topk8 -nocrypt -in key.pem -out key.pk8.pem and use that, or switch the algorithm to match the key you actually have.
I’ve run into this issue myself. I believe OidcProvider is only partially configured. I misunderstood how to set up OIDC and meant to mess with OpenID Connect under the Directories settings tab. Because I was messing with OIDC Provider instead, I believe it became partially configured and is in an invalid state. Currently I must restart my podman container to apply new settings since the Reload Server Settings Action fails with “Action failed No usable ECDSA private key found in PEM”.
When starting the container, the following shows up in logs: ERROR Configuration build error (registry.build-error) source = "OidcProvider", id = <redacted just in case>, reason = "No usable ECDSA private key found in PEM".
When logging in via Bulwark, logs show INFO Authentication successful immediately followed by ERROR Authentication error (auth.error) reason = "InvalidAlgorithm", details = "Failed to encode ID token".
How would one reset OidcProvider to its default unconfigured state? All settings and data are stored via PostgreSQL 18.
This does seem to be the issue since running openssl ecparam -name prime256v1 -genkey to generate a key and entering it into the OpenID Connect Signature Key field set to ECDSA using P-256 and SHA-256 resolves the issue. I don’t plan to use this feature and would still like to unset the OidcProvider configuration to it’s default state.
What you have now is already the factory state. OidcProvider is seeded once at first start with a generated P-256 key and es256, and being a singleton it cannot be deleted, so a fresh P-256 key with signatureAlgorithm set to es256 is exactly what a new install looks like. If you would rather park it, hs256 with any random string as signatureKey also works, since the HMAC path takes the raw secret.
The InvalidAlgorithm error at login was a symptom of the same bad key, not a second fault. When the configured key fails to parse we fall back to a random HMAC secret but leave the algorithm at es256, so authentication succeeds and then the ID token cannot be signed. I’ll fix that fallback to set hs256 with the key. And yes, “Reload settings” failing on the one bad object is why you needed the restart.