# any-listen: a self-hosted private music playback service for local files, WebDAV and extensions

> any-listen is a TypeScript, pnpm workspace project that ships a desktop app and a web service for playing local songs, WebDAV-hosted songs and extension-provided online resources. Its AGPL v3 licence adds a no-commercial-use term, and the repository does not document rollback.

**any-listen/any-listen** — A cross-platform private music playback service

- Repository: https://github.com/any-listen/any-listen
- Stars: 4,154 · Forks: 188
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/any-listen-any-listen

## The problem any-listen solves, and who it is aimed at

Streaming services decide what you can play and where that playback happens. any-listen takes the other position: it is described in the README as "a cross-platform private music playback service", and its feature list is built around sources you already control. Local songs, standard playlists, local lists, WebDAV-hosted songs in remote lists. The repository topics (any-listen, music-player, nas) point at the intended setting, a machine on your own network holding the files.

The audience is narrower than a general music app. If your library lives on a NAS or a WebDAV share and you want a player that reads it directly, the remote list feature is the reason to look at this project rather than a desktop-only player. If you have no music files and no WebDAV server, there is nothing here to play: the online features are extension-based, and the README says you install the relevant extension through the Extension Manager before online resources, metadata matching, covers or lyrics become available.

Two distribution shapes are offered. A desktop version, whose releases live in a separate repository (any-listen/any-listen-desktop), and a web service version you deploy to a server or run through Docker. The README describes the project as under active development, and the repository's last push was on 2026-09-22.

## How the web service is put together: pnpm workspace, Docker stages, port 9500

The repository is a pnpm workspace. The root package.json declares "workspaces": ["packages/*"], pins the package manager to pnpm@10.34.5, and requires Node ">=22.12.0 || ^20.19.0". Build scripts are thin wrappers: pnpm build:web and pnpm dev:web both delegate to the @shared/scripts workspace package, while pnpm build:desktop delegates to a Windows-specific desktop build script. There is no plain pnpm build for the web target; you call build:web explicitly.

The Dockerfile shows the intended data flow of the server image. A builder stage installs g++, make, py3-pip, git, nodejs, icu-data-full and npm, enables pnpm through corepack, runs pnpm fetch, then pnpm i --offline --frozen-lockfile, and finally pnpm build:web with WEB_SERVER_ONLY set to true. The final stage is Alpine plus nodejs, icu-data-full and tzdata, and it copies the build output to /server. The runtime is node index.cjs, running as the non-root user anylisten (uid 1001, group algroup).

Configuration is environment variables declared in the image: DATA_PATH defaults to /server/data, NODE_ENV to production, PORT to 9500 and BIND_IP to 0.0.0.0. EXPOSE 9500 matches the PORT default. The comments in the Dockerfile explain two Alpine additions: icu-data-full is there to fix a new TextDecoder('latin1') error, and tzdata is installed alongside it. A commented-out TZ=Asia/Shanghai line records where the timezone variable goes if you need it. The README points to docs/docker-server.md for deployment steps, environment variables and building from source, so treat that file as the authority over the Dockerfile defaults.

## Deploying the web version and playing your first local song

The README says the web version can be deployed directly to a server or with Docker, and refers to docs/docker-server.md for the full steps. The Dockerfile is the source for the image's own defaults, so the run command below only supplies what a typical deployment changes: the data volume and the host port. Both the image name and the container name are yours to choose; the port, the internal path and the user are fixed by the Dockerfile.

```bash
docker build -t any-listen .
docker run -d --name any-listen -p 9500:9500 -v /srv/any-listen/data:/server/data any-listen
```

The image already sets DATA_PATH=/server/data, so the volume mount is what makes the library and settings survive a container replacement. The container listens on 9500 and binds 0.0.0.0 inside the container. Note the ownership requirement baked into the image: /server/data is chowned to anylisten:algroup with uid and gid 1001, and the process runs as that user, so a host directory mounted there must be writable by uid 1001 or the server will not be able to write its data.

For development against the source tree, the root scripts are the entry point. pnpm i installs the workspace, and pnpm dev:web starts the web service in development mode.

```bash
pnpm i
pnpm dev:web
```

Once the service is up, the first real use is adding music you own. The README lists adding and playing local songs through standard playlists and local lists, and adding songs stored on WebDAV through remote lists. Metadata matching for covers and lyrics, and online playlists and charts, are separate: the README states you install the relevant extension through the Extension Manager first. Nothing in the repository documentation describes a default account, so check docs/docker-server.md for how the first login is established.

## Where any-listen stops being the right tool

The licence is the first boundary. The README states the project is licensed under AGPL v3.0 with additional terms, and that "commercial use is strictly prohibited unless written permission is obtained from the original author". That is not a standard AGPL term. For an individual running a home server it changes nothing. For anyone who wants to host this for paying users, embed it in a product, or run it inside a company, it is a blocker until permission is granted, and the LICENSE file is the text that matters.

The second boundary is operational. There are no retrieved releases, and the version field in the root package.json is 0.1.0. The README itself says the project is under active development, which in practice means the web build is something you build from source or from the Dockerfile rather than something you pin to a tagged artifact. The README does not document rollback, so if a rebuild changes the data format under DATA_PATH, the repository gives you no stated procedure for going back. Back up that directory yourself before upgrading.

The third is fit. any-listen is a playback service, not a library manager or a metadata authority. Cover art and lyrics come from extension-based matching, and online playlists and charts come from extensions too. If your files are poorly tagged and you expect a self-contained scanner to fix that, the README does not describe one. And if you have no WebDAV endpoint and no local files, the remote list and local list features have nothing to work with.

## How any-listen differs from Navidrome and Jellyfin

The nearest comparison is Navidrome, a self-hosted music server that scans a directory and serves a Subsonic-compatible API so existing clients can connect. any-listen does not describe a Subsonic-compatible API in the README; it describes its own playback surface, with the desktop app and the web service as the two ways in. The practical difference is client strategy. Navidrome's value is that many third-party players already speak to it. any-listen's value is that one project covers the desktop app and the server, with WebDAV as a first-class source rather than a mounted directory.

Jellyfin is the other reference point, but it is a general media server whose music support sits inside a larger video, live TV and user-management system. any-listen has no such scope in the README: no video, no live TV, no user administration described. That makes it smaller to run and smaller in what it can do. If you want one server for films and music with per-user libraries, Jellyfin is the broader tool. If you want a music player that reads a WebDAV share and your local disks and does little else, any-listen is the more direct fit.

The extension model is the real dividing line. Metadata matching and online resources are installed through the Extension Manager rather than built in, so the feature set is something you assemble. That is a design choice with a cost: a fresh install plays local and WebDAV files and nothing more until you add extensions.

## Maintenance cost, the dev branch and licence obligations

The repository's last push was on 2026-09-22, so the codebase is moving. The README tells contributors to clone the repository and switch to the dev branch for development, and to submit pull requests to dev rather than main. If you build from source, expect to track a moving target: the root package.json pins pnpm@10.34.5 through packageManager, and the Dockerfile relies on pnpm i --offline --frozen-lockfile, so a lockfile that drifts from pnpm-lock.yaml will break the image build rather than silently resolve.

Upgrade cost is concentrated in two places. The Docker build re-runs pnpm build:web inside the builder stage, so every image rebuild compiles the web target from source; there is no prebuilt server artifact described in the README. And DATA_PATH is the stateful part, mounted at /server/data in the image. The README does not document rollback or a migration path, so the safe procedure is to snapshot that directory before pulling new code.

On licensing, the AGPL v3.0 base plus the README's additional no-commercial-use term is an unusual combination, and the README directs readers to the LICENSE file for full details. AGPL normally imposes source-availability obligations on network users; the added commercial restriction sits on top of that. Whether those terms are compatible with your organisation's policy is a question for your own legal review, not something this article can settle. What can be said plainly: if your use is commercial, the README says you need written permission from the original author first.

## Conclusion

Adopt any-listen if you want a self-hosted player for your own local files and a WebDAV share, and you are comfortable with AGPL v3 plus the README's added term that commercial use is prohibited without written permission. Do not adopt it if you need a supported commercial deployment, a stable release line, or a documented rollback path; there are no retrieved releases and the README does not document rollback. Verify first that the web server's DATA_PATH volume is writable by the non-root anylisten user (uid 1001), and that your Node version satisfies the engines field.

## FAQ

### What is any-listen?

It is described in its README as a cross-platform private music playback service, written in TypeScript. It provides a desktop version and a web service version, and plays local songs, WebDAV-hosted songs and, with extensions installed, online resources.

### How do I install any-listen as a web service?

The README says you can deploy the web version directly to a server or use Docker, and points to docs/docker-server.md for deployment steps, environment variables and building from source. The repository ships a Dockerfile whose final stage runs node index.cjs as the anylisten user on port 9500.

### Where does any-listen store its data?

The Dockerfile sets DATA_PATH to /server/data and creates that directory owned by anylisten:algroup (uid and gid 1001). That path is the stateful part of a container deployment, so it is what you mount and back up.

### Can I use any-listen commercially?

The README states the project is licensed under AGPL v3.0 with additional terms, and that commercial use is strictly prohibited unless written permission is obtained from the original author. It refers readers to the LICENSE file for full details.

### How do I add covers and lyrics in any-listen?

The README lists online song metadata matching for cover and lyrics as a feature, and says you install the relevant extension via the Extension Manager. It is not described as built-in behaviour.

## Sources

- [any-listen/any-listen on GitHub](https://github.com/any-listen/any-listen)
- [Issues](https://github.com/any-listen/any-listen/issues)
- [README](https://github.com/any-listen/any-listen/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/any-listen-any-listen
