So You Wanna Scrobble
Now some of you may be asking, what the hell does "scrobble" mean? Well, it's a nonsense word for the most part, but it means "to submit your currently playing song to a service which tracks your listening history." Back in the early 2000s (2002 per a search just now), a service spun up called Audioscrobbler. The idea was that you'd play music, and your music player would send metadata about the song you were playing to Audioscrobbler's site, and eventually it would build up a sort of personal listening profile of you. You could share it with friends and say "hey, look at all the cool music I listen to! You should too!" or whatever. Or you could learn about others' music taste in turn, and discover new artists. It all started out very inauspiciously and homebrew, very chill. Eventually the venture capitalists and music industry took notice, and well, y'all know what that means. It became corporate and boring and annoying. The service rebranded as Last.fm, which was a more suitable name for the service, probably, but it was never the same. I don't like it anymore.
I was on Audioscrobbler/Last.fm for years and years, with thousands and thousands of playcounts. Eventually I left it, though, and decided to go with a more smallweb solution called Libre.fm. That site is fine, but it's very barebones, and I'm still having to submit data to somewhere I don't control. In an age where we have very little control over our data floating about in the world, I try to retain as much as I can. Hence this server, and its services, and whatever other smallweb things I use that largely circumvent the easy access, data-hungry corporations everywhere.
When looking for a Libre.fm alternative, I found ListenBrainz, which seems to be a pretty non-corporate, nice site for submitting listening data and such. It's associated with MusicBrainz, which in general is focused on correctly cataloguing music metadata. All for that. I found out that my music player of choice, Strawberry Music Player, is able to scrobble to ListenBrainz. Awesome! I just have to put in my API key for ListenBrainz (easily available in your user settings on the site, known as the "user token"). So that's pretty cool. I highly recommend it if you want a no-fuss alternative to Last.fm.
However, I was talking to one of my friends, and she said she self-hosts a software package called Koito which does pretty much the same thing. I looked at her Koito instance and thought it was super, super cool. And if you know anything about me, you know I'm down for self-hosting just about anything I can shake a stick at. Why not host it myself and keep all the data somewhere I control, rather than sending it elsewhere? So I thought, awesome, let's do this!
As you may know from perusing elsewhere on my site, I run my server on YunoHost, which is lovely. They have apps for most of the things I want, but unfortunately not everything. I found that the recommended easiest quickstart for Koito is via Docker, a system which, as far as I can tell, lets you create little "containers" for webapps to run on your server. Not dissimilar from YunoHost, but works a little differently. YunoHost has some limited documentation on installing "custom apps," but it was not very helpful. As usual, I found a YunoHost forum post, which, while it bumbled through things a bit, still helped me get started. I spent part of a weekend day setting up Koito according to those instructions, and then found that I couldn't set a custom ListenBrainz API URL for Strawberry. That's on me; I put the cart before the proverbial horse. So back to ListenBrainz I went, but I still wanted to find a way to use Koito, whether that meant changing music players or what.
I had an idea: what if I could get another intermediate program to "listen to" (i.e., track) what I was listening to in Strawberry, and then pass it along to Koito? That way I could set up a custom ListenBrainz API url and point it at Koito, rather than the official ListenBrainz site. And then we'd be all good. I really lucked out, because I found a small but mighty program called rescrobbled which uses MPRIS (Music Player Remote Interfacing Specification) to read the currently playing track. And Strawberry definitely uses MPRIS, since you can control it with a widget on the panel. So I think I found my pipeline: Strawberry -> MPRIS -> Koito! Now, if you're using a music player that allows a custom ListenBrainz URL, you can certainly omit the rescrobbled step, and just point it at your Koito API (https://<your Koito instance>/apis/listenbrainz/1 should work)
Installing Docker & Koito
Now, I can only speak for my experience using YunoHost (on Debian Linux). Your installation steps for Docker may be way different. Basically, install Docker on your system, whether it's local or on a VPS. If you've already installed it, and set up the Docker daemon to start on boot (these instructions are for systemd on Linux; YMMV), then move on.
If you're running Koito on a domain or subdomain, set that up, either on your computer, or in your DNS settings on your VPS. Everyone's installation is a bit different, so I can't provide for all those permutations. However, if you're setting it up on YunoHost, set up a domain/subdomain, then do the following:
- Install the YunoHost Redirect app on your Koito domain.
- Point the Redirect app, using the Reverse proxy mode, at http://127.0.0.1:4110 (I use 4110 because that's the default Koito port; if you change it [see below], use a different port here)
- That's it, you're done on the YunoHost side; the domain/subdomain should be able to reach Koito once it's up and running, which we'll do next.
Once Docker is installed and ready to go, you're ready to start installing Koito. Koito's quickstart suggests using Docker Compose, which seems to be an easier way to set up a Docker app container. Docker Compose uses a .yaml file for its configuration. I am really unfamiliar with yaml, except for using it a bit with Hugo, but it seems easy enough to follow. And the sample compose.yaml (I called it docker-compose.yaml on my installation) is an easy skeleton you can modify. Here's mine:
services:
koito:
image: gabehf/koito:latest
container_name: koito
depends_on:
- db
environment:
- KOITO_DATABASE_URL=postgres://postgres:<PostgreSQL password>@db:5432/koitodb
- KOITO_ALLOWED_HOSTS=<your Koito instance URL>,127.0.0.1:<4110, or your Koito port>
<note: optional parameters>
- KOITO_ENABLE_LBZ_RELAY=true
- KOITO_LBZ_RELAY_URL=https://api.listenbrainz.org/1
- KOITO_LBZ_RELAY_TOKEN=<your ListenBrainz user token>
<note: end optional parameters>
ports:
- "4110:4110" <note: you can use whatever port you prefer, but Koito defaults to 4110; use this above in KOITO_ALLOWED_HOSTS also>
volumes:
- ./koito-data:/etc/koito
restart: always <note: I set this to "always" instead of "unless-stopped" so it would start on boot with Docker>
db:
image: postgres:16
container_name: psql
restart: unless-stopped
environment:
POSTGRES_DB: koitodb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: <PostgreSQL password>
volumes:
- ./db-data:/var/lib/postgresql/data
So that's my Docker Compose config file. A few notes on some of the parameters within (please remove any <> part with note: at the start of it from your file!):
- KOITO_DATABASE_URL is a PostgreSQL URL pointing to the PostgreSQL database holding Koito's data. Think of it like an oldschool URL for username/password, like if you were logging into a FTP server in your browser. <login>:<password>@<domain>:<Koito port>/<Koito database name> is the URL scheme.
- Make up a strong password for after the postgres: username, then make sure to keep the "domain" as "db"; Docker does its own internal networking stuff, and it'll get the traffic routed to the right place.
- PostgreSQL defaults to port 5432, so you can easily keep that the same.
- KOITO_ALLOWED_HOSTS does exactly that: specifies what hosts are allowed to connect to the Koito instance.
- The first item in there should be your Koito instance URL; the domains/subdomain URL should be fine, go ahead and use https:// for it
- It also doesn't hurt to specify the localhost:port URL: https://127.0.0.1:<your Koito port>
- The following are optional settings I've enabled; feel free to omit them if they don't apply:
- KOITO_ENABLE_LBZ_RELAY=true means to enable relaying Koito submissions to ListenBrainz; either the main site, or another ListenBrainz-compatible server (it could even be gasp another Koito server!)
- KOITO_LBZ_RELAY_URL=<ListenBrainz API URL>: This is the URL to relay to; the main ListenBrainz URL is, at least at the time of writing, https://api.listenbrainz.org/1 (see here for more instructions). Here are the ListenBrainz API docs too.
- KOITO_LBZ_RELAY_TOKEN=<ListenBrainz user token>: This sets your ListenBrainz user token, which you can find here in ListenBrainz user settings. This allows Koito to authenticate to ListenBrainz and submit on your behalf.
- ports: sets the port Koito will listen on; as far as I know, both halves of the port:port pair should ideally be the same. They suggest 4110.
- POSTGRES_DB sets the PostgreSQL database name, which must match the <Koito database name> set above in the database URL.
- POSTGRES_USER sets the PostgreSQL username, which must match the <login> set above in the database URL.
- POSTGRES_PASSWORD sets the PostgreSQL password, which must match the <password> set above in the database URL.
Once you've set everything up within, you're ready to spin up the Koito instance:
- On Linux, make sure you're in the same directory as your Koito (docker-)compose.yaml file, and type:
docker compose up -d- This command will start the Docker container and keep it running in the background (-d for daemon).
- Go ahead and fire up a web browser to check out your Koito instance!
- Make sure to go into Settings -> Account, and "login" to your Koito instance with the default login & password "admin" and "changeme". Then immediately change the password to something secure.
- From there, go into Settings -> API Keys, and generate an API key for your music player. Keep this tab open after you generate it.
Setting Up Your Music Player
So now we've got Koito set up. But we need to set our music player up to submit its plays to the Koito instance. As I mentioned above, if you have a music player that will accept a custom ListenBrainz API URL, go ahead and set it to the following: https://<your Koito instance>/apis/listenbrainz/1/
- We also need to set an API key so that we can authenticate from the music player to Koito. Copy the API key from your Koito settings and use it in your music player.
However, if your music player, like mine, will only allow scrobbling to the main ListenBrainz server, then we need to take a different tack. This is where the little program rescrobbled comes in.
- Install rescrobbled by following the instructions on the site; it is written in Rust, AFAIK, so it can be installed easily using the crates system.
- Once rescrobbled is installed, we need to set up a configuration file so it knows where to send its plays; at least on Linux, this file will be located in ~/.config/rescrobbled/config.toml. The program doesn't ship with this, though, so we'll have to create the rescrobbled directory and its config file.
- Now you need to decide whether you want rescrobbled to track all plays through MPRIS, or just through your main music player. I only want it to count plays through Strawberry, so I put this line at the top of the config file:
player-whitelist = [ "strawberry" ] - Per the documentation, the ListenBrainz info needs to be at the bottom of the config file, below all the other options:
[[listenbrainz]]
url = "https://<your Koito instance>/apis/listenbrainz/1/"
token = "<your Koito API key>"
Make sure you pull your Koito API key from the Koito instance in Settings -> API Keys.
I also highly recommend setting up rescrobbled as a systemd service; the service file is provided by the author, and needs to be placed in ~/.config/systemd/user. Go ahead and follow the rescrobbled instructions here under Usage to set up the systemd service. That way you can have it start every time you fire up your computer.
Now, go ahead and play your music; it should all send to your Koito instance (and ListenBrainz, if desired, via the relay), either directly from your music player, or via rescrobbled!
Koito & Streaming Apps
Let's say you, like me, are super geeky about all of this. Not only do you want to track music played on your computer through Koito, but also through your favorite streaming app. I prefer to stream music via my phone a lot while I'm working, since I don't have my (personal) laptop running during that time. Best case scenario is if you can find something that will allow you to access it through a Subsonic-compatible client. I use DSub2000 (available on F-Droid) personally. DSub2000 will let you set it to Scrobble to Last.fm (Settings -> Playback), which of course can use ListenBrainz as well.
Here are a couple of good options for self-hosted music streaming servers:
- Navidrome*
- *caveat: Navidrome devs are using AI to code; that link is just one AI-coded merged pull request I found, and I doubt it's the only one. If you are not OK with that, then I'd recommend using another program.
- Funkwhale is a good option, but it unfortunately didn't fit my use case personally, so I switched back to Navidrome. I don't love the AI part of it, at all, but the program works extremely well otherwise.
- The Nextcloud Music app is a very easy way to get up and running if you already have Nextcloud installed. It has a Subsonic backend that you can easily connect to with apps. That was my first streaming music solution, and it's a great one, especially if you're just starting out.
Basically, decide on a solution, and ideally it'll let you specify a custom ListenBrainz URL. Below, please find how I got Funkwhale to work with Koito (hacky workaround, but oh well).
Koito & Funkwhale
Once you've installed Funkwhale (pretty straightforward via YunoHost), we have to do a little manual tweaking. Now I don't mean just tweaking the configuration. That part is relatively easy, but this is a little more obscure. Funkwhale's ListenBrainz plugin is hardcoded to access only the main ListenBrainz server. That's all good and fine if we're just scrobbling to ListenBrainz, but we presumably would like to send it to our Koito server instead, which, again, can handle ListenBrainz requests just fine. At the time of writing, the most recent Funkwhale version is 1.4.1, which has integrated an old ListenBrainz scrobbler plugin that still works just fine. I looked at the code for the development branch, and they seem to have ditched this plugin for a Python library called liblistenbrainz, so we may have to update this tweak whenever that ships. It's fine.
So the nice thing is that this is all open-source, right? So we can modify the ListenBrainz plugin to point at our Koito server instead. I really wish there were a GUI option for this, but oh well. We make do. Now follow these steps:
- SSH into your server, and become the root user (
sudo suis an easy way to do this). - Change to the ListenBrainz plugin directory:
cd /var/www/funkwhale/api/funkwhale_api/contrib/listenbrainz - Open a text editor (e.g., pico), and edit the file client.py:
pico client.py - Find the following lines (not far from the top of the file), and change them as follows:
HOST_NAME = "<Koito hostname>"PATH_SUBMIT = "/apis/listenbrainz/1/submit-listens"
- Save the file
- Either restart the Funkwhale services (YunoHost web interface -> Tools -> Services) or restart your server (YunoHost web interface -> Tools -> Shutdown/Reboot)
Now that Funkwhale knows how to send scrobbles to your Koito server, you can follow the Funkwhale ListenBrainz plugin documentation and enter your API key from Koito. I'd recommend generating an API key for Funkwhale too (see instructions above). Now login to your Funkwhale server on your streaming app (via Subsonic ideally), tell it to scrobble, and it'll use the info saved in Funkwhale to route that correctly! Yay!
Koito & Navidrome
In Navidrome, we have to do a few things before we can set up scrobbling to Koito or another ListenBrainz-compatible instance. This involves manually editing the navidrome.toml file, which is the configuration file. There are a ton of options within, but only one that we care about for our purposes.
- Open the Navidrome configuration file; in YunoHost, it is typically located at /home/yunohost.app/navidrome/navidrome.toml
- Add the following lines, set off by a line between other options:
# ListenBrainz for Koito
ListenBrainz.BaseURL = "https://<your Koito instance>/apis/listenbrainz/1/"
- Restart Navidrome (in YunoHost, you can run
sudo yunohost service restart navidromein the shell on your server). Now the API URL is set so we can authenticate. - This is optional, but I would recommend going into your Koito instance, then Settings -> API Keys, and generating a new API Key specifically for Navidrome. Copy it.
- Login to Navidrome, and go to Settings -> Personal, and click "Scrobble to ListenBrainz"
- Navidrome will then ask you for the API key. Paste the one you just generated. If it is all set up correctly, you'll get a green banner saying Navidrome and ListenBrainz are linked!
You should be all set now! Go and enjoy sharing your music taste with the rest of the world, and also enjoy looking back at trends in your listening habits! I'm happy to try to answer any questions I can otherwise. Thanks for reading, friends! <3
- ← Previous
Panta Rheusetai - Next →
Annus Elapsus