---
sidebar_position: 2
title: Overview
toc_max_heading_level: 3
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
import SchemaLink from "../../src/components/SchemaLink";
import AIOExample from "../../src/components/AIOExample";
import FileExample from "../../src/components/FileExample";
import ScrobbleThreshold from "@site/src/components/snippets/_scrobble-threshold.mdx"

import AIOConfig from '!!raw-loader!../../../config/config.json.example';
import SpotifyConfig from '!!raw-loader!../../../config/spotify.json.example';

:::tip

Check the [**FAQ**](../FAQ.md) if you have any issues after configuration!

:::

## Configuration Types

[**Sources**](/configuration/sources) and [**Clients**](/configuration/clients) are configured using:

* environmental (ENV) variables
* client/source specific json config files
* an all-in-one json config file

**MS will parse configuration from all configuration types.** You can mix and match configurations but it is generally better to stick to one or the other.

<Tabs groupId="configType" queryString>
    <TabItem value="env" label="ENV">
        MS will parse environmental variables present in the OS/container when it is run. **This method means MS does not require files to run.**

        <details>
          <summary>Use ENV-based configuration if...</summary>

          * You are the only person for whom MS is scrobbling for
          * You have a very simple setup for MS such as one scrobble [Client](/configuration/clients) and one [Source](/configuration/sources) IE Plex -> Maloja

        </details>

        <details>
          <summary>Config Example</summary>

          For Docker container...

          ```shell
          docker run -e "SPOTIFY_CLIENT_ID=yourId" -e "SPOTIFY_CLIENT_SECRET=yourSecret" ...
          ```

          For Docker Compose

          ```yaml title="docker-compose.yml"
          services:
              multi-scrobbler:
                  image: foxxmd/multi-scrobbler
                  environment:
                      - SPOTIFY_CLIENT_ID=yourId
                      - SPOTIFY_CLIENT_SECRET=yourSecret
                      - MALOJA_URL=http://domain.tld:42010
                      - MALOJA_API_KEY=1234
                      # ...
                  # ...
          ```

          For a local/node installation export variables before running...

          ```shell
          SPOTIFY_CLIENT_ID=yourId SPOTIFY_CLIENT_SECRET=yourSecret npm run start
          ```
        </details>
    </TabItem>
    <TabItem value="file" label="File">
        MS will parse configuration files located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to:

        * Local installation -> `PROJECT_DIR/config`
        * Docker -> `/config` (in the container) -- see the [install docs](../installation/installation.mdx#docker) for how to configure this correctly

        <details>

            <summary>Use File-based configuration if...</summary>

            * You have many [Sources](/configuration/sources)
            * You have many of each type of **Source** you want to scrobble from IE 2x Plex accounts, 3x Spotify accounts, 1x
            Funkwhale...
            * You have more than one scrobble **Client** you want to scrobble to IE multiple Maloja servers
            * You want only to scrobble to specific **Clients**
            * You need to setup more advanced configuration for a Source/Client
              * Most Source/Clients only support basic configuration through ENV, all configuration is possible using File/AIO

        </details>

        :::tip
            * There are **example configurations** for all Source/Client types and AIO config located in the [`/config`](https://github.com/FoxxMD/multi-scrobbler/tree/master/config) directory of this project. These can be used as-is by renaming them to `.json`.
            * For docker installations these examples are copied to your configuration directory on first-time use.
            * There is also a [**kitchensink example**](/configuration/kitchensink) that provides examples of using all sources/clients in a complex configuration.
        :::

        Each file is named by the **type** of the Client/Source found in below sections. Each file as an **array** of that type of Client/Source.

        Example directory structure:

        ```
        /CONFIG_DIR
            plex.json
            spotify.json
            maloja.json
        ```

        <details>
            <summary>Config Example</summary>

            <CodeBlock title="CONFIG_DIR/spotify.json" language="json5">{SpotifyConfig}</CodeBlock>

        </details>
    </TabItem>
    <TabItem value="aio" label="File AIO">
        MS will parse an **all-in-one** configuration file located in the directory specified by the `CONFIG_DIR` environmental variable. This variable defaults to:

        * Local installation -> `PROJECT_DIR/config/config.json`
        * Docker -> `/config/config.json` (in the container) -- see the [install docs](../installation/installation.mdx#docker) for how to configure this correctly

        <details>

            <summary>Use AIO-based configuration if...</summary>

            * You have many [Sources](/configuration/sources)
            * You have many of each type of **Source** you want to scrobble from IE 2x Plex accounts, 3x Spotify accounts, 1x
            Funkwhale...
            * You have more than one scrobble **Client** you want to scrobble to IE multiple Maloja servers
            * You want only to scrobble to specific **Clients**
            * You need to setup [monitoring/webhooks](#monitoring)
            * You want to setup defaults for all Sources/Clients

        </details>

        **The AIO config also enables setting default options for sources/clients as well as global options for MS itself.**

        :::tip
            * An example AIO config files can be found in the project directory at [`/config/config.json.example`](https://github.com/FoxxMD/multi-scrobbler/tree/master/config/config.json.example)
            * For docker installations this example is copied to your configuration directory on first-time use.
            * There is also a [**kitchensink example**](/configuration/kitchensink) that provides examples of using all sources/clients in a complex configuration.
        :::

        [**Explore the schema for this configuration, along with an example generator and validator, here**](https://json-schema.app/view/%23?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)

        <details>

            <summary>Config Example</summary>

            <CodeBlock title="CONFIG_DIR/config.json" language="json5">{AIOConfig}</CodeBlock>

        </details>
    </TabItem>
</Tabs>

## Setup Sources and Clients

See the [Configuration Types](#configuration-types) above for your options for creating Source and Client configurations.

* Reference [**Scrobble Sources**](/configuration/sources) for what Sources are available
* Reference [**Scrobble Clients**](/configuration/clients) for what Clients are available

Each entry for a Source/Client includes a **Configuration** section that describes how to configure it using a [configuration type](#configuration-types).

## Application Options

These options affect multi-scrobbler's behavior and are not specific to any source/client.

### Base URL

Defines the URL that is used to generate default redirect URLs for authentication on [spotify](/configuration/sources/spotify) and [lastfm](/configuration/clients/lastfm) -- as well as some logging hints.

* Default => `http://localhost:9078`
* Set with [ENV](./?configType=env#configuration-types) `BASE_URL` or `baseUrl` [all-in-one configuration](./?configType=aio#configuration-types)
* If protocol is `http` or no protocol is specified MS will try to use port `9078` -- to override this explicitly set the port or use `https`

Useful when running with [docker](../installation/installation.mdx#docker) so that you do not need to specify redirect URLs for each configuration.

<details>

    <summary>Example</summary>

    EX Lastfm Redirect Url is `BASE_URL:PORT/lastfm/callback` (when no other redirectUri is specified for [lastfm configuration](/configuration/clients/lastfm))

    | `BASE_URL`                          | Redirect URL                                             |
    |-------------------------------------|----------------------------------------------------------|
    | `192.168.0.101`                     | `http://192.168.0.101:9078/lastfm/callback`              |
    | `http://my.domain.local`            | `http://my.domain.local:9078/lastfm/callback`            |
    | `http://192.168.0.101/my/subfolder` | `http://192.168.0.101:9078/my/subfolder/lastfm/callback` |

    | `BASE_URL`                        | Redirect URL                                             |
    |-----------------------------------|----------------------------------------------------------|
    | `my.domain.local:80`              | `http://192.168.0.101:80/lastfm/callback`                |
    | `my.domain.local:9000`            | `http://my.domain.local:9000/lastfm/callback`            |
    | `192.168.0.101:4000/my/subfolder` | `http://192.168.0.101:4000/my/subfolder/lastfm/callback` |
    | `https://192.168.0.101`           | `https://192.168.0.101:443/lastfm/callback`              |

</details>

### Caching

Multi-scrobbler can cache some of its data for the purpose of **persisting queued and dead scrobbles** after restarting.

It supports caching using either:

* **File** cache stored in the `CONFIG_DIR` directory (next to your File/[AIO](./?configType=aio#configuration-types) file)
* [**Valkey**](https://valkey.io/), an open-source fork of Redis.

**File** caching is **enabled by default** when no other configuration is present.

The type of cache used, and it's connection properties, can be configured through ENV or **AIO** config.

##### Caching Configuration

<Tabs groupId="cache" queryString>

<TabItem value="file" label="File">

**File** cache is stored in the `CONFIG_DIR` directory using the pre-defined file name `ms-scrobble.cache`.

It is **enabled by default** if `CACHE_SCROBBLE`, or the respective AIO configuration, is not defined.

<Tabs groupId="configType" queryString>

<TabItem value="env" label="ENV">

| Environmental Variable | Required? | Default              | Description                                                  |
| :--------------------- | --------- | -------------------- | ------------------------------------------------------------ |
| `CACHE_SCROBBLE`       | No        | `file`               | The cache type to use                                        |
| `CACHE_SCROBBLE_CONN`  | No        | The config directory | The directory, within the container, to store the cache file |

</TabItem>

<TabItem value="aio" label="AIO">

```json5 title="config.json"
{
    "cache": {
        "scrobble": {
            "provider": "file",
            "connection": "/config"
        }
    },
    // ...
}
```

</TabItem>

</Tabs>
</TabItem>

<TabItem value="valkey" label="Valkey">

<Tabs groupId="configType" queryString>

<TabItem value="env" label="ENV">

| Environmental Variable | Required? | Default              | Description                                                  |
| :--------------------- | --------- | -------------------- | ------------------------------------------------------------ |
| `CACHE_SCROBBLE`       | Yes        | `valkey`               | The cache type to use                                      |
| `CACHE_SCROBBLE_CONN`  | Yes        |  | The host/IP and port to connect to, prefixed with `redis://` -- EX: `redis://192.168.0.120:6379` |

</TabItem>

<TabItem value="aio" label="AIO">

```json5 title="config.json"
{
    "cache": {
        "scrobble": {
            "provider": "valkey",
            "connection": "redis://192.168.0.120:6379"
        }
    },
    // ...
}
```

</TabItem>

</Tabs>
</TabItem>

</Tabs>

### Debug Mode

Turning on Debug Mode will

* override and enable all optional "debugging" options found in configuration
* set log output to DEBUG

Use this as a shortcut for enabling output that can be used for troubleshooting and issue reporting. Be aware that logs will likely be VERY noisy while Debug Mode is on. You should only have this mode on while gathering logs for troubleshooting and then turn it off afterwards.

To set debug mode either add it to [AIO `config.json`](./?configType=aio#configuration-types)

```json5 title="config.json"
{
    "debugMode": true,
    "sources": [...],
    // ...
}
```

or set the [ENV](./?configType=env#configuration-types) `DEBUG_MODE=true`

### Disable Web

If you do not need the dashboard and/or ingress sources, or have security concerns about ingress and cannot control your hosting environment, the web server and API can be disabled.

:::warning

Any **[ingress-based sources](/configuration/sources#ingress) will be unusable** (Webscrobbler, etc...) if this is disabled.

:::

Disable using either:

* ENV `DISABLE_WEB=true`
* In [All-in-One File](./?configType=aio#configuration-types) use the top-level property `"disableWeb": true`

## Monitoring

Multi-scrobbler supports some common webhooks and a healthcheck endpoint in order to monitor Sources and Clients for errors.

### Webhook Configurations

Webhooks will **push** a notification to your configured servers on these events:

* Source polling started 
* Source polling retry
* Source polling stopped on error 
* Scrobble client scrobble failure

Webhooks are configured in the AIO [config.json](#configuration-types) file under the `webhook` top-level property. Multiple webhooks may be configured for each webhook type.

<details>

    <summary>Example</summary>

    ```json5 title="config.json"
    {
      "sources": [
        //...
      ],
      "clients": [
        //...
      ],
      "webhooks": [
        {
          "name": "FirstGotifyServer",
          "type": "gotify",
          "url": "http://192.168.0.100:8070",
          "token": "abcd"
        },
        {
          "name": "SecondGotifyServer",
          "type": "gotify",
          //...
        },
        {
          "name": "NtfyServerOne",
          "type": "ntfy",
          //...
        },
        //...
      ]
    }
    ```

</details>

#### [Gotify](https://gotify.net/)

Refer to the [config schema for GotifyConfig](https://json-schema.app/view/%23/%23%2Fdefinitions%2FGotifyConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)

multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings.

<details>

    <summary>Example</summary>

    ```json title="config.json"
    {
      "type": "gotify",
      "name": "MyGotifyFriendlyNameForLogs",
      "url": "http://192.168.0.100:8070",
      "token": "AQZI58fA.rfSZbm",
      "priorities": {
        "info": 5,
        "warn": 7,
        "error": 10
      }
    }
```

</details>

#### [Ntfy](https://ntfy.sh/)

Refer to the [config schema for NtfyConfig](https://json-schema.app/view/%23/%23%2Fdefinitions%2FNtfyConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)

multi-scrobbler optionally supports setting message notification priority via `info` `warn` and `error` mappings.

<details>

    <summary>Example</summary>

    ```json title="config.json"
    {
      "type": "ntfy",
      "name": "MyNtfyFriendlyNameForLogs",
      "url": "http://192.168.0.100:9991",
      "topic": "RvOwKJ1XtIVMXGLR",
      "username": "Optional",
      "password": "Optional",
      "priorities": {
        "info": 3,
        "warn": 4,
        "error": 5
      }
    }
```

</details>

#### [Apprise](https://github.com/caronc/apprise-api)

Refer to the [config schema for AppriseConfig](https://json-schema.app/view/%23/%23%2Fdefinitions%2FAppriseConfig?url=https%3A%2F%2Fraw.githubusercontent.com%2FFoxxMD%2Fmulti-scrobbler%2Fmaster%2Fsrc%2Fbackend%2Fcommon%2Fschema%2Faio.json)

multi-scrobbler supports [stateless](https://github.com/caronc/apprise-api?tab=readme-ov-file#stateless-solution) and [persistent storage](https://github.com/caronc/apprise-api?tab=readme-ov-file#persistent-storage-solution) endpoints as well as [tags](https://github.com/caronc/apprise-api?tab=readme-ov-file#tagging)/

<details>

    <summary>Example</summary>

    ```json5 title="config.json"
    {
      "type": "apprise",
      "name": "MyAppriseFriendlyNameForLogs",
      "host": "http://192.168.0.100:8080",
      "urls": ["gotify://192.168.0.101:8070/MyToken"], // stateless endpoints
      "keys": ["e90b20526808373353afad7fb98a201198c0c3e0555bea19f182df3388af7b17"], //persistent storage endpoints
      "tags": ["my","optional","tags"]
    }
    ```

</details>

### Health Endpoint

An endpoint for monitoring the health of sources/clients is available at GET `http://YourMultiScrobblerDomain/health`

* Returns `200 OK` when **everything** is working or `500 Internal Server Error` if **anything** is not 
* The plain url (`/health`) aggregates status of **all clients/sources** -- so any failing client/source will make status return 500 
  * Use query params `type` or `name` to restrict client/sources aggregated IE `/health?type=spotify` or `/health?name=MyMaloja`
* On 500 the response returns a JSON payload with `messages` array that describes any issues
  * For any clients/sources that require authentication `/health` will return 500 if they are **not authenticated** 
  * For sources that poll (spotify, yt music, subsonic) `/health` will 500 if they are **not polling**
