Overview
Docker
Section titled “Docker”Cross-platform images are built for x86 (Intel/AMD) and ARM64 (IE Raspberry Pi)
Recommended Settings
Section titled “Recommended Settings”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 filesIf 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"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://hostMachineIPWhen 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://YOUR_MS_DOMAIN/multiscrobblerThis 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://YOUR_MS_DOMAIN/multiscrobbler # ... environment: # ... # multi-scrobbler served under this subpath - BASE_URL=https://YOUR_MS_DOMAIN/multiscrobblerSet 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_YorkIf 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:noexecOptionally, 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: localDocker Usage Example
Section titled “Docker Usage 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://YOUR_MS_DOMAIN - 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: localLocal Installation
Section titled “Local Installation”After installation see As a Service to configure multi-scrobbler to run automatically in the background.
Nodejs
Section titled “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.gitcd multi-scrobblernpm installnpm run docs:install && npm run buildnpm run start- 1.optional, to set correct Node version
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
Section titled “Usage Examples”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",only scrobbles to the Client with this name "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 startPersistent Directories
Section titled “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)
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…
$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…
$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…
$XDG_STATE_HOME/multi-scrobbler or ~/.local/state/multi-scrobbler
~/Library/Logs/multi-scrobbler
%LOCALAPPDATA%\multi-scrobbler\Log
Reverse Proxy Recommended
Section titled “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:
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.