Expose the bus over the tailnet
There are two ways. Both keep traffic inside the tailnet. Funnel is never used.
Tailscale serve (default)
serve stays on 127.0.0.1:47910. Tailscale terminates HTTPS on port 8443 and forwards to it.
- Enable HTTPS certificates for the tailnet (admin console, DNS page, "Enable HTTPS"). This publishes the machine name in public Certificate Transparency logs. If you do not want that, use the direct bind below.
- Check it works:
It writes atailscale cert <bus-host>.<tailnet>.ts.net
.crtand a private.keyinto the current directory.tailscale servedoes not need them; delete them. Do not rely ontailscale status --json.Self.CertDomains: on a macOS client it stayednullafter a certificate was issued. - Expose:
tailscale serve --bg --https=8443 --accept-app-caps catesworks.com/cap/session-bus http://127.0.0.1:47910
- Base URL for clients:
https://<bus-host>.<tailnet>.ts.net:8443.
Undo with tailscale serve --https=8443 off. Do not use tailscale serve reset; it clears every serve configuration on the host.
Direct tailnet bind
BUS_HOST=$(tailscale ip -4) BUS_PORT=47910 node dist/cli.js serve
- No certificates needed. Base URL:
http://<bus-host>.<tailnet>.ts.net:47910. - The bind guard accepts the address only if
tailscale ipreports it. Iftailscaleis not on thePATH,serverefuses to start (exit 2). - Tailscale identity headers are not logged in this mode.
ACL grant
Grant the client machines access to the bus port. Save the current policy version first; rollback is restoring it.
{
"grants": [
{
"src": ["tag:<client-tag>"],
"dst": ["tag:<bus-host-tag>"],
"ip": ["tcp:8443"]
}
]
}
- For the direct bind, grant
tcp:47910instead. autogroup:memberworks as a source if the clients are user devices rather than tagged ones.- Optionally add the app capability
catesworks.com/cap/session-bus. The bus only logs it; it does not use it for authorization. - Add a policy test for the grant if your tailnet uses them.
Check from a client
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://<bus-host>.<tailnet>.ts.net:8443/mcp
# 401
401 means the request reached the bus and was refused for lack of a token. A timeout means the ACL or serve configuration is wrong.