Self-hosted service
krateng/maloja avatar
krateng/maloja

Maloja: a self-hosted scrobble database for people who want their listening history to stay theirs

Self-hosted music scrobble database to create personal listening statistics and charts

1,813 stars98 forksPythonGPL-3.0

At a glance

What is it?
Maloja is a Python scrobble server you run yourself, storing listening history in a parseable format and rendering charts from it. It is aimed at people who want Last.fm-style statistics without the social layer, and it is distributed as a container first.
Who is it for?
Adopt Maloja if you already run containers, want your scrobble history in a file you control, and accept that it will not recommend anything to you. Do not adopt it if you want a hosted service, a mobile app, or a bare-metal install the maintainer will support: the README says Maloja should only be used in Docker or Podman and that no help is offered for bare metal.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 34 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Maloja solves is ownership of scrobble history, not discovery

Last.fm stores your listening history on someone else's server, in someone else's schema, behind someone else's rate limits and API changes. Maloja inverts that: the README describes it as a "self-hosted music scrobble database", and the first listed feature is that you "will always be able to access your data in an easily-parseable format". That sentence is the whole pitch. The library is not reconciled against a public music database, so a track called whatever you tagged it as stays called that. If you have spent years correcting artist spellings in your own files, that matters more than any chart feature.

The target user is narrow on purpose. The README states plainly that "unlike Last.fm and similar alternatives, Maloja doesn't have social networking, radios, recommendations or any other gimmicks. It's a tool to keep track of your listening habits over time - and nothing more." There is no friend feed, no neighbour radio, no weekly recommendation email. If your reason for scrobbling is to compare tastes with other people, this is not the project for you, and the maintainer is not pretending otherwise. If your reason is to see what you actually played in March, it is.

How Maloja models artists: associations, multi-artist tracks and images

The interesting design work is in artist identity, which is where most scrobble databases get awkward. Maloja has a feature it calls Associated Artists: you can mark that a subunit, a collaboration project or a solo project belongs to a parent artist, and the charts then compare the parent's popularity across your listening. The README notes you can "change these associations at any time without losing any information", which implies the association is stored separately from the scrobble records rather than baked into them. That is the right call. Rewriting history every time you decide that a side project counts is how you end up with a database you cannot trust.

Multi-Artist Tracks attack the same problem from the other side. When a track is credited to two artists or has a "featuring" credit in the title, Maloja does not create a synthetic combined artist entry. Instead "each individual artist competes in your charts". So a featured verse counts toward the featured artist's total rather than spawning a one-off duo entry that appears exactly once in your statistics and never again. Both of these are schema decisions, and both are visible in the feature list rather than in a separate design document.

Custom Images is the third part. Rather than waiting for a community image database to pick a good picture, you upload your own by dragging them onto the artist or track page while admin mode is active, or by managing files directly. The README points at images.info in /var/lib/maloja/images for the file-system route. Note the dependency: displaying images at all requires API keys for Last.fm and Spotify, which the README says are free of charge. Without those keys, the charts still work but the artwork does not.

Running Maloja: the container command and the three environment variables that matter

The README is unusually blunt about deployment. It says Maloja "should only be used in Docker or Podman, not on bare metal" and that no help is offered for bare metal installs, though a venv may help. Take that at face value. The minimum run configuration given in the README is:

docker run -p 42010:42010 -v $PWD/malojadata:/mljdata -e MALOJA_DATA_DIRECTORY=/mljdata krateng/maloja

Three environment variables carry the setup. MALOJA_SKIP_SETUP makes the server setup non-interactive, and the README warns that "Maloja will not work properly in a container without this variable set", though the provided Containerfile sets it by default. MALOJA_FORCE_PASSWORD sets an admin password and is only needed on the first run. MALOJA_DATA_DIRECTORY tells the container where configuration folders and files live; you mount a volume there so the data survives the container and is reachable from the host. The web port defaults to 42010 and the container uses IPv4 by default, so if you proxy to it, the README's note about proxying to the matching IPv4 or IPv6 address applies.

One host-specific wrinkle: if you run Docker on a Linux host, the README recommends passing the owning user's ids as PUID and PGID to avoid file permission problems on the mounted directory. You get them with id -u and id -g. The modified example is:

docker run -e PUID=1000 -e PGID=1001 -p 42010:42010 -v $PWD/malojadata:/mljdata -e MALOJA_DATA_DIRECTORY=/mljdata krateng/maloja

The README states this does not apply to rootless Podman. Outside a container, the command is maloja run, which is the one documented path for a non-container start.

Getting your existing history in, and getting new scrobbles in

Import is file-based. You copy an export into the import folder inside your data directory, and the README lists four accepted sources: a Last.fm export generated by ghan64's website, an official Spotify data export, an official ListenBrainz export, and the export of another Maloja instance. That last one is the migration path if you are moving between servers, and it is also the closest thing to a backup format the README mentions. There is no documented incremental sync from Last.fm, so the import is a one-shot operation on a file you supply.

