Skip to content

fix(desktop): support self-signed remote HTTPS windows#289

Closed
pascalandr wants to merge 2 commits into
NeuralNomadsAI:devfrom
Pagecran:feat/tauri-self-signed-https
Closed

fix(desktop): support self-signed remote HTTPS windows#289
pascalandr wants to merge 2 commits into
NeuralNomadsAI:devfrom
Pagecran:feat/tauri-self-signed-https

Conversation

@pascalandr

Copy link
Copy Markdown
Contributor

Summary

  • route remote desktop windows through a local HTTPS proxy so WebView2 accepts secure cookies when the target server uses a self-signed certificate
  • generate and trust a local proxy certificate on Windows, then terminate TLS locally while forwarding requests to the remote CodeNomad server
  • install the rustls crypto provider explicitly so the HTTPS proxy starts reliably at runtime on Windows

Testing

  • cargo check
  • npx @tauri-apps/cli build
  • manually verified remote window connection works against a self-signed HTTPS CodeNomad server

Route remote windows through a trusted local HTTPS proxy so WebView2 accepts secure cookies with self-signed servers. Install the rustls provider explicitly so the proxy starts reliably on Windows.
@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

@pascalandr - Thanks, that's a clever trick to work around Tauri self signed.

A few things,

  • can we restrict this server to only accept connections from the Tauri process?
  • Maybe not use a network port but use some other way?
  • Maybe handle self signed in tauri with a custom protocol handler instead of starting a whole server?

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

@CodeNomadBot

What are our options here, do you have some ideas

@codenomadbot

codenomadbot Bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

What I think you’re asking: given this PR’s current approach (a localhost HTTPS proxy with a locally trusted cert), what are the realistic alternatives, and is there a cleaner way to satisfy WebView2’s secure-cookie / self-signed-cert constraints on Windows.

Assumption: the goal is specifically to make remote HTTPS sessions work in a Tauri WebView when the upstream server uses a self-signed cert, without opening a broad local attack surface.

My read is that the option space is roughly:

  1. Keep the local HTTPS proxy, but harden it
    This is the most pragmatic option.
  • It already binds to 127.0.0.1 on an ephemeral port, so it is not remotely reachable.
  • We can tighten it further by making it single-target and single-session: only forward to the exact configured upstream origin, reject all other hosts, and shut it down with the window.
  • Add an unguessable session token in the first URL or a required header so random local processes cannot casually reuse it.
  • Keep it Windows-only and only for the self-signed remote-window case.

Why I think this is the leading option: it preserves normal https:// browser semantics, which is the thing WebView2 cares about for secure cookies.

  1. Try to avoid a network port entirely
    I do not think this is a strong fit for a webview.
  • WebView2 wants to navigate to a URL/origin.
  • Named pipes / in-process channels are great for app IPC, but they do not naturally give the web content a normal HTTPS origin.
  • If we move away from a URL-backed origin, we usually lose cookie and storage behavior or end up rebuilding a lot of browser semantics ourselves.

So: technically possible to build some custom transport, but likely a lot more complexity for worse browser compatibility.

  1. Use a Tauri custom protocol instead of a localhost server
    This is the main “cleaner architecture” alternative, but it has important tradeoffs.
  • Upside: no listening socket.
  • Downside: the page origin becomes something custom like tauri://... or an app-specific protocol, not the real remote HTTPS origin.
  • That can break or complicate secure cookies, redirects, CSP, fetch/XHR expectations, service worker behavior, and anything depending on standard same-origin rules.
  • You also end up owning a lot of proxy/rewrite behavior inside the protocol handler anyway.

If the only requirement were “render HTML somehow”, this would be more attractive. For a full remote web app session, I think it is riskier than the localhost HTTPS proxy.

  1. Teach Tauri/WebView2 to trust the upstream self-signed cert directly
    This would be the ideal product behavior if the platform exposed it cleanly.
  • If Tauri/Wry/WebView2 gave us a reliable per-webview certificate override / trust callback for top-level navigation and subresources, that would beat the proxy.
  • My concern is that, in practice, these hooks are either unavailable, incomplete, or not enough to restore all browser cookie behavior on Windows.

So this is worth checking as a platform capability, but I would treat it as a potential future replacement, not the safest near-term path.

  1. Don’t support self-signed remote HTTPS on Windows
    This is the simplest implementation-wise, but weakest UX.
  • We could require a publicly trusted cert or tell users to install their own CA correctly.
  • That avoids local proxy code, but it makes local/dev/private deployments much harder.

If we want this feature to “just work,” this is probably not the direction.

