Loading 8 Votes - +

How-to Build an Open Source Linux iTunes Media Server for Mac Clients

2_article_2963_thumb_itunes

My iTunes library was going to live on my Linux server whether it wanted to or not.

I recently built an all-purpose server and one of the things I wanted to do with it was turn it into a media hub/server. Before exploring my options, I had some specific requirements in mind. A good solution would have to:

  1. be free
  2. run in Linux, preferably Gentoo (because that’s what my server is running)
  3. be open source
  4. allow my primary laptop to act as the “master”
  5. allow any other computer to access the music

Let me clarify point 4. When I say act as the master, I mean that if I add song A to my laptop, I want the media server to see it and duplicate it. If I delete song A, I want my media server to also delete A. Essentially the media server and my laptop would be mirrors. The only real difference is that my server would always be on the net and my laptop would not be. Then if I wanted other clients to sync against the server, they could.

A Cold, Lonely Internet of Options

Surprisingly, I didn’t really find any good solutions already built. There are a few out there, but none really did what I wanted (from what I could tell in my brief period of research anyway). So I did what any good geek would do: I wrote my own solution.

Step 1: Enable ssh Connections on the “Master” Mac Laptop

If my server was going to sync with my laptop, it needed to be able to talk to it somehow. In Mac, to enable ssh all you have to do is go to System Preferences → Sharing and check the Remote Login box.

2_article_2963_thumb_ssh_on_mac

Enable Remote Login, or “ssh”, in Mac. (And yes, my computer’s name is mcp.)

There is an advanced configuration I set up to allow my server to connect to my laptop without a password. I won’t go into the details as it’s documented all over the net. It’s called public key authentication. If you’re not aware of it, check it out as it’s a very nice feature to use in general.

Step 2: Write a Script to Find the Master Mac Laptop’s IP

If you’re not up to speed on network file sharing protocols, here’s all you need to know: Macs, PCs, and Linux don’t all easily share files out of the box. Mac employs what’s commonly called “Bonjour” to advertise itself on a network. My first step was to get my Linux server to “speak Bonjour” and look for my laptop. To do this I installed mono and wrote the following script.

What mono does is allow me to search for my laptop by name, and then get its IP address, which most any network device understands. So to recap: bonjour name in, IP out. That’s our goal.


#/bin/sh
# find_bonjour_client
# simple script to look for a bonjour client by name
# example: find_bonjour_client my_laptop
if [ -z $1 ] 
  then
    echo "You must provide the bonjour client's host name."
    exit
fi

# look for all bonjour client and log them in a tmp file
# you may have to modify the path shown to match your install
mono /usr/lib64/mono-zeroconf/MZClient.exe \
     --type _ssh._tcp -r -v > /tmp/mzoutput &

# unfortunately, mono assumes you're going to interact
# with it, so we'll send a kill signal
monopid=$!
sleep 3
kill -s SIGKILL $monopid

# fish out the bonjour client we're looking for
cat /tmp/mzoutput | grep $1 | grep host > /tmp/mzoutputmcpline
mzoutputmcp=`sed "s/^.* host ip = '//" < /tmp/mzoutputmcpline`
echo $mzoutputmcp > /tmp/mzoutputmcp
mzoutputmcp=`sed "s/'.*$//" < /tmp/mzoutputmcp`

# return the client's IP address
echo $mzoutputmcp

I’m sure there are more elegant solutions for some of that. Feel free to leave suggestions in the comments. For now though, this gets the job done. Executing this script in a terminal yields:

$ ./find_bonjour_client mcp
./find_bonjour_client: line 11: 12017 Killed mono 
/usr/lib64/mono-zeroconf/MZClient.exe --type _ssh._tcp -r -v > /tmp/mzoutput
10.0.1.6

Note the junk that gets thrown on the terminal in addition to the IP address. Other programs will ignore this as its being sent to STDERR and not STDOUT when we killed the mono process. If you don’t like it, you can redirect STDERR like so:

$ ./find_bonjour_client mcp 2> /dev/null
10.0.1.6

