Summary
I’d like to contribute optional Tailscale integration using the native go tsnet library, so that Silo can join a tailnet without a separate daemon or container. Would you be open to this in core, or would you prefer a Silo-managed plugin?
In time, I'd want to add Tailscale to your official clients too, but this is talking about your preferred architecture for the server side TS implementation. Happy to agree on scope before implementing.
User value / why v1
Built-in Tailscale access would let users securely reach Silo remotely without port forwarding, a public reverse proxy, or a separate Tailscale daemon/container. Using tsnet would give Silo its own tailnet identity and let administrators manage the connection through Silo.
This does not need to block v1. I’m proposing it now to agree on whether it belongs in core or a plugin, and I’m happy to target v1.1 if that better fits the roadmap.
API surface
Proposed endpoints, subject to maintainer agreement:
GET /api/v1/tailscale/capability — reports whether the server supports embedded Tailscale: { supported: boolean }.
GET /api/v1/admin/tailscale/status — administrator-only connection status: { enabled, state, hostname, addresses, endpoints, auth_url?, error? }. state distinguishes disconnected, awaiting authorization, connecting, connected, and error. auth_url is returned only when enrollment requires it.
POST /api/v1/admin/tailscale/connect — administrator-only start or resume connection. Optional request: { hostname }. Returns 202 Accepted with the current connection state; enrollment proceeds asynchronously.
POST /api/v1/admin/tailscale/disconnect — administrator-only disables tailnet access and closes its listeners. Preserves node identity for a later reconnection.
Existing playback, authentication, Jellyfin-compatible, and Audiobookshelf-compatible APIs remain accessible through the new listeners. Clients use the appropriate tailnet endpoint and authenticate with their existing Silo credentials; no playback payload changes are proposed.
Private node keys are never exposed through the API. Enrollment URLs are administrator-only and excluded from logs. Identity deletion, automatic login through Tailscale identity, and Funnel are outside the initial scope.
Client impact (android / apple / web)
- Web: add the admin controls and connection status; verify playback, seeking, and realtime behavior through the tailnet endpoint.
- Android and Apple: no proposed playback API changes or embedded VPN. Verify existing server URL entry and playback against the tailnet endpoint on supported devices with Tailscale connectivity.
- Jellyfin and Audiobookshelf clients: preserve their separate protocol surfaces and verify authentication, playback, and progress updates.
Rough size (server-side)
M
AI harness
codex
AI tool(s)
codex
AI model(s)
astra
AI involvement
Human-written, AI-reviewed
Independent or adversarial review
- Independent or adversarial review: n/a for this proposal draft. Required before submitting a non-trivial implementation.
Summary
I’d like to contribute optional Tailscale integration using the native go tsnet library, so that Silo can join a tailnet without a separate daemon or container. Would you be open to this in core, or would you prefer a Silo-managed plugin?
In time, I'd want to add Tailscale to your official clients too, but this is talking about your preferred architecture for the server side TS implementation. Happy to agree on scope before implementing.
User value / why v1
Built-in Tailscale access would let users securely reach Silo remotely without port forwarding, a public reverse proxy, or a separate Tailscale daemon/container. Using tsnet would give Silo its own tailnet identity and let administrators manage the connection through Silo.
This does not need to block v1. I’m proposing it now to agree on whether it belongs in core or a plugin, and I’m happy to target v1.1 if that better fits the roadmap.
API surface
Proposed endpoints, subject to maintainer agreement:
GET /api/v1/tailscale/capability— reports whether the server supports embedded Tailscale:{ supported: boolean }.GET /api/v1/admin/tailscale/status— administrator-only connection status:{ enabled, state, hostname, addresses, endpoints, auth_url?, error? }.statedistinguishes disconnected, awaiting authorization, connecting, connected, and error.auth_urlis returned only when enrollment requires it.POST /api/v1/admin/tailscale/connect— administrator-only start or resume connection. Optional request:{ hostname }. Returns202 Acceptedwith the current connection state; enrollment proceeds asynchronously.POST /api/v1/admin/tailscale/disconnect— administrator-only disables tailnet access and closes its listeners. Preserves node identity for a later reconnection.Existing playback, authentication, Jellyfin-compatible, and Audiobookshelf-compatible APIs remain accessible through the new listeners. Clients use the appropriate tailnet endpoint and authenticate with their existing Silo credentials; no playback payload changes are proposed.
Private node keys are never exposed through the API. Enrollment URLs are administrator-only and excluded from logs. Identity deletion, automatic login through Tailscale identity, and Funnel are outside the initial scope.
Client impact (android / apple / web)
Rough size (server-side)
M
AI harness
codex
AI tool(s)
codex
AI model(s)
astra
AI involvement
Human-written, AI-reviewed
Independent or adversarial review