On your specific questions:

  • “Can we restrict this server to only accept connections from the Tauri process?”
    Not in a strong OS-level sense with a localhost TCP listener. We can make abuse much harder with 127.0.0.1 only, ephemeral ports, single-target behavior, short lifetime, and a random session secret, but another local process can still attempt to connect.
  • “Maybe not use a network port but use some other way?”
    Not without giving up the normal HTTPS origin model the webview wants.
  • “Maybe handle self signed in tauri with a custom protocol handler instead of starting a whole server?”
    Possible, but I think it is higher-risk because it changes origin semantics and may reintroduce the exact cookie/storage issues this PR is trying to avoid.

My recommendation:

  • Keep the localhost HTTPS proxy approach.
  • Harden it rather than replace it.
  • Specifically: keep loopback-only + ephemeral port, scope it to one upstream origin, add a per-window random session token, and keep its lifetime tied to the remote window.

If useful, I can follow up with a concrete hardening checklist for this PR.

--
Yours,
CodeNomadBot

Bootstrap each remote window proxy with a random one-time token, establish a local secure session cookie, and reject unauthenticated loopback requests so other local processes cannot casually reuse the proxy port.
@pascalandr

pascalandr commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

Hardened in ba9cd53: loopback-only + ephemeral port, one-time random bootstrap token, then HttpOnly; Secure; SameSite=Strict local cookie, and 403 for unauthenticated requests. I also looked at a custom protocol, but it breaks the normal HTTPS/cookie/SSE behavior we need here, so I kept the proxy and tightened it instead.

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

@pascalandr -

Few things

  1. The CodeNomad server already generates a self signed certificate when the server starts in ~/.config/codenomad so if needed that can be used instead of managing 2 certificates
  2. If we are automatically trusting the locally generated certificate, can't we just get the remote server certificate and trust that rather than trusting local cert?

@pascalandr

pascalandr commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author
  1. Reusing the existing local CodeNomad cert is a good follow-up and would let us avoid managing a second local cert.
  2. I don’t want to auto-trust the remote server cert in the OS store: that broadens trust to that remote host outside the app and can persist across server/cert changes. Trusting a loopback cert we generate and only use for the local proxy is narrower and easier to reason about.

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator
  1. We are indirectly trusting the remote server anyway, so what's the harm directly accepting the certificate?
  2. Also the local CodeNomad server can be modified to do this job instead of creating a separate server just for proxy, it already implements proxying in it for using sidecars.

@pascalandr

pascalandr commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author
  1. The difference is scope: trusting the remote cert in the OS store would trust that host outside CodeNomad too. Here we only trust a loopback cert that the app owns.
  2. Agreed on reusing the existing local CodeNomad server/proxy path. I treated that as a follow-up refactor and kept this PR focused on getting self-signed remote windows working first.

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator
  1. The difference is scope: trusting the remote cert in the OS store would trust that host outside CodeNomad too. Here we only trust a loopback cert that the app owns.

Is it possible to un-trust the remote cert ? We could make it work like

  • Connect to an untrusted server
  • User is asked for confirmation to allow trusting
  • Trust certificate
  • Connect to server
  • When remote window is closed
  • Untrust the certificate

@pascalandr

Copy link
Copy Markdown
Contributor Author

Possible in theory, but I think it’s the riskier path: we’d need to pin the exact remote cert/fingerprint, trust it in the OS store, then reliably remove exactly that trust entry on close without affecting other uses of the same cert/CA. That’s broader and more fragile than trusting a local loopback cert that CodeNomad fully owns.

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

other uses of the same cert/CA.

There aren't going to be other users for that cert, if the cert is already there we won't need to trust it ourself. Isn't it?

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

@CodeNomadBot

Can you please verify my suggestion regarding trusting untrusting cert

  • Does Tauri need trusted cert to work in all 3 platforms
  • Is it possible to request Trusting a cert on all 3 platforms macos, linux and windows?
  • Is it possible to untrust a cert on 3 platforms
  • What is your take on the idea?

Keep your response brief but informative

@codenomadbot

codenomadbot Bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

What I understand you’re asking: whether the “temporarily trust the remote cert, then untrust it on close” idea is viable across Windows, macOS, and Linux, and whether it is a better direction than the local loopback cert.

