Tailscale serve service vs. proxy manager

I couldn’t help but notice that the Tailscale service has a serve_service configuration option. From what I understand, this was added not long ago to expose IncusOS itself as a service to Tailscale, right? tailscale: Add support for tailscale services in serve command by AmandaCameron · Pull Request #912 · lxc/incus-os · GitHub

Initially, I thought this would accept an array of services so other container services could be advertised to Tailscale as well. However, I believe this is not the intended implementation. Eventually, I found this other project: GitHub - jtdowney/tsbridge: A lightweight proxy manager built on Tailscale's tsnet library that enables multiple HTTPS services on a Tailnet · GitHub, which I have since been using to expose some services running on OCI containers to Tailscale.

type: container
name: tsbridge
description: Tailscale proxy
profiles:
  - default
source:
  alias: jtdowney/tsbridge:latest
  mode: pull
  protocol: oci
  server: https://ghcr.io
  type: image
devices:
  tsbridge-data:
    path: /data
    pool: local
    source: tsbridge-data
    type: disk
config:
  environment.TS_OAUTH_CLIENT_ID: 
  environment.TS_OAUTH_CLIENT_SECRET: 
  raw.lxc: lxc.execute.cmd = /usr/local/bin/tsbridge -config /data/config.toml

I’m writing to ask how you guys are solving this problem. I would also like to eventually start contributing to IncusOS =), so I ask, should this feature be kept as simple as it is today, or should IncusOS be able to run multiple tailscale serve --service= commands to advertise the intended services to Tailscale? Or should that be left to a proxy manager?

Using tsbridge feels a bit odd on Incus since it seems heavily tied to Docker and tries to mimic Traefik’s labels feature. As I’m on my way to learn golang, I’m considering forking it to make it more ‘the Incus way’; but, what exectly would the Incus way be? :rofl:

Bear with me, I’m tottaly novice on Incus, IncusOS, and Tailscale itself :nerd_face:.

My understanding (I’m not part of the project) is that the tailscale instance on the host is meant to be used to expose the incus API on a tailnet. So your first paragraph is likely correct.

I personally managed this by running one normal tailscale instance in a normal LXC. It has access to an uplink as well as a private LAN, where instances I want to expose to the VPN are given static IP addresses (through DHCP/SLAAC) and are served on the tailne through tailscale serve –service=…. The static IPs are necessary because tailscale serve does not deal well with domain names (yet?). Each service gets its own ts.net URL according to the name they were given and, so far, it’s been working very well.

I know it’s a bit more faff than using what is bundled with the OS but at the same time, the LXC approach is much more versatile and robust.