[feature] Support running under a HTTP path #406

Closed
opened 2025-12-29 01:28:26 +01:00 by adam · 7 comments
Owner

Originally created by @kev-the-dev on GitHub (Jan 9, 2023).

Feature request

Tailscale client supports specifying not just host/port/protocol, but also a HTTP path when connecting to a control server:

tailscale up --login-server https://example.com/foo

Presumably this is to allow multiple control servers to be behind the domain, for example https://example.com/customer1 https://example.com/customer2, or to allow other services to also be behind a reverse proxy i.e https://example.com/headscale for headscale backend, https://example.com/my_api for a different backend.

There doesn't seem to be any way to support this in Headscale currently. Headscale does allow a path to specified in the config:

server_url: https://127.0.0.1:443/headscale

But the path in this URL doesn't seem to affect the application i.e. a client with tailscale --login-server https://example.com/headscale. The requests tailscale makes 404s since they are not provided by headscale.

Implementation
From what I can tell this feature would require the following changes:

  • If server_url contains a path, the HTTP server should use this path as a prefix for all provided endpoints
  • The noise protocol implementation should also use the path prefix, as Tailscale client also includes the path prefix in the Noise-encrypted API calls under /ts2021
  • Perhaps same with embeded DERP server?
  • Any other paths I may be missing?

I'm actively working on a patch for this to use myself, but if developers have any tips for getting this feature upstream let me know.

Originally created by @kev-the-dev on GitHub (Jan 9, 2023). **Feature request** Tailscale client supports specifying not just host/port/protocol, but also a HTTP path when connecting to a control server: ``` tailscale up --login-server https://example.com/foo ``` Presumably this is to allow multiple control servers to be behind the domain, for example https://example.com/customer1 https://example.com/customer2, or to allow other services to also be behind a reverse proxy i.e `https://example.com/headscale` for headscale backend, `https://example.com/my_api` for a different backend. There doesn't seem to be any way to support this in Headscale currently. Headscale _does_ allow a path to specified in the config: ``` server_url: https://127.0.0.1:443/headscale ``` But the path in this URL doesn't seem to affect the application i.e. a client with `tailscale --login-server https://example.com/headscale`. The requests tailscale makes 404s since they are not provided by headscale. **Implementation** From what I can tell this feature would require the following changes: * If `server_url` contains a path, the HTTP server should use this path as a prefix for all provided endpoints * The [noise protocol implementation](https://github.com/juanfont/headscale/blob/93aca81c1cb20695d010766042a3abbe820364e8/noise.go#L66) should also use the path prefix, as Tailscale client also includes the path prefix in the Noise-encrypted API calls under /ts2021 * Perhaps same with embeded DERP server? * Any other paths I may be missing? I'm actively working on a patch for this to use myself, but if developers have any tips for getting this feature upstream let me know.
adam added the enhancement label 2025-12-29 01:28:26 +01:00
adam closed this issue 2025-12-29 01:28:26 +01:00
Author
Owner

@juanfont commented on GitHub (Jan 13, 2023):

@kev-the-dev are you sure about this? Happy to merge it, but I was not aware, tbh.

@juanfont commented on GitHub (Jan 13, 2023): @kev-the-dev are you sure about this? Happy to merge it, but I was not aware, tbh.
Author
Owner

@rusitschka commented on GitHub (Apr 1, 2023):

I'd love to see this feature. @kev-the-dev are you still working on it?

It would also allow to "hide" headscale behind a random path which reduces the attack surface for script kiddies scanning the host - similar to random webhook paths.

@rusitschka commented on GitHub (Apr 1, 2023): I'd love to see this feature. @kev-the-dev are you still working on it? It would also allow to "hide" headscale behind a random path which reduces the attack surface for script kiddies scanning the host - similar to random webhook paths.
Author
Owner

@kev-the-dev commented on GitHub (Apr 4, 2023):

Yes I am working on this. Waiting on approval from my employer to contribute my patch, but should be in a PR in a week or so

@kev-the-dev commented on GitHub (Apr 4, 2023): Yes I am working on this. Waiting on approval from my employer to contribute my patch, but should be in a PR in a week or so
Author
Owner

@juanfont commented on GitHub (May 7, 2023):

Hey folks, I am 99.9% convinced this is not possible due to the Tailscale client. The clients need to be able to talk to /ts2021 to initiate the protocol connection. This is hardcoded in the client.

And, to be fair, I cannot see the usecase for this - given that you can very well host multiple headscales in the same machine by just having various subdomains in the same reverse proxy.

@juanfont commented on GitHub (May 7, 2023): Hey folks, I am 99.9% convinced this is not possible due to the Tailscale client. The clients need to be able to talk to `/ts2021` to initiate the protocol connection. This is hardcoded in the client. And, to be fair, I cannot see the usecase for this - given that you can very well host multiple headscales in the same machine by just having various subdomains in the same reverse proxy.
Author
Owner

@kev-the-dev commented on GitHub (May 8, 2023):

Yes subdomains are a reasonable way to achieve this, assuming you have that level of control over DNS for your server.

I agree it would be confusing / complicated to have Headscale match the current implementation of the Tailscale client where some paths (like /ts2021) are at the root and some make use of the path given in --login-server.

Perhaps it makes sense to first file a bug / patch for the Tailscale client about this odd behavior

@kev-the-dev commented on GitHub (May 8, 2023): Yes subdomains are a reasonable way to achieve this, assuming you have that level of control over DNS for your server. I agree it would be confusing / complicated to have Headscale _match_ the current implementation of the Tailscale client where some paths (like /ts2021) are at the root and some make use of the path given in `--login-server`. Perhaps it makes sense to first file a bug / patch for the Tailscale client about this odd behavior
Author
Owner

@kev-the-dev commented on GitHub (May 8, 2023):

To be clear, my use case is not to have multiple headscale instances behind the same reverse proxy. It is to have other unrelated backend services behind the same reverse proxy as headscale. In this case it isn't desireable to map location / to headscale. But this too could make use of SNI and subdomains

@kev-the-dev commented on GitHub (May 8, 2023): To be clear, my use case is not to have multiple headscale instances behind the same reverse proxy. It is to have other unrelated backend services behind the same reverse proxy as headscale. In this case it isn't desireable to map `location /` to headscale. But this too could make use of SNI and subdomains
Author
Owner

@juanfont commented on GitHub (May 8, 2023):

assuming you have that level of control over DNS for your server.

Given our userbase, it is fair to assume that...

patch for the Tailscale client about this odd behavior

That'd be the first thing indeed. But in my experience, reverse proxies are already a source of issues sometimes... adding path to the mix can only make things worse.

unrelated backend services behind the same reverse proxy as headscale

You can always have everything in /... 😅

@juanfont commented on GitHub (May 8, 2023): > assuming you have that level of control over DNS for your server. Given our userbase, it is fair to assume that... > patch for the Tailscale client about this odd behavior That'd be the first thing indeed. But in my experience, reverse proxies are already a source of issues sometimes... adding path to the mix can only make things worse. > unrelated backend services behind the same reverse proxy as headscale You can always have everything in /... 😅
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#406