Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Public shares

Users with the shareRole permission can generate public share links for a song, album, or playlist.

BeetstreamNext creates a public landing page with a secure download endpoint, accessible without needing the recipient to have an account or Subsonic client.

Active shares can be revoked at any time from the admin panel’s Shares tab.

Share options

Shares can be configured with an expiry date, a download count limit, and protected by passwords.

You can set a default policy for these (since OpenSubsonic clients can’t set a password or download limit).

Public routes

Everything that works without an account is a public route:

  • share pages and downloads (/share/...)
  • tokenised stream and image links (/tokenised-stream/..., /tokenised-image/...)
  • the now-playing cover (/now-playing/cover)
  • the health check (/healthz), the homepage (/) and the static files they use

Everything else (the Subsonic API, login, account pages, admin panel, control API) needs an account.

Public hostname

You can expose the public shares on a different hostname than what BeetstreamNext binds to locally:

For example, you access the admin panel via https://admin.example.com and the Subsonic API and account pages via https://music.example.com, but you want to allow unauthenticated users to download public shares from https://public.example.com.

You can set external_hostname so that share links use the correct public URL instead of the internal bind address:

beetstreamnext:
  external_hostname: public.example.com

If it isn’t set, share links use the address of the public scope listener (or the users one), when it has a specific address (not 0.0.0.0 or loopback) and when reverse_proxy is off. Otherwise, they use the Host header of the request, which is only as trustworthy as trusted_hosts.

Set external_hostname whenever the server is reachable from outside.

Listener scopes

Every listener of BeetstreamNext has a scope that sets which routes it serves. Any other route returns 404.

ScopeServes
publicthe public routes
usersthe public routes, the Subsonic API, login and account pages
admineverything, including the admin panel and the control API

By default, a single listener has the admin scope. To give addresses or ports a smaller scope, use:

By address: public_hosts and admin_hosts

On a machine with several addresses, public_hosts and admin_hosts pick the ones that serve the public and admin scopes. They must also be in host. The remaining addresses have the users scope (or admin, if neither admin_hosts nor admin_port is set):

beetstreamnext:
  host: [100.70.0.5, 127.0.0.1, 192.168.0.10]
  public_hosts: [192.168.0.10]
  admin_hosts: [127.0.0.1]
AddressScope
192.168.0.10public
100.70.0.5users
127.0.0.1admin

host must list addresses explicitly (no 0.0.0.0 or ::) when it is combined with these settings.

Note

The first-run setup page is part of the admin panel, so it is served on admin listeners.

By port: public_port and admin_port

With a single address, public_port and admin_port open extra ports for the public and admin scopes.

port then has the users scope:

beetstreamnext:
  port: 8080
  public_port: 8081
  admin_port: 8082

Every address in host listens on all three ports: point your reverse proxy’s public hostname at 8081, the Subsonic hostname at 8080, and the admin hostname at 8082.

See Traefik with Docker for a complete example.

Using hosts and ports together

Addresses in public_hosts and admin_hosts get their scope on port, and public_port and admin_port cover the remaining addresses of host.

For example, with this config:

beetstreamnext:
  host: [100.70.0.5, 192.168.0.10]
  public_hosts: [192.168.0.10]
  port: 8080
  public_port: 8081
Listens onScope
100.70.0.5:8080admin
100.70.0.5:8081public
192.168.0.10:8080public

Good to know

  • These settings need a restart. With a Unix socket or in debug mode there is a single admin listener and they are ignored.

  • Public listeners have their own thread pool (up to 8 threads), so heavy public traffic can’t starve the others.


See external_hostname in the configuration reference.