Skip to main content

Overview

tip

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)

Available Images

Repository Page

docker.io/foxxmd/multi-scrobbler:latest

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

Docker Usage Example​

tip

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.

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://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​

note

Regardless of the config type you are using, some settings must be set via ENV such as Persistent Directories for config/data/log directories.

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

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

}