Adding music from an ssh-accessible remote server to an Android phone via Debian 11

This might be subtitled “Neil paying the penalty for bad decisions.”

tl;dr:

Install gvfs-fuse, then

rsync -rvhP --size-only --temp-dir='/home/neil' -e ssh 'remotemachine://path/to/music/*' '/run/user/1000/gvfs/mtp:host=PhoneName/Internal shared storage/Music'

Background

I have a phone. It’s a OnePlus 6T, running /e/.

I want music on that phone, for me to playback locally / offline.

I have a computer, running Debian 11, to which I can connect my phone via USB.

I have the music I want in a directory on a remote machine (remotemachine), which I can access from the computer via certificate-only SSH. (Thankfully, I’ve already got ~/.ssh/config set up to make this bit easy.)

I don’t want or need the music to be stored on my computer.

Question

How do I get that music onto my phone in a way which makes it easy to add other music in the future? (i.e. I’d rather not have to copy 50GB of music each time I want to add a 10MB file.)

Answer

Getting the phone connected to the computer

I plugged in the phone, via a USB-C cable, and it was recognised automatically and mounted in Nautilus.

However, I could not access anything.

It turns out that, by default, USB file transfer permission is disabled on the phone.

Screenshot of USB settings in Android

To fix that, I went into Settings / Connected devices / USB, and set:

USB controlled by to This device Use USB for to File transfer

I browsed to it again in Nautilus, and I could access my phone’s storage. Excellent.

Behind the scenes, mtp is doing the work (as I understand it, at least).

So now I just need to get the music on it.

Getting the music onto the phone

This should be simple, since the computer has access to both the phone and the remotemachine which has the music.

I verified that it would indeed work, by using scp to copy an album onto the phone. It worked, and pretty quickly.

But I would rather use rsync instead of scp, so I can sync only new files in the future.

Easy: rsync over ssh:

rsync -rvz -e ssh 'remotemachine://path/to/music/*' '/run/user/1000/gvfs/mtp:host=OnePlus_OnePlus/Internal shared storage/Music'

First, install gvfs-fuse.

Except it was not this easy. No music transferred, and instead the terminal was full of errors. I did not (more fool me) keep the exact error messages, but the gist was:

mkstemp operation not supported rsync rename input output error

It appears that one cannot rsync into a subdirectory on an mtp-mounted share, as there is a problem with the creation of a temporary file and renaming it to whatever the “real” name should be.

I could rsync the files to a directory on the computer, and then mv them to the phone. But that is ugly, and requires me to have sufficient space on my computer for all the music. (I mean, I probably do, but it’s ugly.)

rsync has a switch to essentially proxy the files through one directory before putting them in their intended destination, --temp-dir or -T:

This option instructs rsync to use DIR as a scratch directory when creating temporary copies of the files transferred on the receiving side.

Basically - as I understand it - it does the rsync and the mv in one command, without storing all the files on the computer as part of it.

So:

rsync -rvhP --temp-dir='/home/neil' -e ssh 'remotemachine://path/to/music/*' '/run/user/1000/gvfs/mtp:host=OnePlus_OnePlus/Internal shared storage/Music'

It works, but it is slow.

I fiddled around a bit with it, meaning I had music on both the phone and the server. I noticed that, using the rsync incantation above, it still seemed to be transferring / overwriting everything, each time, rather than syncing only the difference.

I was getting a bit fed up by this point, so I added --size-only to the command, and that did the trick. (Since it is music, being this blunt will be fine.)

So:

rsync -rvhP --size-only --temp-dir='/home/neil' -e ssh 'remotemachine://path/to/music/*' '/run/user/1000/gvfs/mtp:host=OnePlus_OnePlus/Internal shared storage/Music'

But it is still slow. At time of writing, I have over 6,000 files to go, so I’ll be here for a while.

And if the phone disconnects (I am not sure why it did that; perhaps because it reached 100% charge?), you have to run the script again.

Update: it is not lightning fast, but it is faster than I had first appreciated. It turns out that the initial files were around 150MB, and so - unsurprisingly? - took a little longer than files of 4-5MB.