"Android permissions are a beast".
In desktop-Linux if you have root permissions you get spoiled to be able to do everything (good or bad). I found out, that in Android even if you execute something with root permissions, you are still not almighty, and need some tweaks. Maybe it is better this way ...
Below I will explain how I successfully mounted my sftp-share on a mount-point using Termux, and made it accessible to all users/apps/file explorers. Credits to MountainX: In his post How to automate rclone-mount without Termux or Magisk?
he paved the way to break through the permissions-jungle for clone-mount without Magisk/Termux. I believe one can do it within Termux/Magisk as well. The obvious advantage is scriptability, cronjobs to regularly check/restore connections etc.
Steps:
- I prefer doing command-line stuff on Termux using my keyboard from a desktop through ssh, and not on the touchscreen (in case somebody is interested, summary for a quick-setup but not the most secure:
$ pkg install openssh
, create a password with $ passwd
, launch $ sshd
, find your android's ip with $ ifconfig
, look under wlan0 the entry: inet 192.168.XXX.XXX, login to your android device from a desktop with $ ssh 192.168.XXX.XXX -p 8022
). When inside Termux I also strongly suggest exploring directories with Midnight-Commander: $ pkg install mc
. All the following steps were performed through ssh-connection(s) from the terminal-emulator of a desktop computer. Main advantage: one can have multiple ssh-connections, for example one as root-CLI, a second as normal-user-CLI, a third with 'midnight-commander' to check the results of mounting.
- In Magisk-Manager-Settings of the android-device find the "Namespace" Option and choose "Global namespace" or "Inherited namespace" (for the time being it is working with both, if I find some problems in the future I will edit the answer).
- The executables rclone and fusermount MUST be in /system/bin AND have ownership system:shell. NOT root:root. It seems, when launched that way they break through the permissions-jungle. Other combinations do not work (for example ownerships changed but launched from another directory). But it is not straightforward how to copy them in /system/bin because it is generally mounted read-only. Supposing both files are already installed in /data/data/com.termux/files/usr/bin, we must (a) make /system/bin writable, (b) copy them (c) change ownerships and mod, (d) restore /system/bin as read-only.
In Termux:
$ su
# mount -o rw,remount /system
# cp /data/data/com.termux/files/usr/bin/rclone /system/bin/
# cp /data/data/com.termux/files/usr/bin/fusermount /system/bin/
# chown system:shell /system/bin/rclone
# chmod 775 /system/bin/rclone
# chown system:shell /system/bin/fusermount
# chmod 775 /system/bin/fusermount
# mount -o ro,remount /system
# exit
$
- Now we can launch rclone/fusermount through su -c "XXXX" again, but this time through their /system/bin/ copies. By the way, we do not need to pass $PATH variable any more. In my search I discovered the su --mount-master option as well.
su --mount-master -c "HOME=$HOME rclone -vvv mount sshfs-srv-rasp1: /storage/emulated/legacy/srv-rasp1 --allow-other"
As long as the above command is up and running, the mount-point /storage/emulated/legacy/srv-rasp1 is successfully linked to the sftp-share. The option "--allow-other" allows users other than root to have access. I could confirm access through a separate ssh-connection with 'midnight-commander'. But the moment the command is killed with Ctrl-c, the connection closes.
You can add the "--daemon" option to have it run in background. You can check anytime that rclone is still alive with pgrep rclone
In order to kill the connection gracefully: su -c "fusermount -u -z /storage/emulated/legacy/srv-rasp1"
. Note the -z ("lazy") option: it forces unmount even when someone is using the share. This command kills rclone in the background (check with pgrep).
What mount point to choose? My suggestion is, to create a mountpoint-directory in a place accessible from all apps. A good place is somewhere in internal-SD, typically /storage/emulated/0/XXXX or /storage/emulated/legacy/XXXX. You must check in your specific android variant where it lives. Beware, that that termux and su -c "XXXX" may see different things under /storage/emulated !. For example, on my Samsung Tab4:
$ ls /storage/emulated
0 legacy
but
$ su -c "ls /storage/emulated"
legacy
Interestingly, both /storage/emulated/0 and /storage/emulated/legacy refer to the same internal SD-Card. Since rclone command is executed through su -c "XXXX", I decided to use the common denominator "legacy". You have to check in your device the exact path through which su -c "XXXX" sees the internal SD-Card.
Until now, our sftp-share is accessible only within termux. Other apps (e.g. File-Explorer) don't have access. This has to do with ownerships/permission granted to the mount-point by rclone.
Check while rclone is running:
ls -l /storage/emulated/legacy/
drwxrwx--- 2 root sdcard_r 4096 Jan 1 2014 Alarms
drwxrwx--x 5 root sdcard_r 4096 Sep 22 17:47 Android
drwxrwx--- 2 root sdcard_r 4096 Jan 1 2014 DCIM
drwxrwx--- 3 root sdcard_r 4096 Oct 6 18:14 Documents
drwxrwx--- 3 root sdcard_r 4096 Oct 8 17:28 Download
...
drwxr-xr-x 1 root root 0 Oct 9 14:38 srv-rasp1
Ownership of mount-point srv-rasp1 is root:root. Changing the ownership out-of-connection has no effect: rclone grants again root:root. Even my rooted ES-Explorer could not see the content of srv-rasp1. The solution is to tweak the ownerships in rclone: --gid 9997 --dir-perms 0771 --file-perms 0660 --umask=0
The command so far:
su --mount-master -c "HOME=$HOME rclone -vvv mount sshfs-srv-rasp1: /storage/emulated/legacy/srv-rasp1 --gid 9997 --dir-perms 0771 --file-perms 0660 --umask=0 --allow-other --daemon"
Check ownerships/permissions again:
$ ls -l /storage/emulated/legacy
drwxrwx--- 2 root sdcard_r 4096 Jan 1 2014 Alarms
drwxrwx--x 5 root sdcard_r 4096 Sep 22 17:47 Android
drwxrwx--- 2 root sdcard_r 4096 Jan 1 2014 DCIM
drwxrwx--- 3 root sdcard_r 4096 Oct 6 18:14 Documents
drwxrwx--- 3 root sdcard_r 4096 Oct 8 17:28 Download
...
drwxrwx--x 1 root everybody 0 Oct 9 14:46 srv-rasp1
Voila. Mount-point srv-rasp1 was given group-ownership "everybody". ES-Explorer and all other apps can now access see the contents of srv-rasp1 mount.
Some comments, slightly unrelated to the question but still interesting:
- rclone mounts as "root" directory by default not the actual root ("/") but the HOME directory ("/home/XXXX/") of the user who logs in the ssh/sftp server. In order to override this, I found a not-so-clear answer here: https://github.com/rclone/rclone/issues/4307. By experimenting, I discovered that rclone accepts the general syntax of Linux sshfs command: server:/path/to/mount/, with the remark that instead of "server" we give the configuration-name. So, if I want to mount srv-rasp1/mnt/ I simply have to type:
... rclone mount sshfs-srv-rasp1:/mnt /storage/emulated/legacy/srv-rasp1 ...
. The mount-point will be showing now the contents of srv-rasp1/mnt/
- In his post MountainX adds some rclone options regarding vfs and cache stuff. This is beyond my knowledge but seems to achieve a seamless interaction between device <-> server, simultaneous writing/reading etc. I simply added them to the command line.
Below my final command:
su --mount-master -c "HOME=$HOME rclone -vvv mount sshfs-srv-rasp1:/mnt /storage/emulated/legacy/srv-rasp1 --gid 9997 --dir-perms 0771 --file-perms 0660 --umask=0 --cache-dir /storage/emulated/legacy/.cache --vfs-cache-mode full --vfs-cache-max-age 2h0m0s --vfs-cache-poll-interval 5m0s --allow-other --daemon"
In my setting, I didn't need:
- to tweak anything regarding SELinux (see also the comment of MountainX in the above mentioned link).
- to pass any Termux enviromental variable regarding libraries (e.g. LD_LIBRARY_PATH=$LD_LIBRARY_PATH). The executables rclone and fusermount are stand-alone, don't need any external libraries.
- to tweak anything regarding namespaces (e.g. readlink or nsenter stuff), as Irfan Latif suggested (see How to mount rclone on Android? )
However, I can not exclude that the above mentioned tweaks could be needed in other settings. For this reason I mention them.
sudo
orsu -c
ortsu -c
, better open a root shell and run commands from there. You can also usestrace
to get the error more precisely. And I hope you've gone through this answer of mine.