Short answer:

  • Does Tauri need a trusted cert on all 3 platforms?
    Not strictly “Tauri” itself, but the embedded browser / platform TLS stack generally needs the certificate to validate normally if we want standard HTTPS behavior without bypasses. For the remote-window case, yes, an untrusted remote cert is the root problem on every platform; Windows/WebView2 is just the place where it bites us hardest here.

  • Can we request trusting a cert on all 3 platforms?
    In theory yes, but not with one clean cross-platform flow.

    • Windows: feasible via cert store APIs, usually with a user-facing trust prompt or store write.
    • macOS: feasible via Keychain APIs / security, but usually needs the right keychain target and may prompt for approval/admin auth.
    • Linux: possible in some environments, but much less uniform because trust stores vary by distro, browser/runtime, and user vs system config.
  • Can we untrust on all 3 platforms?
    Also possible in theory, but again not uniformly reliable.

    • Windows/macOS: more doable if we pin exactly what we installed.
    • Linux: much shakier because there may not be a single canonical trust store we can safely modify and later clean up.
  • My take on the idea:
    I would treat it as technically possible but product-risky.

    • It broadens trust to the remote cert outside CodeNomad.
    • Cleanup is fragile: crashes, multiple windows, cert rotation, or partial failures can leave stale trust behind.
    • Linux support is the weakest link.

So my recommendation stays the same: trusting a local loopback cert that CodeNomad owns is the safer design boundary than temporarily trusting arbitrary remote certs in the OS store.

--
Yours,
CodeNomadBot

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

@CodeNomadBot

Will we have the same issues with Trusting CodeNomad owned certificate on these platforms?
Research if there is any library / Tauri helper for this that simplifies the process.

@codenomadbot

codenomadbot Bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

What I understand you’re asking: if we switch to trusting a CodeNomad-owned local cert instead of an arbitrary remote cert, do we still hit the same platform problems, and is there any helper/library that makes this easier.

Short answer:

  • Same issues?
    Some of the same platform mechanics still apply, but the risk profile is much better.

    • Windows/macOS/Linux may still require OS trust-store integration, prompts, or elevated permissions depending on where we install trust.
    • Linux is still the least uniform platform.
    • But trusting a CodeNomad-owned loopback cert is narrower and easier to manage than trusting arbitrary remote certs, because we fully control the cert lifecycle and scope.
  • Any library / Tauri helper?
    I did not find an official Tauri helper/plugin for cross-platform certificate trust management.
    I did find one relevant Rust crate: koi-truststore.

    • It is a general Rust helper, not Tauri-specific.
    • It supports install/check flows across Windows/macOS/Linux.
    • Based on its docs, it shells out to platform tools (certutil, security, update-ca-certificates), so it simplifies wiring but does not remove the underlying OS-specific prompts/permissions.
    • I did not see removal/untrust as a strong built-in story there.

My take:

  • If we want to support this beyond Windows, trusting a CodeNomad-owned local cert is still the better direction than trusting remote server certs.
  • A helper crate can reduce implementation work, but it will not eliminate the cross-platform trust-store complexity, especially on Linux.

--
Yours,
CodeNomadBot

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

@pascalandr - It seems this approach of installing a certificate and creating a proxy in CodeNomad for working around a self signed SSL might not work very well on all the platforms, as explained above.
I am leaning towards it being handled by OS either by

  1. Trusting the remote certificate
  2. Setting up a proxy outside CodeNomad and use that to connect. I can quickly whip up a nginx config to help

@pascalandr

pascalandr commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

@shantur I think that’s the real tradeoff: there may simply not be a good cross-platform in-app solution here.
This PR still has value as a pragmatic Windows fix now ; And we can also try to move toward an OS/external-proxy approach. I’d be interested in the nginx config to see if that broader direction is actually viable.

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

Below config should work

# /etc/nginx/conf.d/reverse-proxy.conf

upstream remote-codenomad-server {
    server <remote-codenomad-server-ip>:9898;
    keepalive 16;
}

