Overview
For the difference between ENV and File examples in this document see Configuration Types.
Docker
Cross-platform images are built for x86 (Intel/AMD) and ARM64 (IE Raspberry Pi)
- Dockerhub
- Github Packages
docker.io/foxxmd/multi-scrobbler:latest
ghcr.io/foxxmd/multi-scrobbler:latest
Recommended Settings
- Storage
- Networking
- Base URL
- Timezone
- Linux Host
- Read Only
- Caching
You should bind a host directory into the container for storing configurations, credentials, database, and other files. Otherwise, these will be lost when the container is updated.
services:
multi-scrobbler:
# ...
volumes:
- "./config:/config"
Optionally, use a separate directory for data (database, cache, etc...) by mounting an additional directory and setting the DATA_DIR ENV to the directory that should be used inside the container:
services:
multi-scrobbler:
# ...
environment:
# ...
- DATA_DIR=/msData
volumes:
- "./config:/config" # used for config files
- "./my/host/folder:/msData" # used for data files
If you are using a bridge network (default docker setup) you must map a port to the container in order to access the dashboard and use MS with some sources (Webscrobbler, LFM/LZ Endpoints). The default container port is 9078.
services:
multi-scrobbler:
# ...
ports:
- "9078:9078"
If your machine is accessible from the public internet consider installing multi-scrobbler on a different, private machine.
- Redirects
- Deploying MS with a Subpath
Optionally, when
- using a Source or Client that has a "Redirect URI" that you have not explicitly defined
- and
- using a bridge network or
- installing MS on a different machine than the one used to view the dashboard
set the Base URL as the IP/domain of the host machine. (This is the IP you would use to view the dashboard in a browser)
services:
multi-scrobbler:
# ...
environment:
- BASE_URL=http://hostMachineIP
When deploying MS to a domain where it will be served under a subpath, like http://mydomain.com/multiscrobbler, you must define BASE_URL:
services:
multi-scrobbler:
# ...
environment:
# multi-scrobbler served under this subpath
- BASE_URL=https://mydomain.com/multiscrobbler
This is not required when the root path is /, like https://my-scrobbler.com or scrobbler.mydomain.com.
Self-Hosted Docs
Multi-Scrobbler's docs are at docs.multi-scrobbler.app but they are also generated and hosted on your instance.
If you are using a subpath and need these self-hosted docs as well you will need to build your own docker image. This is a limitation of Docusaurus, the framework the docs are built on.
This build step is optional and not required for MS to run with a subpath, you just won't have self-hosted docs and will need to use the official, hosted docs instead.
To build MS with self-hosted docs, provide the same BASE_URL used above as a build arg:
services:
multi-scrobbler:
## remove/comment out official image
# image: docker.io/foxxmd/multi-scrobbler:latest
## add build spec
build:
context: https://github.com/FoxxMD/multi-scrobbler.git
args:
- BASE_URL=https://mydomain.com/multiscrobbler
# ...
environment:
# ...
# multi-scrobbler served under this subpath
- BASE_URL=https://mydomain.com/multiscrobbler
Set the timezone for the container using the environmental variable TZ.
services:
multi-scrobbler:
# ...
environment:
# Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
- TZ=America/New_York
If you are running this container with Docker on a Linux Host you should specify user:group permissions of the user who owns the configuration and data directories on the host to avoid docker file permission problems. These can be specified using the environmental variables PUID and PGID.
To get the UID and GID for the current user run these commands from a terminal:
id -u-- prints UIDid -g-- prints GID
MS can be hardended by setting the file system as read only with read_only, with a few exceptions:
services:
multi-scrobbler:
image: foxxmd/multi-scrobbler
# ...
read_only: true
tmpfs:
- /run:exec
- /tmp:noexec
Optionally, add a Valkey service to your stack for secondary caching to take advantage of faster performance, reduced memory usage, and cached api calls to external services.
services:
multi-scrobbler:
image: foxxmd/multi-scrobbler
# ...
environment:
# ...
CACHE_VALKEY=redis://valkey:6379
# ...
valkey:
image: valkey/valkey
volumes:
- valkeydata:/data
volumes:
valkeydata:
driver: local
Docker Usage Example
See the Quick Start Guide for another guided docker-compose example
The example scenario:
- Jellyfin Source
- Maloja Client
- Serving app on port
9078 - Docker container located on a different IP (
192.168.0.100) so use Base URL - Config/data directory on host machine in a directory next to
docker-compose.yml - Linux uid/gid is
1000:1000 - Optional caching using valkey (after uncommenting)
See docker-compose.yml sample above for more options and annotations.
services:
multi-scrobbler:
image: foxxmd/multi-scrobbler
container_name: multi-scrobbler
environment:
- TZ=Etc/GMT # Specify timezone from TZ Database name found here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
- JELLYFIN_APIKEY=c9fae8756fbf481ebd9c5bb56bd6540c
- JELLYFIN_URL=192.168.0.101:8096
- JELLYFIN_USER=MyUser
- BASE_URL=http://192.168.0.100:9078
- MALOJA_URL=http://domain.tld:42010
- MALOJA_API_KEY=1234
- PUID=1000
- PGID=1000
# uncomment along with valkey service/volume below for better caching
#- CACHE_VALKEY=redis://valkey:6379
volumes:
- ./config:/config
ports:
- 9078:9078
restart: unless-stopped
#valkey:
# image: valkey/valkey
# volumes:
# - valkeydata:/data
#volumes:
# valkeydata:
# driver: local
Local Installation
After installation see As a Service to configure multi-scrobbler to run automatically in the background.
Nodejs
Clone this repository somewhere using the latest git tag and then install from the working directory.
git clone --branch <LATEST_RELEASE_TAG> https://github.com/FoxxMD/multi-scrobbler.git
cd multi-scrobbler
nvm use # optional, to set correct Node version
npm install
npm run docs:install && npm run build
npm run start
Pass ENVs directly to node/npm, or make a new .env (using .env.example as a reference), to configure MS for basic settings and Persistent Directories for config/data/log directories.
Usage Examples
Regardless of the config type you are using, some settings must be set via ENV such as Persistent Directories for config/data/log directories.
- ENV
- File
JELLYFIN_APIKEY=c9fae8756fbf481ebd9c5bb56bd6540c JELLYFIN_URL=192.168.0.101:8096 JELLYFIN_USER=MyUser MALOJA_URL="http://domain.tld" node src/index.js
./config/config.json
{
"sources": [
{
"type": "jellyfin",
"clients": ["myConfig"],
"name": "myJellyfinSource",
"data": {
"apiKey": "a89cba1569901a0671d5a9875fed4be1",
"url": "http://192.168.0.101:8096",
"user": "MyUser"
}
}
],
"clients": [
{
"type": "maloja",
"name": "myConfig",
"data": {
"url": "http://localhost:42010",
"apiKey": "myMalojaKey"
}
}
],
}
npm run start
The web UI and API is served on port 9078. This can be modified using the PORT environmental variable.
Persistent Directories
The directories MS uses for
- Configuration -
config.json,jellyfin.json, etc... - Data - database, cache, etc...
- Logs
can be specified by environmental variables passed directly to npm/node, or set in an .env file in the working directory.
Settings these paths is optional. If you do not set paths MS will try to use OS-standardized directories, falling back to subfolders in the working directory (.config/). Note: These paths are automatically set for you when using Docker.
Relative and Absolute Paths Only
When parsing these ENVs MS will resolve relative directories but not bash expansions like ~ for home. Examples:
CONFIG_DIR=/my/absolute/path=> sets directory to use for config filesDATA_DIR=./relative/data=> sets directory relative to working directory for data filesLOGS_DIR=~/myDir/logs=> ❌ cannot use this path!
(The bash expansions shown below are for example only)
- Config
- Data
- Logs
All of your configuration files, like config.json, jellyfin.json, etc... will be read from this directory.
Order of path acquisition:
$CONFIG_DIR- user-defined (or auto defined in Docker image)$CONFIGURATION_DIRECTORY- defined by systemd- OS-standardized directory from below...
- Linux
- MacOS
- Windows
$XDG_CONFIG_HOME/multi-scrobbler or ~/.config/multi-scrobbler
~/Library/Preferences/multi-scrobbler
%APPDATA%\multi-scrobbler\Config
All of the persistent data -- like the database (ms.db), cache, and credential files -- will be written to this directory.
Order of path acquisition:
$DATA_DIR- user-defined (or auto defined in Docker image)$STATE_DIRECTORY- defined by systemd- OS-standardized directory from below...
- Linux
- MacOS
- Windows
$XDG_DATA_HOME/multi-scrobbler or ~/.local/share/multi-scrobbler
~/Library/Application Support/multi-scrobbler
%LOCALAPPDATA%\multi-scrobbler\Data
Logs will be written to this directory.
Order of path acquisition:
$LOGS_DIR- user-defined (or auto defined in Docker image)$LOGS_DIRECTORY- defined by systemd- OS-standardized directory from below...
- Linux
- MacOS
- Windows
$XDG_STATE_HOME/multi-scrobbler or ~/.local/state/multi-scrobbler
~/Library/Logs/multi-scrobbler
%LOCALAPPDATA%\multi-scrobbler\Log
Reverse Proxy Recommended
Multi-Scrobbler's UI performs best when it is behind a reverse proxy, like NGINX (NPM) Traefik or Caddy.
Why: Security
Most reverse proxies have easy ways to set up basic authentication which a necessity if you plan on running Multi-Scrobbler on a machine directly exposed to the internet.
Why: Connection Pooling and Live Events
For connections to domains using HTTP/1.1 (non-TLS http: addresses like http://192.168.0.101) all major browsers use a shared connection pool per domain, that is used across all tabs. This connection pool is limited to 6 concurrent connections.
For non-TLS connections Multi-Scrobbler uses one, always-open SSE connection per tab to send live updates and logs to your browser.
So, with HTTP/1.1, if you open more than 5 tabs of multi-scrobbler you will not be able to communciate to the server through your browser.
Using TLS (like https://ms.mydomain.com), which reverse proxies make easy, removes this connection limit for the pool.
Additionally, using TLS unlocks the ability for Multi-Scrobbler to share a single SSE connection between all tabs which reduces the bandwidth used by all tabs signficantly.
Disable Buffering for Searches
When Multi-Scrobbler performs metadata searches for your Play data it streams results from providers as soon as they arrive, rather than waiting for all providers to respond. This can significantly speed up how soon you see search results in your browser.
Some reverse proxies automatically enable buffering for requests which is usually a good thing but in this scenario prevents you from benefiting streaming results because buffering waits for the entire response before forwarding it to your browser.
Use one of the common methods below to disable buffering for search-related routes. Note: these are not complete solutions, just examples as a jumping off point:
- Caddy
- nginx
- Traefik
Set flush_interval -1 to disable response buffering.
multi-scrobbler.domain.tld {
reverse_proxy multi-scrobbler:9078
@search {
method POST GET
path /api/metadata/search/*
}
reverse_proxy @search multi-scrobbler:9078 {
flush_interval -1
}
}
NGINX
location /your-route {
proxy_pass http://your_backend;
proxy_buffering off;
}
Traefik does not automatically enable buffering. If you use the Buffering middleware then responses are automatically buffered and cannot be disabled, yet.