TSLinkTSLink Docs

Share Jellyfin, Immich and Other Self-Hosted Apps with Friends and Family

Share existing media apps over Tailscale, grant a person access until a deadline, or send a public browser guest link.

View as Markdown

To share Jellyfin or Immich with friends and family, register the running app with TSLink, retrieve its exact private address and grant each person's Tailscale login access until a deadline. Private recipients install Tailscale once. Someone outside your tailnet can accept one gateway device share for several routed apps. For a browser-only visitor, use an explicitly public, expiring guest link instead; it is forwardable and does not prove identity.

TSLink proxies an existing app. You remain responsible for installing, configuring, backing up and securing it, including its accounts and authentication. The host must stay awake and connected. TSLink is an independent project, not made or endorsed by Tailscale.

Jellyfin

TSLink's jellyfin recipe targets http://127.0.0.1:8096. Jellyfin's optional HTTPS port 8920 is not that recipe's target. Finish initial setup locally, keep user login enabled, use an empty Base URL and add the actual TSLink source IP to Jellyfin's Known Proxies. Review the tagged recipe.

Install TSLink, run Jellyfin separately, then preview and apply:

bash
tslink apps share jellyfin --allow you@example.com
tslink apps share jellyfin --allow you@example.com --yes
tslink url jellyfin --wait

Replace you@example.com with your actual Tailscale login. If the host mapping differs, pass --proxy 127.0.0.1:<host-port> to both recipe commands. Finish enrollment or admin device approval when prompted. Registration alone does not prove the app works; open the returned address and test the app before inviting anyone.

Immich

The immich recipe targets native HTTP at http://127.0.0.1:2283. Finish first-admin setup locally and keep Immich login enabled. Use the root of a dedicated hostname and the exact URL returned by TSLink as the mobile server URL. See the tagged recipe.

bash
tslink apps share immich --allow you@example.com
tslink apps share immich --allow you@example.com --yes
tslink url immich --wait

Recipes preserve existing registrations. Both recipes preserve the canonical external Host; check the app's hostname and Origin settings. Immich uploads remain subject to TSLink's default 32 MiB request-body cap and 30-second read inactivity timeout. Choose suitable finite request limits for large or slow uploads; TSLink does not back up your photo library.

Choose who can open the app

Your own devices

  1. Register and enroll the app using the recipe above, retaining your own --allow login.
  2. Install Tailscale on the phone, tablet or other receiving device, sign in to your tailnet and finish any required approval. Keep it connected; tailnet policy must permit the app.
  3. Open the exact address from tslink url jellyfin --wait or tslink url immich --wait in a browser, or enter it in a compatible app's server-address setting. Sign in to the application as required.

A named person with a deadline

  1. For someone already in your tailnet, use their actual Tailscale login:

    bash
    tslink people add alice@example.com --apps jellyfin,immich --for 7d
  2. Send the exact app addresses. Alice installs Tailscale, signs in with the granted login and opens the addresses under the tailnet's network policy. Keep each app's own accounts and login.

  3. Inspect grants with tslink people list --json. To end access early, run tslink people remove alice@example.com. Removal and expiry deny new requests without stopping the app or daemon. Accepted streams may finish; delivered data cannot be recalled. See people sharing.

The first people grant scopes the selected app to people; the owner --allow rules above retain your access. Unlisted callers need an active grant or an explicit legacy allow rule.

A person outside your tailnet through gateway mode

  1. Enable the private portal and route the already registered apps:

    bash
    tslink portal enable --owner you@example.com --gateway
    tslink portal route add jellyfin
    tslink portal route add immich
    tslink portal route list --json
    tslink status --urls
  2. For a new person, grant access and generate a gateway invitation:

    bash
    tslink people add bob@example.com --apps jellyfin,immich --for 7d --invite --print-links --qr

    Creating invitations needs a stored user-owned Tailscale API token; use the stdin login path. Send the generated message yourself. Invitation links are bearer capabilities; keep them private. Here --qr prints a QR code for the gateway dashboard, not for the invitation link; an invitation QR code needs --qr-invite @gateway. For an existing person, use people update rather than people add.

  3. Bob installs Tailscale, signs in with the granted account, accepts the gateway device share and keeps Tailscale connected. He opens the dashboard or the exact route URLs from status. Each route uses its own HTTPS port on the gateway hostname; do not guess the address.

  4. Change routed-app grants later without another invitation. Non-routed apps still need their own shares. Default per-app sharing remains available. Follow gateway mode for enrollment, network policy, stale-invite recovery and compatibility limits.

Gateway ports are separate browser origins but share cookies; they do not isolate app cookies. Keep application authentication and verify each app's proxy/Origin behavior. TCP, Funnel and guest-link apps cannot be gateway routes.

  1. Choose one HTTP proxy app that is not a gateway route. If you followed the gateway path above, remove that route before choosing guest mode for that app; do not combine the two paths. Verify application authentication and the private app's enrolled node first.

  2. Explicitly create a public link with a finite deadline:

    bash
    tslink guest create jellyfin --for 3d --public --print-link

    Add --pin for hidden terminal input and send the PIN separately. Check status and doctor for actual Funnel availability; creation alone saves configuration.

  3. Send the original link privately. The guest needs only a browser, and enters the PIN if configured. This public bearer link can be forwarded and does not verify a person's identity; it is not a promise of native-client compatibility.

  4. Use tslink guest list --json to find its ID and tslink guest revoke <id> to end access. See guest links for tracked-stream cancellation and revocation limits. Files, folders and raw TCP never become public through TSLink.

Before sharing

Names of HTTPS apps appear in public certificate logs; choose names you are happy for others to see. Tailscale policy and application authentication still apply. Check tslink status --json and tslink doctor --json, then test a real visit from the intended recipient; backend health alone does not prove recipient reachability.

Related: Gateway mode · People sharing and revocation · Browser guest links · App recipes.

Sources: TSLink v0.2.0 apps.md, people.md, portal.md, guest-links.md and README.

Table of Contents