Repository navigation
Description
Describe the bug
π‘ Before filing, please check common issues:
Biorouter Troubleshooting Guide
π¦ To help us debug faster, attach a diagnostics bundle: in the app, Chat summary β Diagnostics β Generate diagnostics. It collects the transcript, a redacted copy of your configuration and the relevant logs. Read it before attaching β it contains the whole conversation.
π Full troubleshooting guide
A clear and concise description of what the bug is.
What previously worked (1.89.0):
biorouter-headless serve --port 1234 --public-url https://proxy.example.org/prefix/where there is a reverse proxy forwarding the public url to biorouter-headless over localhost.
But the closest equivalent with 1.93:
biorouter serve --port 1234 --no-token
no longer works, for an apparent variety of reasons:
--public-urlis removed, and no equivalent apparently presented- securely proxied https requests are rejected erroneously with the message
Open Biorouter through localhost or HTTPS. Use an SSH tunnel or a TLS proxy and a current browser that sends Fetch Metadata.
where the suggested solution is in fact exactly what is happening.
It seems biorouter is doing too much to attempt to verify secure connections, and getting it wrong.
To Reproduce
Steps to reproduce the behavior:
- start
biorouter serve --port 9999 --no-token - Access via HTTPS revese proxy
- See error above
Expected behavior
A clear and concise description of what you expected to happen.
The existing proxy still works:
- trusted connection over localhost (or local BSD socket, if preferred)
- proxied HTTPS requests
- proxy with path prefix
- it should not be biorouter's responsibility to check and enforce these things, other applications do not do this
Suspected cause
If you have an idea where the problem is (a file, a setting, a step that behaves differently from the documentation), describe it here. Optional.
serve appears to have been rewritten, and a number of features necessary for proxying to continue to function removed.
Screenshots
If applicable, add screenshots to help explain your problem.
Please provide the following information
- OS & Arch: Debian 13, amd64
- Interface: [UI / CLI] headless
- Version: [e.g. v1.0.2] v1.93.0
- Extensions enabled: doesn't get that far
- Provider & Model: doesn't get that far
Additional context
Add any other context about the problem here.
Activity
minrk commentedon Oct 16, 2026
fwiw, I can bypass the erroneous security message by setting the Host header to localhost in the proxy, but then we are back in the situation that the fix for #9 has still been lost by the removal of
biorouter-headlessfix(serve): built apps behind an HTTPS proxy and under a path prefix
Broccolito commentedon Oct 17, 2026
Thanks for the report. You were right on every point, and this is fixed in #404 (merged to
main; it ships in the next release).What was wrong in 1.93.0
X-Forwarded-Proto: httpsand read its last value. Behind JupyterHub that header arrives ashttps,http, because configurable-http-proxy appends its own scheme. So a request your browser had already marked withSec-Fetch-*headers was refused. The check now relies on the browser's Fetch Metadata, which browsers only send to https or localhost addresses, and ignores the proxy's scheme header. Plain-HTTP network access is still refused, because there the browser can't protect the page.--public-urland path-prefix support (cannot proxy biorouter-headless on a path prefixΒ #9) were lost whenbiorouter-headlesswas retired. Both are back. The bundle now uses relative URLs and the daemon writes a<base href>, so a prefix the proxy strips works without rewriting anything./. Both are fixed.Behind a proxy
--public-urldoes three things:HostorX-Forwarded-Proto;The proxy must strip the prefix, pass WebSocket upgrades through, and leave the browser's
Sec-Fetch-*headers in place. A plainhttppublic URL is accepted only for a loopback address.One caution on
--no-tokenOn a hub where users' servers share one machine (LocalProcessSpawner, The Littlest JupyterHub), every other account can reach the loopback port. Keep the token there, passed in with
BIOROUTER_BROWSER_TOKEN. With one container per server (KubeSpawner, DockerSpawner),--no-tokenbehind the hub's login is reasonable. The docs have jupyter-server-proxy examples for both:docs/deployment/browser-access.md, section "Behind a reverse proxy".I verified this in Chrome through a proxy that mimics the JupyterHub chain: prefix stripped,
Hostpreserved,X-Forwarded-Proto: https,http. The interface, its live views and a built app all work under/user/<name>/proxy/<port>/.