Skip to content

Web Client Requires HTTPS

marcpope edited this page Jul 27, 2026 · 3 revisions

Web client and HTTPS

The web client works over plain http://. Earlier releases refused to run without HTTPS, and this page previously said that could not be changed. That was wrong, and 1.0 fixes it.

HTTPS is still the better experience, and the difference is worth understanding before choosing.

What you get either way

HTTPS (or localhost) Plain HTTP
Video VP8, VP9, H.264, H.265, AV1 via WebCodecs H.264 only, via Media Source Extensions
Hardware decoding Yes Depends on the browser's own H.264 pipeline
Per-frame statistics Codec, FPS, bitrate, dropped frames Not reported
Keyboard, mouse, file transfer, chat Yes Yes
Clipboard sync Yes Restricted by the browser

The fallback is automatic. Nothing to configure and no separate URL — the client detects what the browser allows and picks the path.

Why the difference exists

Browsers restrict some APIs to a secure context — HTTPS, or localhost. Two mattered here:

  • crypto.subtle (Web Crypto) — the login handshake hashes with SHA-256.
  • VideoDecoder (WebCodecs) — the full-quality video pipeline.

Neither turned out to be a hard wall:

  • The hash never needed Web Crypto. SHA-256 is small and well specified, and the client now carries its own implementation.
  • Video does need a decoder, but WebCodecs is not the only one. Media Source Extensions is not secure-context gated, and any browser that can play an MP4 can decode H.264 through it. The client muxes the incoming H.264 stream into fragmented MP4 and hands it to a <video> element.

The cost is real — one codec instead of five, and no per-frame numbers, because on that path nothing in the client ever sees an individual frame.

Should you still use HTTPS?

Yes, where you can. Better codec choice, hardware decoding, working clipboard sync, and the ordinary reasons an admin console should be encrypted: the session carries keystrokes and screen contents whichever path renders them.

The fallback is for where TLS genuinely is not available — an isolated LAN, a temporary deployment, a machine you cannot install a certificate on.

Getting HTTPS on an internal network

A self-signed certificate is not enough on its own: browsers only grant a secure context to a certificate they trust, so a self-signed cert has to be installed into the trust store of every machine that connects.

Options, roughly easiest first:

A real certificate for a name that resolves to a private address. This is usually the least work and is widely misunderstood as impossible. Point a public DNS name you own — console.example.com — at the LAN address (10.0.0.50), and issue a certificate with a DNS-01 challenge, which never requires the host to be reachable from the internet. You get a browser-trusted certificate for a service that is only reachable internally, and nothing has to be deployed to client machines.

A reverse proxy that handles certificates for you. Caddy does this in one line, and Traefik or nginx-proxy-manager are equivalent:

console.example.com {
    reverse_proxy localhost:8080
}

Remember the web client also needs /ws/id and /ws/relay proxied with WebSocket upgrade headers. Full configs for Caddy, Traefik and nginx are in Reverse proxy and TLS.

An internal CA. If you already run one — AD Certificate Services, step-ca, Smallstep — issue from it. The CA root is usually already trusted on managed machines, which is what makes this painless where it applies and painful where it does not.

Tailscale, or a similar overlay. Tailscale issues trusted certificates for its own hostnames and needs no public DNS or open ports, which suits a clinic or office network well.

Notes

  • Clicking through a browser certificate warning loads the page but does not grant a secure context, so it lands you on the HTTP path rather than the HTTPS one.
  • Chrome's OverrideSecurityRestrictionsOnInsecureOrigin policy still works if you want the full WebCodecs path over HTTP on a managed fleet. It deliberately weakens a browser security boundary for that origin, and it is no longer necessary just to make the client run.
  • The desktop RustDesk client has none of these restrictions. The console's per-device Connect links open it with rustdesk://.

Clone this wiki locally