Ongoing scrobbling goes through API keys. You define them in apikeys.yml in the configuration folder or through the web interface, and the README recommends a separate key per scrobbler client. Clients can either speak Maloja's native API or point at Maloja as a custom ListenBrainz or GNUFM server, which is the pragmatic choice: it means existing scrobblers work without a Maloja-specific build. The README also mentions a Proxy Scrobble feature that forwards your scrobbles onward to other services, so you can keep a Last.fm account in sync without configuring every client twice. For records that no client can capture, the web interface accepts a manual scrobble, which the README frames around vinyl and background music.

Settings live in /etc/maloja/settings.ini, and the README notes that each setting can alternatively be supplied as an environment variable with the MALOJA_ prefix. Custom rules go in the rules.info file under /etc/maloja/rules, with some predefined rules applicable from the /admin_setup page.

Where Maloja is the wrong tool

The container-only stance is a real constraint, not a stylistic preference. Anyone who wants Maloja running as a systemd unit on a small VPS without a container runtime is outside the supported path, and the README says so directly. The second constraint is that the statistics are only as good as what reaches the server. Maloja has no client of its own in the material provided; scrobbling depends on third-party players and extensions that either implement the native API or can be pointed at a custom ListenBrainz or GNUFM endpoint. If your player of choice can do neither, you are entering scrobbles by hand through the web interface or not at all.

The third gap is that there is no social or discovery layer, which is a limitation if you were using Last.fm partly to find music. There is nothing here to replace that. Recommendations are explicitly excluded from the feature set. And the README's own framing of images as an extra, dependent on external API keys from Last.fm and Spotify, means a fully offline instance is a charts-and-text experience. The README does not document what happens when those keys are absent or rate-limited beyond the implication that images simply do not appear.

What Maloja does differently from a hosted scrobble service, and from a plain database

The obvious comparison is Last.fm, and the difference is structural rather than cosmetic. Last.fm is a shared catalog: every scrobble is matched against a canonical track and artist, which is what makes its community pages and recommendations possible, and also what makes a mis-tagged track permanently wrong. Maloja keeps your tagging schema, so the trade is that you get no shared catalog and no cross-user statistics. The README's own wording captures the split: no social networking, radios or recommendations, just a record of your listening over time.

The less obvious comparison is a generic time-series store or a spreadsheet you maintain yourself. Those give you full control of the schema but nothing on top of it, and you would be writing the artist-association logic, the multi-artist credit handling and the chart rendering yourself. Maloja's value is that it ships those three as decisions already made, with an API that existing scrobblers can talk to. The cost is that you inherit its schema and its GPL-3.0 licensing rather than defining your own. If you want to embed Maloja's code in a closed product, the licence is the deciding factor and it is worth reading in full rather than taking a summary from an article.

Maintenance cost, licensing and what to check before you commit

The repository is not archived and the last push recorded is 2026-08-13, so the project is active, but no recent releases were retrieved for this article, which means version cadence cannot be assessed from the material here. The README points at GitHub tags, PyPI (malojaserver) and Docker Hub as the three distribution channels, so upgrades can come from either a new container image or a Python package depending on how you installed it. Because the container is the supported path, the practical upgrade routine is pulling a new image and restarting against the same mounted MALOJA_DATA_DIRECTORY. Whether a given version migrates the on-disk data automatically is not stated in the README; that is the first thing to confirm from the release notes before upgrading an instance you care about.

Licensing is GPL-3.0. That is a copyleft licence, and it affects what you can do if you modify Maloja and distribute it. This is not legal advice; read the licence text and, if you plan to redistribute a modified version or bundle it into a product, get proper advice. Self-hosting for your own listening history is the ordinary use case and raises none of those questions.

The concrete things to verify before you commit: that your host can run Docker or Podman, that port 42010 is free or remappable, that the directory you bind to MALOJA_DATA_DIRECTORY is owned by the PUID and PGID you pass on a Linux Docker host, and that your existing export is one of the four formats the import folder accepts. If any of those four fails, you are outside what the README documents.

Editorial conclusion

Adopt Maloja if you already run containers, want your scrobble history in a file you control, and accept that it will not recommend anything to you. Do not adopt it if you want a hosted service, a mobile app, or a bare-metal install the maintainer will support: the README says Maloja should only be used in Docker or Podman and that no help is offered for bare metal. Before committing, verify the port mapping and the MALOJA_DATA_DIRECTORY volume on your host, confirm that the import folder accepts your existing Last.fm, Spotify or ListenBrainz export, and check the settings.ini keys against your deployment.

Official sources

  1. Issues
  2. krateng/maloja on GitHub
  3. License: GPL-3.0
  4. Project website
  5. README
Community notes

Community notes