iTunes Home Sharing via SSH

I’ve tried lots of different options for music management: iTunes, Google Music, Spotify, Subsonic, and others. All of them have different problems. For iTunes, you’re tied to Apple devices. For Google Music, you have to start over organizing and rating your music, as it has no public API and doesn’t really attempt to sync metadata besides your playlists in a limited fashion. Spotify, similar story. Subsonic doesn’t reflect your changes in iTunes and maintains its own database separate from your iTunes library. Organizing via a flat file system is cumbersome, doesn’t sync to devices easily, and doesn’t have a lot of niceties such as ratings and playlists.

I’ve settled on the idea of iTunes as a central store for music. I get all the organizational tools, streaming to Airplay devices, syncing to iDevices, and merely have to put up with an overly complicated and poorly performing app. To that end, I explored trying to manage my media library at work. At home, a NAS hosts the library files while a Mac running iTunes mounts the directory over the network.

I could try to mount the NAS on my work machine, but iTunes does a decent amount of writes to the library file (as it assumes it’s local on-disk) and doesn’t handle the case very well. Even via local network, sometimes iTunes hangs while writing to the iTunes Library file.

Instead, I decided to use the Home Sharing or Library Sharing options available in iTunes and use the iTunes instance I have at work to remotely play songs over the Internet via ssh tunnels. Searching the internet yields a number of options that no longer seem to work. The basic idea is that iTunes library sharing (not iTunes Home Sharing, which is slightly different) runs on port 3689 on the iTunes and advertises a DAAP protocol via mDNS. What has changed since most of those blog posts were written is that iTunes seems to require a TXT record with metadata regarding the capabilities of the DAAP endpoint, whereas it did not seem to before. Thus, if you want to use ssh tunnels to link your home iTunes instance with your remote (or “local”) instance, you’ll need something like this.

ssh -L 3690:localhost:3689 -N yourremotemachine.com

This command connects to yourremotemachine.com (insert your machine’s WAN IP or domain name here, it’s up to you to properly expose your ssh port to the internet) and sets up port forwarding. The port 3689 on yourremotemachine.com is now connected to 3690 on your local machine. This will allow the DAAP commands and music stream to traverse the network from your home iTunes machine to your remote machine. -N stops ssh from running a terminal, which is not required, but at least won’t confuse you when you’re tabbing through your terminal windows. Honestly, you could use most any port above the reserved ports that’s not currently in use, but 3690 is easy to remember as one port more than 3689.

The next thing we need to do is advertise the DAAP endpoint on the local network. This will make it appear as if your machine has an iTunes instance running on port 3690. In reality, requests to 3690 will be forwarded to your home iTunes machine on port 3689.

On your iTunes home machine, run this command:

dns-sd -Z _daap._tcp local

This command gets the mDNS records for services advertising a DAAP endpoint over TCP on the local domain. This command is meant to be interactive, so it will not exit until you press Ctrl+c. You can also run something like dns-sd -Z _daap._tcp . to see all DAAP endpoints on the local network (some of which will also be advertised on your machine locally), or dns-sd -B _services._dns-sd._udp to see all services. If iTunes is running and library sharing (again NOT Home Sharing) is enabled, you should see something like the following. I’ve obfuscated my valueswith XXX in my output.

XXX’s\032Library_PW._daap._tcp            TXT     "txtvers=1" "Version=XXX" "MID=XXX" "Database ID=XXX" "Machine ID=XXX" "dmv=XXX" "OSsi=XXX" "Media Kinds Shared=XXX" "iTSh Version=XXX" "Password=1" "Machine Name=XXX’s Library"

The quoted key-value pairs are what we need for our own dns-sd command on our local machine. Copy everything to the right from "textvers=1" to use for the next command on your local machine.

dns-sd -P iTunesServer _daap._tcp local 3690 foobar.local 127.0.0.1 "txtvers=1" "Version=XXX" "MID=XXX" "Database ID=XXX" "Machine ID=XXX" "dmv=XXX" "OSsi=XXX" "Media Kinds Shared=XXX" "iTSh Version=XXX" "Password=1" "Machine Name=XXX’s Library"

A few things regarding this command. iTunesServer is an arbitrary name for the service; you can call it whatever you want. Just be careful of any spaces in the name. foobar.local is another somewhat arbitrary name for your local machine. Other instructions have suggested localhost.local, but on my machine that name was already taken. _daap._tcp is the type of service advertised, and local is only for your local machine. If you want to expose this library to more hosts on your remote network, you can try replacing local with ., though I haven’t tested this extensively.

This should allow you to see a shared iTunes library in iTunes on your local machine. Actually, even if your port forwarding isn’t working, you’ll see the remote library in iTunes, but you won’t be able to connect.

A variation of this should also work for Home Sharing. Home Sharing advertises a service with the protocol _home-sharing._tcp, and Home Sharing runs on the same port (3689) as library sharing does. The difference is you need to be signed into Home Sharing for it to work, but you’ll be able to manage your library remotely as opposed to only being able to play songs.

Instead of the dns-sd above, you need to replace the _daap._tcp with _home-sharing._tcp.

dns-sd -P iTunesServer _home-sharing._tcp local 3690 foobar.local 127.0.0.1 "txtvers=1" "Version=XXX" "MID=XXX" "Database ID=XXX" "Machine ID=XXX" "dmv=XXX" "OSsi=XXX" "Media Kinds Shared=XXX" "iTSh Version=XXX" "Password=1" "Machine Name=XXX’s Library"

This should allow you to rate songs, create playlists, and so on.