# Local HTTPS listener
server {
    listen 8443 ssl;
    server_name localhost;

    ssl_certificate     /etc/nginx/ssl/local.crt;
    ssl_certificate_key /etc/nginx/ssl/local.key;

    location / {
        proxy_pass https://remote-codenomad-server;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_ssl_server_name on;
        proxy_ssl_name <remote-codenomad-server-ip>;
        proxy_ssl_verify off;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

@pascalandr

Copy link
Copy Markdown
Contributor Author

Thanks, this helps. I agree this could be a cross-platform path, but it looks like a much bigger project, not a small follow-up. So the immediate question is whether we keep this PR as a pragmatic Windows fix for now ?

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

For a cross platform project, I think having a feature just to work on one won't be a good idea.

@pascalandr

Copy link
Copy Markdown
Contributor Author

Just to clarify, are you opposed to this being the Windows implementation specifically, or only to merging it without a clear path for macOS/Linux as well? I agree the feature itself should be cross-platform, even if the implementation may differ by OS.

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

Yes that's correct. Thanks for understanding

@pascalandr

Copy link
Copy Markdown
Contributor Author

I think the most realistic cross-platform direction is to keep the same overall design on all 3 OSes, but use OS-specific trust-store integration.

Common design

  • Do not trust the remote server cert in the OS store.
  • Instead, generate a CodeNomad-owned local cert for localhost / 127.0.0.1.
  • Start a local HTTPS loopback proxy.
  • Open the remote window on that local HTTPS origin.
  • Forward traffic from the proxy to the remote CodeNomad server.

That keeps normal browser semantics for:

  • secure cookies
  • credentials: include
  • SSE / EventSource
  • standard HTTPS origin behavior

So the feature can be cross-platform even if the implementation differs by OS.

Windows

This is the approach in this PR and it is the only one actually validated so far.

  • generate a persistent local cert
  • trust it in CurrentUser\Root
  • run a loopback HTTPS proxy on an ephemeral port
  • keep the proxy single-target / single-session / window-scoped

macOS

I think the same architecture should work.

  • generate the same persistent local cert
  • add it to the login keychain, not the system keychain
  • mark it trusted for SSL
  • run the same loopback HTTPS proxy

Most likely implementation path is via security / Keychain integration.

Linux

Same proxy architecture in theory, but this is the hardest platform because trust stores are not uniform.

Likely approach:

  • generate the same persistent local cert
  • try OS-specific trust-store installation depending on environment
  • examples: trust anchor, update-ca-certificates, update-ca-trust
  • fall back to a guided/manual flow if we cannot reliably install trust automatically

So I think Linux should be treated as best-effort first, then tightened based on real distro testing.

Practical conclusion

I do think the feature can be cross-platform, but probably not with one identical implementation.
The shared product model can stay the same; the trust-store plumbing will need to be OS-specific.
What do you think ?

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

Same proxy architecture in theory, but this is the hardest platform because trust stores are not uniform.
think Linux should be treated as best-effort first, then tightened based on real distro testing.

I don't want to inherit something that is so specific to platforms and it's not a native CodeNomad feature that's missing here. Please use a proxy, accept remote codenomad certs or run remote codenomad with proper free certs from Let's Encrypt

@pascalandr

pascalandr commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

That can only work in environments where the user controls DNS / reverse proxy / certificates, but in many work setups that is decided by IT/network admins, so it is not really a user-available solution. That is exactly why I explored a client-side workaround here.

Just to clarify, I did try hard on the other paths on Windows :

  • accepting the remote self-signed cert directly in Tauri/WebView2: I could not get that to work at all
  • reusing the existing local CodeNomad server/proxy path: I tried it, but it did not isolate the remote session correctly.
  • using a Tauri custom protocol: I explored it, but it was a poor fit for normal HTTPS/cookie/SSE behavior
  • The dedicated local HTTPS proxy was the ONLY approach that worked end-to-end.`

@shantur

shantur commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

Or you can use Electron version, it works fine, it has capability to allow self signed certificate

@pascalandr

pascalandr commented Apr 4, 2026 via email

Copy link
Copy Markdown
Contributor Author

@shantur

shantur commented Apr 7, 2026

Copy link
Copy Markdown
Collaborator

Well it's a lot slower on my side, especialy in this case.

@pascalandr - Sorry to hear that. I can surely help you get it working with nginx if you are available on Discord.

@pascalandr

Copy link
Copy Markdown
Contributor Author

@shantur, I think there may be a cleaner path now that SideCar support exists: keep the Windows/self-signed workaround outside CodeNomad in an external helper, and only use CodeNomad SideCars as the integration point. i'll try that.

@shantur

shantur commented Apr 7, 2026

Copy link
Copy Markdown
Collaborator

@shantur, I think there may be a cleaner path now that SideCar support exists: keep the Windows/self-signed workaround outside CodeNomad in an external helper, and only use CodeNomad SideCars as the integration point. i'll try that.

Brilliant. If it doesn't work with Sidecar, the remote server can be worked with the Windows/Self-signed workaround. That would be a better experience IMO as it will give you access to keyboard shortcuts

@shantur

shantur commented Apr 8, 2026

Copy link
Copy Markdown
Collaborator

@pascalandr - Closing this as we have another way forward.

@shantur shantur closed this Apr 8, 2026
@pascalandr

Copy link
Copy Markdown
Contributor Author

@shantur I tried the SideCar approach, but for some reason it pointed back to the local CodeNomad session instead of a properly isolated remote one. Hotkeys worked fine thought; droping it for now.
I also had to revert the proxy hardening to make the Windows self-signed remote window work again. I’m keeping that version in my fork for now, and I’ll try a similar approach on a Linux VM to see if this can become a more credible multi-platform path.

@shantur

shantur commented Apr 11, 2026

Copy link
Copy Markdown
Collaborator

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants