Tech
I used Spotify for two years and Apple Music for almost eight years; I’ve always appreciated music streaming services, first because I love music, and second because they allowed me to access an immense music catalog with a few clicks.
Yet, after all these years, I decided to move on.
Not to a new service, but to my own music streaming service.
The important premise to make is that everyone has their own needs, tastes, and preferences.
What is a problem for me might not be a problem for you at all, and vice versa. The same goes for using one service rather than another. If you’re happy with what you have, it’s right to continue using it.
In my case, it’s time to change course.
One of the things I hated about these services is when a song or even an entire album gets “deleted.” By deleted, I don’t mean physically; on Apple Music, it’s obscured, meaning you see the track but it’s no longer accessible, you can’t listen to it anymore.
As much as there may be valid reasons for a track to no longer be accessible, this started to weigh on me, and over many years, it happened much more often than you might imagine.
If I have a physical or local digital copy, however, it will stay there forever, regardless of anything else. I can listen to what I bought forever and as many times as I want. While the world is burning, I can still play my favorite song.
And this, however trivial it may seem, is essential for me.
Another point, in this case personal. The sheer amount of music I’ve bought, traded, received as gifts, and so on over the years. I was a DJ for several years, discos and shows, the quantity of accumulated music is enormous.
And not only that, much of that music, many of those tracks, are not available on the internet; many are amateur tracks by people who tried composing a song for fun; many are drafts, tests, remixes, and so on.
All this music is there waiting to be listened to.
If you already have a good starting base, why not leverage it?
I know that many streaming services allow you to upload local music to have it synchronized across various devices along with all the tracks provided by the service itself. However, at least from my point of view, it seems confusing; rather than me having to upload music, you, the service, should do it. I’m not saying the service should upload all existing music on this planet, but perhaps if a certain album or song is uploaded by many local users, then it might be useful to make it accessible to everyone.
Another point, services change. This is a double-edged sword. On one hand, it allows for change, not always positive, but it allows for adding a new way of seeing things, a new way to interact, a new way to discover something different. On the other hand, however, you are bound by the decisions of that service.
The example I always have in mind to explain the concept is Twitter, the old Twitter. I signed up to follow, coincidentally, a musical artist, Avicii.
It was one of my favorite social networks that I truly appreciated.
Then the service changed, Elon Musk decided to make it his toy, and so many left, including me.
This is the double-edged sword: on one hand, leaving Twitter led me to discover an even better social network, Mastodon and its philosophy. On the other hand, there remains the regret for what had been built over the years with Twitter.
The point is that if you accept a service, you must take into account its changes, whether it’s price increases, interfaces you might not like, AI thrown everywhere without meaning, artists getting paid less and less, more restrictions, and much more.
This discussion can also be applied to alternatives like Navidrome, but with less severity. Navidrome is open source, if there’s something you don’t like, you can change it yourself and leave it there. You build what you want and how you want it, you are not subject to the direction of a company.
We can then add many other factors, such as privacy, monthly cost, audio quality, AI, less and less support for artists, and much more. Everyone will find their reasons to choose one path over another, but they will only realize it by experiencing it firsthand.
Furthermore, there is a last motivation, almost hidden, almost imperceptible at first but which becomes increasingly evident over time. I will discuss this motivation in the conclusions, as it deserves a separate discussion.
Essentially, the combination of all these factors led me to look for an alternative.
Navidrome was the answer.
As mentioned before, Navidrome is an open-source solution to make your music collection available everywhere. It’s a lightweight and easy to use music streaming server that supports a wide range of audio formats and offers features such as playlists, transcoding, radio, support for various clients, and much more.
Navidrome is written in Go, which makes it very resource efficient, ideal for running on devices with limited hardware like Raspberry Pi, NAS, and so on.
Another advantage is that Navidrome supports the Subsonic API up to version v1.16.1. Subsonic clients written for that version can connect and communicate with Navidrome using its compatible API. Consequently, a client written for Subsonic will work exactly the same way with Navidrome. This means you have a wide range of clients to choose from, for both mobile and desktop devices, without having to rely on a specific client developed only for Navidrome.
As for the web interface, Navidrome offers a modern and intuitive interface that allows you to easily navigate through your music library, create playlists, stream music, and manage server settings. The interface is responsive, so it works well on both desktop and mobile devices. Also, for those accustomed to Spotify’s colors, Navidrome also offers a theme like the one I currently use:
In addition to these, we have other interesting features such as:
And many more. If you are a music lover, then it’s definitely worth taking a look at this project, even if just out of curiosity.
Having a small NAS at home with Docker already available, it was quite simple to install Navidrome via docker compose.
Here you can find the link to the Navidrome configuration file, but I preferred to report my configuration below, which also includes Cloudflare Tunnel for remote access.
This is the final configuration, but it’s useful to break it down to better understand each individual aspect.
services:
cloudflare-tunnel:
image: cloudflare/cloudflared:latest
container_name: cloudflare-tunnel
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=WowSoMuchSecret
restart: always
networks:
- navidrome-net
depends_on:
- navidrome
navidrome:
image: deluan/navidrome:0.59.0
container_name: navidrome
user: PUID:PGID
ports:
- "4533:4533"
restart: always
environment:
- ND_CONFIGFILE=/data/navidrome.toml
- ND_BACKUP_PATH=/backup
- ND_BACKUP_SCHEDULE=0 0 * * *
- ND_BACKUP_COUNT=3
volumes:
- "/.../Container/navidrome/data:/data"
- "/.../Music/Library:/music:ro"
- "/.../Music/Deejay/Library:/deejay:ro"
- "/.../Container/navidrome/backup:/backup"
networks:
- navidrome-net
networks:
navidrome-net:
driver: bridge
Let’s start with the Navidrome configuration:
navidrome:
image: deluan/navidrome:0.59.0
container_name: navidrome
user: PUID:PGID
ports:
- "4533:4533"
restart: always
environment:
- ND_CONFIGFILE=/data/navidrome.toml
- ND_BACKUP_PATH=/backup
- ND_BACKUP_SCHEDULE=0 0 * * *
- ND_BACKUP_COUNT=3
volumes:
- "/.../Container/navidrome/data:/data"
- "/.../Music/Library:/music:ro"
- "/.../Music/Deejay/Library:/deejay:ro"
- "/.../Container/navidrome/backup:/backup"
networks:
- navidrome-net
networks:
navidrome-net:
driver: bridge
With this block, we configure the entire instance. In particular:
Regarding network configuration, I decided to create a dedicated Docker network for Navidrome. We use a bridge to have a network that isolates containers in a private environment but allows them to communicate easily with each other.
For convenience, let’s look at an example. What we need is to have a folder for the music library and define the folders for Navidrome.
So, let’s assume we have:
We will then have a structure like this: the MyLibrary folder contains the music library, for example with n folders for artists, each with their respective albums and tracks; and then the Docker folder with the subfolders for Navidrome:
C:/Users/Maya/Music/MyLibrary
┃ Michael_Jackson
┣━ 1983-Thriller
┃ ┣━ Beat_It.flac
┃ ┣━ Billie_Jean.flac
┃ ┗━ ...
┗━ ...
┃ Daft_Punk
┣━ 2013-Random_Access_Memories
┃ ┣━ Get_Lucky.flac
┃ ┣━ Lose_Yourself_to_Dance.flac
┃ ┗━...
┗━...
D:/share/Docker
┃ navidrome
┣━ data
┗━ backup
The example docker compose will be:
navidrome:
image: deluan/navidrome:0.59.0
container_name: navidrome
user: PUID:PGID
ports:
- "4533:4533"
restart: always
environment:
- ND_CONFIGFILE=/data/navidrome.toml
- ND_BACKUP_PATH=/backup
- ND_BACKUP_SCHEDULE=0 0 * * *
- ND_BACKUP_COUNT=3
volumes:
- "C:/Users/Maya/Music/MyLibrary:/music:ro"
- "D:/share/Docker/navidrome/data:/data"
- "D:/share/Docker/navidrome/backup:/backup"
networks:
- navidrome-net
networks:
navidrome-net:
driver: bridge
This is just a silly example to understand how to set the paths. Obviously, it makes sense that the folder containing the music library is easily accessible from the device where we will run the Navidrome Docker container. In my case, being a NAS, the music library and all Docker data are accessible on the NAS itself.
So, for those who want to use this configuration, remember to:
The remaining challenge is how to securely expose the Navidrome service to the internet. In this scenario, Cloudflare Tunnel offers an ideal solution, eliminating the need to open ports on the router or manually configure the firewall.
I briefly discussed it in the post on how I tried to create a Mastodon instance. With Cloudflare Tunnel, you can securely expose the Navidrome server, significantly reducing the risk of external attacks such as DDoS, brute force attempts, or other unauthorized access.
One of the main advantages is that you don’t need to make any firewall changes or set up port forwarding. Thanks to the tunnel between the server and Cloudflare, internet traffic is routed through a protected connection, keeping the server’s public IP hidden. This approach eliminates the risks associated with direct server exposure, making security management much simpler.
This way, we can access Navidrome remotely without the need to configure a VPN.
Configuring Cloudflare Tunnel with Docker is also very simple, taking the relevant part of the docker compose:
cloudflare-tunnel:
image: cloudflare/cloudflared:latest
container_name: cloudflare-tunnel
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=WowSoMuchSecret
restart: always
networks:
- navidrome-net
depends_on:
- navidrome
We are going to define the tunnel to expose Navidrome.
Directly from the Cloudflare website, go to Zero Trust -> Networks -> Connector (apparently they are no longer called Tunnels) and create a new tunnel. Give the tunnel the name you want and click on Next. We arrive at the configuration part:
From here you need to choose your environment, in our case it doesn’t matter because we already have the docker compose ready, what we need is the authentication token. If we click on the Docker button and then copy the entire command provided to us, something like:
docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIjoiZmZiNjZkZDk3M2Q5Y2Q2ZWIwZWU3ZThjMjIiLCJ0IjoiMj
What interests us is only the token eyJhIjoiZmZiN… (fake example, usually much longer) which we will insert into the TUNNEL_TOKEN environment variable in the Cloudflare Tunnel docker compose.
So we will have:
cloudflare-tunnel:
image: cloudflare/cloudflared:latest
container_name: cloudflare-tunnel
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=eyJhIjoiZmZiNjZkZDk3M2Q5Y2Q2ZWIwZWU3ZThjMjIiLCJ0IjoiMj
restart: always
networks:
- navidrome-net
depends_on:
- navidrome
Subsequently, still on Cloudflare, by clicking on Next we will configure the tunnel to reach our Navidrome instance:
Where:
Let’s update everything by clicking on Complete setup and we have defined our tunnel. Now we can build a single docker compose that includes both Navidrome and Cloudflare Tunnel as shown at the beginning.
Once the container is started, we can access Navidrome via the subdomain we defined in Cloudflare, and that’s it.
The environment variables for Navidrome are numerous and allow you to customize the server’s behavior according to your needs. Here are the ones I use:
Scanner.Schedule = '@every 24h'
EnableInsightsCollector = true
LogLevel = 'info'
UIWelcomeMessage = 'Spotify who?'
DefaultTheme = 'Spotify-ish'
EnableGravatar = true
EnableSharing = true
DefaultShareExpiration = '24h'
DefaultDownloadableShare = false
SmartPlaylistRefreshDelay = '10s'
LastFM.ApiKey = ''
LastFM.Secret = ''
ILoginBackgroundUrl = 'data:image/png;base64,iVBORw0KGgoA...'
With:
So let’s create the navidrome.toml file inside the data folder mounted in the Navidrome container. From the Navidrome logs, we can see if the configuration file is loaded correctly:
Followed by the list of all the variables we saw earlier in both the navidrome.toml file and the docker compose.
As already mentioned, Navidrome’s web interface is very intuitive and easy to use, and above all, it allows me to access it even on devices where I cannot install a dedicated client due to corporate restrictions or other reasons.
However, that’s not enough; there’s always the need for a dedicated desktop and mobile client to listen to music with one’s own devices. On the desktop side, I’ve been using Feishin for a few weeks, which is compatible with Windows, macOS, Linux (via AppImage), and a web interface with Docker.
The peculiarity is that Feishin has many settings and configurations that allow you to customize the client according to your needs.
You can choose audio quality, playback behavior, keyboard shortcuts, graphical appearance, and much more. In addition, support for lyrics is a must for karaoke lovers.
One shortcoming of Feishin is the lack of offline listening support. For now, it’s not a feature I particularly need on the desktop, but it could be very appreciated in the future.
On the mobile side, however, Arpeggi is currently in beta on iOS and iPadOS devices. I must say that the app is really well made, with a clean interface that takes inspiration from Apple Music’s, easy to navigate and with all the essential features for a pleasant listening experience.
Furthermore, like Feishin, it contains a really good set of settings to best customize the entire interface with your preferences.
Arpeggi, on the other hand, features offline listening to keep all your favorite songs locally.
I found just two minor shortcomings that I hope can be addressed in the future: the first is integration with Siri, which would allow playback to be controlled via voice commands. The second is Apple Watch support, which can cause some problems for those who use their watch a lot to listen to music on the go without having to carry their iPhone.
However, overall, I must say that Arpeggi is truly a fantastic application, and those two shortcomings do not in any way detract from the listening experience I am having.
As with everything, the idea of having your own music streaming server also brings its own challenges. But this applies to everything; the point is to find the right balance.
The problem that arises for people is “but how do you discover new music without it?"
Before all these streaming services, perhaps even before the boom of the Internet, how did people listen to music? How did they stay updated on the latest album? Discover new artists, genres, and much more to broaden their musical culture?
By talking, sharing, exchanging ideas and opinions, searching, even buying randomly, listening from friends, shops, relatives, and much more.
Perhaps some still do it today, but most people rely on music streaming services, which are simpler and more practical. And in part, I can’t blame them.
However, for this reason, Navidrome allows for the integration of external services to improve the user experience and fill some gaps. Among these, we have ListenBrainz.
With ListenBrainz, we can keep track of what we listen to and discover new music based on our tastes. ListenBrainz is an open-source project that collects data on users’ music listening habits, similar to Last.fm but with a more transparent and privacy respecting approach.
Navidrome natively supports ListenBrainz for scrobbling, so it’s a great starting point. From the Navidrome web interface, you can enable scrobbling to ListenBrainz and start building your musical profile.
ListenBrainz will then start collecting data on what you listen to, allowing you to discover new music based on your tastes and preferences. Below is an example of what the Last Week’s Exploration represents based on the listening I have done:
In addition to this aspect, you’ll find tabs on music statistics like Top Artists, Top Albums, Top Tracks, and much more that provide a complete overview of your musical tastes.
For those who still can’t detach themselves from streaming service algorithms, they can always, for example, use Spotify Free to discover new music and then buy the songs they like best to add them to their local music library.
We configured Last.fm for scrobbling earlier. Again, Navidrome natively supports Last.fm to track what we listen to. In my case, I tend to rely more on ListenBrainz, but I know many prefer Last.fm for its long history and large user base.
However, in this case too, you get detailed statistics on your listening, you can discover new artists and albums based on your musical tastes, and much more.
There are two costs: NAS and music purchase.
Calculating the energy cost of my NAS, QNAP TS-233, is useful for understanding its impact on the electricity bill. Fortunately, being an ARM-based 2-bay NAS, it’s designed to be extremely efficient.
The calculation, of course, depends heavily on how it’s used. For this reason, I decided to create three distinct scenarios to cover different usage modes and get an idea of the possible costs.
According to official QNAP specifications, the TS-233 model has the following average values with populated disks:
Obviously, these values may vary slightly depending on the type of hard drives used, but I don’t want to overcomplicate the calculations with too many variables.
Furthermore, the cost varies based on the contract. For this estimate, I used a realistic average all-inclusive cost, energy + taxes + charges, for the Italian market where I’m located.
Since the NAS is on 24/7, we calculate the total annual consumption multiplied by the energy cost.
Scenario A: intense use
The NAS never goes into standby, for example, 24/7 downloads, video surveillance, media server, and so on.
Scenario B: realistic use
Active use for 8 hours, work/streaming, sleep for the remaining 16 hours.
Scenario C: light use
The NAS serves only as occasional storage. Disks are sleeping 90% of the time.
Summarizing, we have:
| Usage scenario | Annual consumption | Estimated annual cost |
|---|---|---|
| Maximum | ~95 kWh | ~ 24.00 € |
| Medium | ~52 kWh | ~ 13.00 € |
| Minimum | ~31 kWh | ~ 8.00 € |
By actively using Docker for other containers in addition to Navidrome, I would fall into the worst-case scenario A, with an annual cost of approximately €24.00, which, however, is equivalent to two months of Spotify subscription.
As already mentioned, this is not a precise and direct comparison, but at least it gives an idea of the cost.
In conclusion, considering that I also have other services besides Navidrome, I think the cost is more than justified.
In my case, calculating the price is almost useless as I already own a rather extensive music library that I have built over the years. However, it does not mean that for new additions there are services that allow you to have quality music at accessible prices.
Bandcamp is one of my favorites. It allows artists to sell their music directly to fans, often at very reasonable prices. Furthermore, Bandcamp often offers options to purchase music in high-quality formats such as FLAC or WAV, ideal for audiophiles.
Jamendo Music, on the other hand, is a platform that offers music under Creative Commons licenses. This means that many tracks are available for free or at very low prices, depending on the license chosen by the artist. It’s a great place to discover new independent music and support emerging artists.
Internet Archive (Live Music Archive) is a valuable resource for those looking for live recordings and bootlegs. It offers a vast collection of live recorded concerts, many of which are available for free. It’s a great way to explore unique and rare performances by famous and lesser-known artists.
SoundCloud, I hardly ever use it, but many artists can enable the “Download” button for their tracks, especially DJ sets or unofficial remixes.
Many certainly know the pirate route. I’m not unfamiliar with it; those my age know Napster, eMule, Torrent, and many others well. However, leaving a music streaming service that, among other things, pays artists very little, and then illegally downloading music, doesn’t make much sense.
Indeed, it almost seems contradictory.
It’s been more than a month since I started using Navidrome, and I can say it was an excellent choice, at least for my needs. Having complete control over my music library and being able to listen to the tracks I love without depending on external services is a fantastic feeling. The Navidrome community is active and helpful (GitHub and Reddit), which makes the experience even more enjoyable.
Moreover, there’s something that deeply concerns me, a concept that might seem strange but which I consider fundamental, and I only realized it when I started using services like Navidrome with the music I own, and it was later confirmed by another person online.
We all think the algorithm is there to help us. We believe that “Daily Mix” or “Artist Radio” are designed to expand our musical horizons. But what if I told you that the goal of your favorite streaming service is the exact opposite?
I read an interesting article by Luke Cyca, which I encourage you to read, that confirmed a feeling I had harbored for years but had never paid attention to. For Spotify, music is not art. It’s filler.
The business model of streaming platforms is not based on the quality of what you listen to, but on the amount of time you spend on the platform. Cyca cites a fundamental concept: for streaming executives, most users don’t really want to listen to music. They want a soundtrack for their activities. Music for working. Music for driving. Music for cooking. Lo-fi beats for studying.
From this perspective, songs become, in the author’s words, “the sonic equivalent of a mediocre IKEA painting.” They only serve to cover silence and furnish the empty walls of your day. They must be pleasant enough not to disturb, but harmless enough not to demand your active attention.
Here lies the deception of “discovery.” A true path of musical discovery requires peaks, risks, and sometimes even listening to things we don’t like at first but understand later. But for Spotify, this is a huge risk. If the algorithm proposes something too audacious, different, or complex, you might get distracted from your activity. You might get annoyed. And, in the worst case, you might press STOP.
“Stop” is the mortal enemy of streaming. That’s why the algorithm isn’t designed to make you discover your next favorite band; it’s statistically optimized to serve you the safest possible song. It serves you tracks that maintain a constant mood, fungible, interchangeable.
The result of this approach is that we have stopped actively listening.
We have accepted a continuous flow of audio “content” optimized for retention, not for emotion. Music becomes slop, an indistinguishable flow where one track is as good as another, as long as the BPM is right for our morning run.
Consequently, the next time you open the app, ask yourself: am I listening to music because I want to hear this artist, or am I just filling the void for fear of silence?