Ah, nice and clean. We’ll use that in the next script we write.

Step 3: rsync with the Laptop’s iTunes Library

Now that we know where our ssh-ready laptop is, let’s use a command program called “rsync” to make an efficient copy.

This script is a little longer, but it’s still quite simple. The length is simply because we have more options at the command line this time.


#!/bin/bash
# rsync_music_library_with
# Argument = -h hostname -i ip_address -u username

usage()
{
cat << EOF
usage: $0 options

This script attempt to rsync with an iTunes Library.

OPTIONS:
   -?      Show this message
   -h      hostname
   -i      ip (overrides hostname)
   -u      username (optional)
EOF
}

while getopts ":h:i:u:" OPTION
do
     case $OPTION in
         h)
             RSYNC_SERV_HOSTNAME=$OPTARG
             ;;
         i)
             RSYNC_SERV_IP=$OPTARG
             ;;
         u)
             RSYNC_SERV_USERNAME=$OPTARG
             ;;
         ?)
             usage
             exit
             ;;
     esac
done

# if no hostname or ip is provided, exit
if [[ -z $RSYNC_SERV_HOSTNAME ]] && [[ -z $RSYNC_SERV_IP ]]
then
     usage
     exit 1
fi

# if a hostname is provided, lookup the ip
if [[ -z $RSYNC_SERV_IP ]]
then
    RSYNC_SERV_IP=`./find_bonjour_client $RSYNC_SERV_HOSTNAME 2> /dev/null`
fi

if [[ -z $RSYNC_SERV_USERNAME ]]
then
    RSYNC_SERV_USERNAME=$USER
fi

echo `date`
echo "Will rsync with $RSYNC_SERV_IP as $RSYNC_SERV_USERNAME"
rsync -a --delete -u -v -e ssh --exclude=".DS_Store" \
$RSYNC_SERV_IP:/Users/$RSYNC_SERV_USERNAME/Music/iTunes/iTunes\\\ Music/ \
/mnt/store/Public\ Media/Music/
echo "Done!"

That script will now use the original script we wrote to look out on the network and see if the “master” is present. If so, it will sync up with it. If not, it will simply stop. You could probably tweak the end to make the script exit a little more gracefully, but this does the trick.

Additionally, if the master happens to have a static IP, this script is also ready to use that instead of a hostname.

Step 4: Set up a cron Job to Execute the Script

The last thing to do is quite simple. We want to have our server attempt to sync automatically on a regular basis. We’ll make use of cron for this task. For most Linux distributions you simply need to type:

crontab -e 

to edit your crontab. Once in edit mode, add this line:

1 * * * * /path/to/your/script/rsync_music_library_with -h mcp

That’s it. Now any edits you make on your master library will sync (hourly in this case) with your server. Hourly may seem like overkill, but there’s really no overhead given rsync’s smart approach and this helps to ensure that even if the master laptop is only actually online for a short while, a sync will occur.

Step 5: Have Other Systems Pull From Your Server

The last step is optional, but if you have other computers that you would like to have sync with the master server, simply use rsync to have them pull from the master server in the same manner we used above. If your server is like mine, it uses a static IP address and therefore you can simply supply that and bypass all of the name resolution.

If you are syncing with iTunes, you’ll want to modify the script above to also pull the meta data files in your iTunes library (like iTunes Music Library.xml).

Similarly tagged OmniNerd content:

Information This article was edited after publication by the author on 20 Aug 2009. View changes.
Thread parent sort order:
Thread verbosity:

It’s been awhile since I played with RSync – a long while. If you had the server set for a two-way rsync with two separate laptops, I would think then both laptops should have the same library.

Do you think this would let an iPhone sync on either laptop and for purchased music to appear on both? I don’t have two Apple laptops to try it out with but I know you have more Apple gear in your house than me. :-)

Share & Socialize

What is OmniNerd?

Omninerd_icon Welcome! OmniNerd's content is generated by nerds like you. Learn more.

Voting Booth

The most important factor in buying my next car is?

7 votes, 1 comment