The Administration panel
Profile → Administration. Every admin account sees it; everything else in the app (own profile, own devices, own selections) is per-user and needs no admin.
An account becomes an admin in one of three ways, and in no other:
- it is the first account created on a fresh
localinstall (whenADMIN_USERNAMEis set, that first account must use that name); - under
forwardoroidc, it signs in with the username set inADMIN_USERNAME; - it is created or granted admin with the
create-admincommand (see Locked out of the admin account? below).
Accounts created from the Users tab are never admins, and there is no control, in the web UI or the API, that makes an existing account an admin or takes admin away. Usernames can't be changed either.
This page is the admin-panel reference. Related admin-managed topics have their own pages: Devices & Storage, Delegated Management, and the per-provider setup under Providers.
Configuration
The Configuration tab is grouped into collapsible sections. Each header names its section and summarises it in one line (the active provider and its state, how many playlist sources are set up, and so on), so with every section closed the page is still an overview. On a first visit only Library is open. After that, which sections are open is remembered in this browser. Open all and Close all sit above the sections.
- A warning shows on its section's header whether the section is open or closed, and the full message stays inside the section: a library mounted writable, a disconnected provider or mirror target, Lidarr connected without its profiles chosen, a missing break-glass password.
- A section with an edit not yet saved says Unsaved change on its header, and the bar under the page lists the sections that have one.
- Save stays at the bottom of the page whatever is closed, and saves every section but Security, whose break-glass password has its own button. When the server rejects a setting, the section holding it opens and the field is focused, with the server's message beside Save.
| Section | What's in it |
|---|---|
| Library | The library source, automatic rescan, automatic playlist sync, artist images (TheAudioDB) |
| Playlist sources | Local playlist sources, Music Assistant, Tidal, Spotify |
| Playlists | Playlist track matching (AcoustID), playlist mirroring, Lidarr: missing-album requests |
| Listening | The default Last.fm key, listening history sources |
| Devices | Transcoding (CPU controls, cache) |
| Maintenance | Background job history |
| Security | The sign-in mode, and under OIDC the break-glass admin password |
Library
Provider connection
The card shows the active provider (Roon / Jellyfin / Emby / Plex / LMS / Subsonic / Filesystem), its status, and its connection details, which are editable here, live — no container restart. Changing the Roon host/port re-pairs immediately, reusing the existing pairing token. A new host or a rotated key is not a switch: it saves with the page's Save. Per-provider details: Providers.
Changing the library source
Switching to a different provider goes through Change library source…, never through Save. It's a dialog in four steps, and nothing is written before the last one: Cancel at any step leaves everything as it was.
- Choose the new provider. The active one isn't offered.
- Connect: enter its connection details and Test connection. You can't go on until the test passes. Filesystem needs nothing. Roon can only be checked as reachable at this point: after the switch, approve Trobar in Roon (Settings → Extensions).
- Review and confirm: what the switch does, counted on your server at
that moment:
- Carried over: each of the old provider's playlists that the new provider also has, under the same name (case and spacing aside), for the same owner, with most of the same tracks: at least 3 in common, and at least 60% of the smaller of the two. It keeps its row, so its device selections, mirroring, Lidarr requests, shared/private choice and excluded gaps stay, and its tracks are refreshed from the new provider on the first sync. Two playlists with one name and owner on either side are left unmatched rather than guessed. The switch runs the same matching against the new provider as it is then. Nothing is carried over to Roon, which can't list its playlists until Trobar is approved in Roon, nor to Filesystem or Music Assistant, whose playlists are already in Trobar as playlists of their own (both are listed under every provider).
- Removed: the old provider's other playlists, with their per-playlist settings (mirroring, the shared/private choice, excluded gaps). A mirrored playlist's mirror copies are removed with it. Also the artist-image cache, which is fetched again from the new provider.
- Devices with one of those playlists selected: the selection is removed with the playlist, and the device's next sync removes that playlist's file and any tracks no other selection keeps on it. Select the new provider's playlists for it afterwards.
- Untouched: playlists from every other source (linked Tidal and
Spotify accounts, YouTube Music and Spotify playlist links, the
.m3ufolder and iTunes, Music Assistant) with all their settings, and the library, users, devices, artist/album/track selections and listening history. Switching away from Filesystem removes nothing: its.m3ufolder is read whichever provider is active.
The confirm button names the target, e.g. Switch to Jellyfin. 4. Done: the switch re-tests the connection before changing anything, then starts the first playlist sync from the new provider and shows its result. A switch is refused while a playlist sync is already running.
First-run setup keeps its own provider picker: there is nothing to lose yet.
API keys
Three keys live in different sections:
- Last.fm API account for sending plays (Listening → Listening history) — an API key and shared secret from a Last.fm API account of your own. With both set, members can connect their Last.fm and send plays to it. The secret is stored encrypted and never shown again. Set its callback URL to your server's address.
- Default Last.fm API key (Listening → Listening history) — used for suggestions and listening stats for any user who hasn't set a personal key in their own profile.
- TheAudioDB API key (Library → Artist images) — when set, artist pictures are fetched
from TheAudioDB (whose API terms are written for
exactly this use) instead of the active provider, with the provider and an
artist.jpg-style folder image as fallbacks. Get a free key from their site; entering or changing it clears the image cache so everything re-fetches. Leave it empty to keep provider-sourced images — fine for private use, but recommended to set for anything public-facing, since provider imagery (Roon especially) is licensed for display inside that provider's own products.
Playlist sources
Local playlist sources is the one exception to "one provider at a time".
Both fields there are layered on top of the .m3u/.m3u8 discovery every
provider already gets, and both are editable and effective regardless of
which provider is active:
- Extra playlist folder — one folder outside your music library, walked
for
.m3u/.m3u8exactly as the library is, for players that keep their playlists in a directory of their own. Read-only; it must not overlap your music folder or the mirror output folder. See Filesystem. - iTunes/Apple Music Library.xml path — an exported library file. See iTunes / Apple Music.
Music Assistant has one card for all it does: enter its URL and a long-lived token, and its playlists are added to the next sync whichever provider is active. The same connection is used when Music Assistant is the library provider (the Library source card then links here rather than repeating the fields) and when a playlist is mirrored into it. Clear both fields and save to disconnect. See Music Assistant.
Streaming accounts (OAuth registration)
Personal streaming accounts are linked per-user, but the admin registers each OAuth app once here under Configuration so those logins have something to authenticate against:
- Tidal — client ID/secret; three developer-console
permissions must be enabled or the login fails at Tidal's own screen. A
fourth,
playlists.write, is optional: enable it there first, then tick My Tidal app has playlists.write enabled. - Spotify — client ID/secret (validation pending; Dev-Mode Premium + 5-user limits apply).
Each household member then connects their own account from Profile → Streaming accounts.
Playlists
- Playlist track matching: an optional AcoustID API key. With it, each track's fingerprint is also sent to acoustid.org, and MusicBrainz is asked, to recover an ISRC for poorly tagged tracks, which playlist entries can then match on. Without it nothing here goes to the internet.
- Playlist mirroring: the targets a playlist can be mirrored to (an
.m3uoutput folder, and Subsonic, Jellyfin, Emby and Plex servers; Music Assistant mirrors through its own card's connection). Each user turns mirroring on per playlist, with Mirror… on the Playlists tab. - Lidarr: missing-album requests: the Lidarr connection, and then its root folder, quality profile and metadata profile. It is not a mirror target: Lidarr is asked for albums missing from a playlist.
Listening
Listening history sources
Suggestions (top-played / recently-played) read from Last.fm, ListenBrainz
and/or Maloja. Each person can also choose to send their devices' plays to their
own Maloja, ListenBrainz or Last.fm, off until they turn it on. Maloja is
set per user, on their Profile (see Suggestions),
so any user can point the server at an address on your LAN; loopback,
link-local, unspecified and multicast addresses are refused, and Maloja
requests ignore the proxy environment variables (HTTP_PROXY and the like).
Last.fm and ListenBrainz default to the real services; two admin fields point
them at a self-hosted alternative instead, live, no restart:
- Last.fm API base URL — overrides where Last.fm reads go. Libre.fm is the closest drop-in (a genuinely Last.fm-API-compatible free-software alternative; test after switching, as not every method is independently verified). Don't point it at Maloja: its Last.fm-compatible endpoints only accept scrobbles; Maloja has its own field on each user's Profile instead.
- ListenBrainz API base URL — self-hosted ListenBrainz is the same software as the public instance, so just the URL changes.
Leave either blank to use the default (the real service, or the
LASTFM_API_BASE / LISTENBRAINZ_API_BASE env var if set). See
Suggestions.
Devices
Transcoding (CPU controls): how many transcodes run at once, and at what priority (nice level).
Transcode cache (GB): how much disk the server may use to keep finished
transcodes, in DATA_DIR/transcode. A device that syncs a track again, or a
second device with the same format, is then sent the kept file instead of
waiting for a new encode. When the cache is full, the files served least
recently are removed first. The default is 2 GB; 0 keeps nothing and empties
the cache when saved. A track whose file changes is transcoded again.
Maintenance
Background job history: how many days finished background jobs are kept in full.
Security
The sign-in mode, set by the AUTH_MODE environment variable rather than here.
Under OIDC, the break-glass admin password: an emergency local login for
when the identity provider can't be reached.
Playlist mirrors
The Playlist mirrors tab shows where playlists are mirrored to, and how that is going. It has two collapsible sections, like Configuration, with a summary and any warnings on each header:
- Targets: the mirror targets that are set up (the
.m3ufolder, Subsonic, Jellyfin, Emby, Music Assistant, Plex), each with its state and a link to its settings. A server's state comes from a live check, the same one Configuration makes when it loads; the folder's, from whether it can be written. A target that is reachable but where a playlist's last write failed shows a warning with that failure. Targets not set up are named on one line, "Also available: …". Lidarr is listed apart, under Requests: a check when it is ready, otherwise what needs attention. When Lidarr is the only thing set up, the section says no mirror target is, and links to set one up. - Playlists: each mirrored or Lidarr-enabled playlist, one line per target, each naming it.
With nothing set up at all, the tab explains what mirroring is and links to Configuration.
Users
The Users tab holds the accounts and the delegations between them, in two
collapsible sections styled like Configuration's. Each header summarises its
section (how many users and admins, and under oidc whether the break-glass
account exists; how many delegations). Both are open on a first visit; after
that, which are open is remembered in this browser. Open all and Close
all sit above them. Every action here takes effect at once, so there is no
Save button.
Accounts
localmode: create household accounts here (username + password).oidc/forwardmodes: accounts appear automatically at first login; this section gives the overview and lets you provision extra local-only accounts alongside. Underoidcthe header warns when there is no break-glass account.- Each user's row also says whom they manage and who manages them, when a delegation links them.
- Deleting a user who still owns devices, selections or playlists fails, and
the dialog lists what they own. Delete those first. Ownership can't be
moved from here; a playlist's owner only changes by re-syncing it.
Deleting a user removes their delegations too. Your own account and the last admin account can't be deleted, nor,
under
oidc, the only account that can still sign in with a password.
Delegations
Choose who manages the devices of whom, and revoke a delegation from its row. What a delegation allows: Delegated Management. Delegations used to have a tab of their own; a browser that last had it open now opens Users with this section expanded.
Locked out of the admin account?
Lost the admin's local password, or need to provision one without a
browser? Run flask --app main.py create-admin <username> inside the
container — it creates the account as admin, or, if the account already
exists, grants admin and resets its password. Prompts for the password if
--password isn't given.