Kubernetes Setup

Issue Description

When trying to open https://new-mail.felderer.systems.

Expected Behavior

i should get to the GUI

Actual Behavior

PR_END_OF_FILE_ERROR

Reproduction Steps

  1. Setup K8S
  2. use a LoadBalancer without proxy (till everything works but it doesnt sadly)
  3. get into the GUI via localhost:8080
  4. create Domain and Cert and also set it in Networks General
  5. everything works fine under http://new-mail.felderer.systems:443/ (i know its unsecure but at least somethings working)
  6. getting the error PR_END_OF_FILE_ERROR and cry

Relevant Log Output

saldy i only see logs when in rescue mode ;(

Stalwart Version

v0.16.x

Installation Method

Built from source

Database Backend

PostgreSQL

Blob Storage

S3-compatible

Search Engine

PostgreSQL

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 agree to follow the project’s Code of Conduct.

on

PR_END_OF_FILE_ERROR is a TLS handshake failure — the browser connected on port 443 but the server closed the connection without completing a TLS handshake. This is almost always a TLS/certificate configuration issue rather than a Stalwart bug itself. Let me check the relevant docs.

PR_END_OF_FILE_ERROR is a Firefox/browser TLS error that means the server closed the connection without completing a TLS handshake. Based on what you’ve described, the most likely cause is that port 443 is being served as plain HTTP rather than HTTPS — your note that http://new-mail.felderer.systems:443/ works (over HTTP, not HTTPS) confirms this: the listener on port 443 is not set up with TLS enabled.

A few things to check:

  1. TLS must be enabled on the HTTPS listener itself. In the Stalwart WebUI under Settings → Network → Listeners, find your port-443 listener and confirm that TLS is toggled on and that the correct certificate is selected for it. Setting a certificate in “General” alone is not sufficient — it must be assigned to (or auto-picked by) the specific listener.

  2. Certificate availability. Make sure the certificate you created for new-mail.felderer.systems is fully provisioned and shows as valid in Settings → Network → TLS Certificates. If it was issued via ACME, verify the ACME challenge succeeded.

  3. Kubernetes / LoadBalancer TLS termination. If your LoadBalancer or Ingress controller is doing TLS termination before traffic reaches Stalwart, then Stalwart should be listening on plain HTTP on the backend port, and TLS should not be enabled on that listener — but then the LoadBalancer must be configured to terminate TLS correctly. Conversely, if you want Stalwart to handle TLS end-to-end (passthrough), TLS termination must be disabled on the LoadBalancer/Ingress.

  4. Logs in rescue mode. Since you can access logs in rescue mode, look for any TLS handshake errors or certificate-loading errors at startup — these will tell you quickly if the cert failed to load.

The core fix is almost always: enable TLS on the port-443 listener in Stalwart’s network settings and ensure the certificate is correctly assigned to that listener.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong. If you found it useful, mention @helpbot in any reply to ask follow-up questions and the bot will respond again.

@helpbot And WHERE WHEREERERER should this setting be? I cant find it anywhere the only setting i found where i can select a cert is in Networks General … and i did assign it … i dont have tls enabled on the LoadBalancer i am using HCloud

service:

type: LoadBalancer

externalTrafficPolicy: Local

annotations:

load-balancer.hetzner.cloud/name: "stalwart-mail-lb"

load-balancer.hetzner.cloud/location: "fsn1"

load-balancer.hetzner.cloud/type: "lb21"

load-balancer.hetzner.cloud/uses-proxyprotocol: "false"

ports:

smtp: 25

smtps: 465

submission: 587

imap: 143

imaps: 993

pop3: 110

pop3s: 995

sieve: 4190

http: 80

https: 443

mgmt: 8080

i saw you’ve got non-default ports listed in your LoadBalancer config (although i have never used k8s so apologies if i am being stupid), those being 587, 143, 80 so assume you have customised your listener config?

my first guess would be that when editing them (or maybe due to the insanely buggy migration script) the https listener on 443 has had “TLS” or “Implicit TLS” disabled - just check both are on :3

you can do that here:
/admin/Settings/x:NetworkListener

if that doesn’t help, please could you share your full network listener config

console logs can be enabled at /admin/Settings/x:Tracer, just add a new tracer and enable colours if you’re feeling fancy!

I am running Stalwart on Kubernetes for more than an year and It is working just fine.
Since you access the admin console on port 443 via HTTP, instead of HTTPS, that makes me believe that the listener on port 443 is not configured with implicit TLS.

Open the admin console and go to context path admin/Settings/x:NetworkListener.
Click on the listener bound on port 443, scroll down to the “TLS options” section and make sure that “Enable TLS” and “Implicit TLS” are enabled.