Allow using IP and http for admin webui

Issue Description

  • The WebUI is reached over HTTPS on the configured hostname only. The OAuth, OIDC, and JMAP discovery documents v0.16 publishes use https://<defaultHostname>/... exclusively in normal mode. Loading the WebUI by IP address, by container name, or over plain HTTP (for example http://192.168.1.10:8080/admin) will appear to load the sign-in page but will fail at the OAuth callback. Use the same hostname that was entered in Step 1 of the wizard, or that already lives on defaultHostname from the migrated settings.
  • http://...:8080 is no longer the right URL for day-to-day administration. Port 8080 carries the recovery / bootstrap HTTP listener and is intended for the migration window; once the server is running normally it stops being a valid sign-in entry point.
  • When the public HTTPS port is not 443 (for example a reverse proxy on :8443, or a Docker host port mapping that diverges from the container’s 443), set the STALWART_HTTPS_PORT environment variable to that port and restart the server. Without it, the discovery documents will publish https://<host>/... (port 443 implied) and clients will be sent to a port the proxy is not listening on.

I understand this is for security concerns. But users have their own workflows and security measures, many of which are no longer possible on v0.16.

The admin panel domain is not necessarily the same with the hostname set in config. For example for security reasons I don’t want to expose the web panel to public internet, but only accessible via ssh port forwarding. Previously everything worked, I could use https with self-signed certs or plain text http in ssh tunnel. But now the whole workflow is broken. I am forced to use the hostname configured which is impossible if I don’t want to expose this to public internet. I cannot set in /etc/hosts either because I heavily use mail clients on my machine, I will not be able to connect to mail ports if I resolve stalwart to localhost.

And I think it is very common for users to use reverse proxies or CDN or WAF. Many users may want to use plain text http within server host, and expose it to public internet using nginx. In this case, certs should be configured in nginx. This is also much better in security: battle-tested nginx or other reverse proxies written in memory safe language or WAF are exposed to public internet, instead of stalwart.

Nginx, ssh port forwarding, mTLS, WAF, CDN, there are a million things that are broken if you require using hostname plus https. I am currently locked out from the admin panel due to this broken workflow.

Expected Behavior

Leave an option for users to visit admin web panel using IP and plain text http.

Actual Behavior

Cannot login to admin web panel unless using the hostname configured, and https.

Reproduction Steps

N/A

Relevant Log Output

N/A

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

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.

on

There are several documented paths forward for your use case. Here’s a breakdown of how to restore your workflows:


The core constraint and how to work around it

The OAuth callback flows used by the WebUI require that the public URL in the discovery documents matches what the browser actually connects to - and browsers refuse OAuth flows over plain HTTP for non-localhost origins. This is a browser-enforced security restriction, not just a Stalwart policy. However, the docs provide clear workarounds for every scenario you describe.


SSH port forwarding (your current use case)

Your exact scenario (SSH port forwarding to keep the panel off the public internet) works, but with one important detail: localhost is exempt from the browser’s HTTPS requirement for OAuth. Forward the port to localhost (e.g. ssh -L 8080:127.0.0.1:443 yourserver), then open the WebUI at https://localhost. The browser will accept an OAuth flow on localhost over HTTPS with a self-signed cert.

Alternatively, set STALWART_PUBLIC_URL=https://localhost (or https://localhost:<port>) as an environment variable on the container. This makes all discovery documents point to localhost, so the OAuth callback will land correctly when accessed via port forwarding.


Reverse proxy (nginx, Caddy, Traefik, etc.) behind which Stalwart runs on plain HTTP

This is fully supported and is actually the recommended pattern:

  1. Let nginx (or any other proxy) terminate TLS on the public-facing side.
  2. Have nginx talk to Stalwart’s HTTP listener on port 8080 (plain HTTP upstream - no certs needed on Stalwart).
  3. Set the STALWART_PUBLIC_URL environment variable on the Stalwart container/process to the public URL clients use, e.g. https://mail.example.com or https://mail.example.com:8443.

The discovery documents will then publish the correct https://... URLs, and Stalwart itself never needs to hold or use TLS certs. Nginx/WAF/CDN handles everything public-facing.


The STALWART_PUBLIC_URL variable is the key

From the environment variables docs:

STALWART_PUBLIC_URL: the full base URL clients reach the server on, for example https://mail.example.com, https://mail.example.com:8443, or https://example.com/mail. The variable does not change Stalwart’s internal listener bindings.

Set this in your Docker environment (e.g. -e STALWART_PUBLIC_URL=https://your-admin-hostname) and Stalwart will publish that URL in all discovery documents, regardless of how it is internally accessed.


Diagnosing a broken setup

If sign-in still fails after setting STALWART_PUBLIC_URL, the docs suggest:

curl https://<public-url>/.well-known/openid-configuration

Check that every URL in the response uses your public base URL. Any mismatch points back to STALWART_PUBLIC_URL not being set or picked up correctly.


Relevant docs:

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

I am asking about Stalwart v0.16. It is new and the docs is not fully updated. Port 8080 is no longer supported. STALWART_PUBLIC_URL did not seem to work for me. And I am not stopped by browser restrictions, but rather, a successful response with Temporary server failure. If the problem persists, contact your administrator. error