Skip to content

Overview

Cross-platform images are built for x86 (Intel/AMD) and ARM64 (IE Raspberry Pi)

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.

docker-compose.yml
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:

docker-compose.yml
services:
multi-scrobbler:
# ...
environment:
# ...
- DATA_DIR=/msData
volumes:
- "./config:/config" # used for config files
- "./my/host/folder:/msData" # used for data files

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.

docker-compose.yml
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: local

After installation see As a Service to configure multi-scrobbler to run automatically in the background.

Clone this repository somewhere using the latest git tag and then install from the working directory.

Terminal window
git clone --branch <LATEST_RELEASE_TAG> https://github.com/FoxxMD/multi-scrobbler.git
cd multi-scrobbler
nvm use1
npm install
npm run docs:install && npm run build
npm run start
  1. 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.

Terminal window
JELLYFIN_APIKEY=c9fae8756fbf481ebd9c5bb56bd6540c JELLYFIN_URL=192.168.0.101:8096 JELLYFIN_USER=MyUser MALOJA_URL="http://domain.tld" node src/index.js

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 files
  • DATA_DIR=./relative/data => sets directory relative to working directory for data files
  • LOGS_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

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
}
}