I'm so sick of paying for music subscriptions
Intro #
I’ll just host my own.
Yes every song out there will no longer be a search away, but do I really need anything other than City Girls?
Server Set-Up #
For hosting the server, I went with the obvious option of using a VPS, especially since using my PC means that I won’t be able to put it to sleep. Also there is no guarantee that I will have a power outage-free life…
There’s nothing to consider for a simple music streaming server other than a minimal amount of CPU’s and RAM GiB’s. I went with the AWS t3.small instance since it offers 2 vCPU’s and 2 GiB’s of RAM, just a little more than necessary. Anything from the operating system and architecture is unimportant.
A basic configuration is enough when setting up an AWS EC2 Instance, except for the security group. By default, the EC2’s security groups only allow for incoming SSH connections on port 22. Since music will be served from port 443, however, we will need to add an extra rule in the AWS security group to allow for incoming https connections (port 443).
Once you have your instance running, time to SSH into it and start setting up that music server!
Firewall configuration (Optional) #
Depending on the default firewall configuration your instance comes with, port 443 may not be accepting https connections yet.
If sudo ufw status verbose; does not list a rule allowing for https/port 443 incoming traffic, run sudo ufw allow 443/tcp or sudo ufw allow https
Link an Elastic Block Storage volume #
For music storage, it’s best to choose a detachable elastic volume. The benefit is that if the EC2 instance ever becomes inaccessible, the music is still recoverable through this volume. It can be attached and detached from any Amazon instances of your choosing. Its size can also adapt to the amount of storage requested by the server. Let’s use an EBS gp3 volume of 20 GiB to store compressed music. Then attach the block to our EC2 instance.
Once the storage is attached to the instance, install a filesystem on it if need be, then mount it in a directory available to the Navidrome docker container. Which brings me to the next section: the Navidrome docker container itself.
Navidrome setup #
Using docker-compose to pull down the image and run it is about as easy of a set-up as it gets. Once you create a directory for the project, create a docker-compose.yml file to define the image configuration.
With ~/music-server/docker-compose.yml containing the following:
version: '3.8'
services:
navidrome:
image: deluan/navidrome:latest # Docker image pulled from Docker Hub
container_name: navidrome # Custom name for docker instance
volumes:
- ./data:/data:z # Persistent data storage containing config files, cache, etc... (~/music-server/data)
- /data/music:/music:z # Folder containing your music library (/data/music)
environment: # Variables passed to the Docker instance when it is being initialized/created
- ND_LOGLEVEL=debug # Enables detailed log output for troubleshooting
- ND_SCANINTERVAL=1h # Scan music folder for changes every 1h
- ND_SESSIONTIMEOUT=24h # Timeout user client sessions after 24 hours
ports:
- "4533:4533" # Map container port 4533 to machine port 4533
restart: unless-stopped # Restart if instance stops for any reason
Next, sudo docker compose up -d to run the container.
Accessing http://localhost:4533 for the first time will prompt you to create an admin user. Once the admin user is created and logged in, music stored in the /data/music directory will be displayed. (It’ll be completely empty if you do not have any music yet, obvi)
DNS configuration #
Avoid having to type up the instance’s IP by having a custom domain point to it. E Z P Z.
(… Also it’s needed for securing traffic with SSL in the next few steps)
Nginx reverse proxy #
In order to be able to serve music from the default https port (443) and encrypt traffic with SSL, we need to use a reverse proxy, like Nginx.
After installing Nginx, we can configure it to handle requests from domain.com on behalf on Navidrome. This is done by adding a server block to a custom file in the /etc/nginx/sites-available/ directory.
(Example: /etc/nginx/sites-available/navidrome)
server {
listen 80;
server_name domain.com;
location / {
proxy_pass http://localhost:4533; # Forward requests from domain.com to http://localhost:4533
# Forward the hostname (domain.com), client ip address, and any previous proxies the requests has gone through
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Create a symlink from /etc/nginx/sites-available/navidrome to /etc/nginx/sites-enabled and you’re good to go.
Then restart nginx and test it out by visiting http://domain.com.
Secure traffic with SSL #
Instead of delving deep into the world of web app encryption with SSL, getting lost in the configuration options and messing up a million different ways, I delegated and used certbot to automate the whole process.
It can be installed with apt:
sudo apt install -y certbot python3-certbot-nginx;
Then we encrypt traffic to and from our domain:
sudo certbot --nginx -d domain.com;
Then test the automatic renewal of the SSL certificates:
sudo certbot renew --dry-run;
(Changes to the Nginx server blocks can be easily identified as they all end with “# Managed by Certbot”.)
Restarting Nginx will apply all the changes and accessing your server will be done through https.
That’s it! All that’s left to do is add music to the server. Yay!
Listen to MUSIC! ๐ #
Once I’ve downloaded music, I use “MusicBrainz Picard” to correctly tag any missing metadata or download album covers. It has a ton of options so the learning curve is a bit steep, although it’s nothing a 15-min Youtube video can’t fix.
As for album art, FLAC files usually have cover art embedded. Transcoding from FLAC to OPUS doesn’t allow to reimbedd art, however, unless I jump through hoops I am not willing to jump through, so I just opt for keep a copy of the cover as a Folder.jpg file in the album folder.
For clients, I adore the resource-heavy Electron app “Feishin” for its beautiful UI and “Amperfy” on my iPhone for the same reason.
My requirements for music clients are clearly not many:
- Looks good โ๏ธ
- Open source โ๏ธ
Sync music with local computer #
Once music has been acquired all that’s left is uploading it to the server.
I prefer Syncthing because it doesn’t require manual synchronization after every change. It’s a one-time set up forever! If you prefer not to have an on-going open connection between the two computers however, rsync would be a better fit.
I keep a folder of lossless .flac music on my local computer. I also keep a folder of that same music compressed to .opus/.ogg that is synchronized with the Navidrome server. Every time I convert my files to .opus/.ogg, they’re automatically sent to the server.
The Holy Trinity ๐ถ #
For about any music out there can be found on the following services: