pixel-backup-gang icon indicating copy to clipboard operation
pixel-backup-gang copied to clipboard

Network mount option

Open lightc786 opened this issue 1 year ago • 10 comments
trafficstars

Is there any way to do this with a network share rather than an hdd directly connected?

The reason I ask is because I'd like to keep my pixel charged to 50% and I do this by using a smart outlet and tasker to automate turning it off and on to keep the battery at 50%.

If the power delivery powered USB hub turns off, the ext4 drive will disconnect.

lightc786 avatar Sep 29 '24 01:09 lightc786

i wish. my understanding is that it is only possible with a custom kernel. the stock pixel kernel doesn't include filesystem support for nfs or cifs or smb3 etc.

so one would need to recompile the kernel with nfs support

master-hax avatar Sep 30 '24 06:09 master-hax

you could also set it up using a FUSE based solution but it is very slow in my experience. you could also use adb or ftp or syncthing to push media to the pixel's attached drive instead.

master-hax avatar Sep 30 '24 10:09 master-hax

Check out EasySSHFS. It's the only way I easily found to do it on Android 10 (11?)+ I've noticed it will also scan periodically throughout the day for new media, or you can broadcast a media scan

DevinDuricka avatar Oct 04 '24 19:10 DevinDuricka

Thanks I'll look into that. Is that a fuse based solution?

How slow are these network options exactly?

I'm using syncthing current to push files to the HDD attached to the pixel but my worry is that keeping it at 100% charge is not a good idea.

Even if one of these other network solutions is a little slow, it will allow me to keep the battery at 50% to hopefully avoid it from swelling down the road.

Also I was wondering whether there is any way to get the Pixelify module to act as if it is the physical pixel I am using to do my backups. If the module could use the same IMEI, I think it would be less likely anything would be flagged by Google down the road.

For now I will use the pixel to be safe but if there was a method to clone all the attributes from my physical device into a VM with Pixelify, it would reduce a lot of the headache involved with maintaining the battery, syncing items, mounting the HDD, re-writing exif and etc.

Thanks again!

lightc786 avatar Oct 04 '24 19:10 lightc786

I'm running Android 14 on it via LineageOS, and I think every solution Android 10+ requires fuse (don't quote me on that). In this case though, yes, it is a fuse based solution.

Umm, I haven't really noticed any slowness. It does run into issues though with large files, although it could be an encoding issue with the large file itself, still investigating. Otherwise, the real limit is the network connection (reading from LAN and upload) and the CPU + Google Photos app processing speed.

I've seen some people use a magisk module called acc to limit the battery charge. LineageOS also has it built in, so I haven't had to try it yet. I also just replaced the battery in one of the other Pixels I have, and it wasn't too terrible of a process (but I've had a little practice).

Agreed though, a VM would be a great solution.

DevinDuricka avatar Oct 05 '24 20:10 DevinDuricka

@DevinDuricka Are you still on Lineage? I am struggling with Lineage 22.2 and this script. Did I understand you correct? You have been able to mount a network share as an internal mount with the App EasySSHFS alone, and Google Photos App was able to see that and started uploading Photos?

deluxio avatar Apr 23 '25 17:04 deluxio

Yep! It's been a while since I did this, but I didn't even end up using the script. I think (if memories serves) I found the best compatibility with mounting the network share directly to the DCIM folder. I think that would trigger the media folder scan the best? Or I might have done it because I wanted Photos to automatically delete backed up media after 30 days. I also only tried a SMB share. EasySSHFS doesn't give you a lot of great feedback, so I thought it wasn't working initially, but I had actually input the wrong credentials.

It's been a while since I did this though, ago my memory is a little foggy 😅

DevinDuricka avatar Apr 23 '25 20:04 DevinDuricka

Thanks for your reply! I just tried the whole night and was not able to mount it. Maybe It's because I am already on Lineage 22.2, will downgrade and try again. Did you update your Lineage meanwhile? I really struggle with EasySSHFS, do you mind sharing the config of your EasySSHFS? Really close to downgrade to the Stock Android 10 but don't want to do it because of the security issues. Your solution is the best so far, new Android version, no messing around with hubs etc. Really appreciate any input on that. Thanks again!

deluxio avatar Apr 24 '25 01:04 deluxio

Out of curiosity, do you have Magisk installed and gave EasySSHFS superuser permissions? That is a whole process, but I think SU permissions are required.

I'm also still on Lineage 21, so maybe 22 is the issue?

Also, I misspoke earlier. I'm connecting to port 22, which is SFTP and not SMB. I think I couldn't get SMB to authenticate, and tried SFTP as a hail-Mary which did work.

The remote server format was: /media/{username}/{path_to_folder} <- obviously yours might be different I then selected the local folder using the select button

TBH, I only did it once to backup a whole backlog of videos, and then my server died and I never got around to replacing it. Since then I've just installed Syncthing fork on the Pixel 1 and Pixel 9 and sync directly to the Pixel 1. Thusfar I haven't run into issues with space, but I don't take a ton of pictures/videos.

DevinDuricka avatar Apr 24 '25 01:04 DevinDuricka

The newest version of Magisk (28.1) is installed. Lineage 22 can maybe be the issue. Just checked the logs EasySSHFS debug logs, it says fuse.sshfs is not in /proc/mounts I am on it to figure out what that is, global namespace is already turned on in Magisk.

deluxio avatar Apr 24 '25 19:04 deluxio

I have recompiled the kernel for marlin with NFS support. The NFS share is visible through file managers, but does not register in Google Photos or the Lineage OS Gallery app.

If I use a file manager and use the share menu to upload to Google Photos, then the photos appear in the Gallery and Photos app. I believe the files are downloaded to a tmp directory when uploading. After a reboot the local files disappear and are no longer visible in the Gallery app.

If anyone has any ideas on how to get the Google Photos app to read the NFS share, please let me know.

# NFS server     /etc/exports.d/dietpi.exports 
### immich user folders
# anonuid and anongid are used as I do not want to change ownership of the files. 
/mnt/Seagate-14TB/Pictures/library/admin *(ro,sync,no_root_squash,fsid=0,crossmnt,no_subtree_check,anonuid=1000,anongid=1000)
adb shell
mkdir -p /data/nfs-share
su --mount-master -c "/data/adb/magisk/busybox mount -t nfs -o nolock, 192.168.1.84:/mnt/Seagate-14TB/Pictures/library/admin /data/nfs-share"

mkdir -p /mnt/runtime/write/emulated/0/DCIM/Camera/nfs-share
setenforce 0
mount -t sdcardfs -o nosuid,nodev,noexec,noatime,gid=9997 /data/nfs-share /mnt/runtime/write/emulated/0/DCIM/Camera/nfs-share

am broadcast \
  -a android.intent.action.MEDIA_SCANNER_SCAN_FILE \
  -d file:///mnt/runtime/write/emulated/0/DCIM/Camera/nfs-share/

SK4G avatar Oct 06 '25 21:10 SK4G

I have recompiled the kernel for marlin with NFS support.

great work! do you mind sharing the instructions here?

If anyone has any ideas on how to get the Google Photos app to read the NFS share, please let me know.

are you running your file managers with root access? i'm surprised the files are accessible without fixing the ownership & permissions.

also i think your am broadcast command is not correct, apps can't access /mnt. it should start with /storage or whatever other path that the apps see.

master-hax avatar Oct 06 '25 21:10 master-hax

The LineageOS recommended dev environment is Ubuntu 20.04 LTS. I chose a systemd-nspawn container as the install method.

Guide
[guide](https://gist.github.com/davidgarland/ae6da821016fde4c877973ddd3f8f116) didn't work under nixos, but it worked using a [systemd-nspawn](https://dzx.fr/blog/how-to-build-lineageos-inside-a-container/)

I had to do the below additional steps.

# enter systemd-nspawn container
sudo systemd-nspawn -D /var/lib/machines/ubuntu --bind=/dev/bus/usb  
\--bind=/etc/resolv.conf:/etc/resolv.conf

su - $NON-ROOT-USER

grep -qxF 'export USE_CCACHE=1' ~/.bashrc || echo 'export USE_CCACHE=1' >> ~/.bashrc
grep -qxF 'export CCACHE_EXEC=/usr/bin/ccache' ~/.bashrc || echo 'export CCACHE_EXEC=/usr/bin/ccache' >> ~/.bashrc
grep -qxF 'export PATH="/bin:/usr/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin:/bin"' ~/.bashrc || echo 'export PATH="/bin:/usr/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin:/bin"' >> ~/.bashrc
grep -qxF 'export PATH=$HOME/platform-tools:$PATH' ~/.bashrc || echo 'export PATH=$HOME/platform-tools:$PATH' >> ~/.bashrc
grep -qxF 'export TERM=xterm-256color' ~/.bashrc || echo 'export TERM=xterm-256color' >> ~/.bashrc
source ~/.bashrc

wget https://dl.google.com/android/repository/platform-tools-latest-linux.zip  
unzip platform-tools-latest-linux.zip  
export PATH=$HOME/platform-tools:$PATH

# Extract the proprietary blobs
# On host  
adb tcpip 5555  
# In container  
adb connect 192.168.1.39:5555
~/android/lineage/device/google/marlin/extract-files.sh

# If you want a flashable boot.img
cd $HOME/android/lineage/
source build/envsetup.sh
breakfast marlin

cd $HOME/android/lineage/kernel/google/marlin
make m1s1_defconfig
make menuconfig
# enable NFS client support under `File systems > Network File Systems`
mka bootimage -j4

# -j4 worked for me on a Steam Deck with 13GB of available 
# ram. You can play around with this based on your
# available ram

# If you get an error `mka: command not found` run
cd ~/android/lineage  
source build/envsetup.sh  
breakfast marlin

# for subsequent rebuilds I used this script
lineage@ubuntu:~/android/lineage$ cat compile-lineage-boot.img.sh 
#!/bin/bash

export ARCH=arm64
rm -rf $HOME/android/lineage/out
cd $HOME/android/lineage/kernel/google/marlin
make clean
make mrproper
make m1s1_defconfig

cd $HOME/android/lineage/
source build/envsetup.sh
breakfast marlin
mka bootimage -j4

# The boot.img will be under ~/android/lineage/out/target/product/marlin. 
# I copied the boot.img from the container to the host and flashed it. 

# on host
sudo cp /var/lib/machines/ubuntu/home/lineage/android/lineage/out/target/product/marlin/boot.img $HOME/
adb reboot bootloader
adb flash boot boot.img

SK4G avatar Oct 07 '25 00:10 SK4G

are you running your file managers with root access?

I have granted the file managers root access.

also i think your am broadcast command is not correct, apps can't access /mnt. it should start with /storage or whatever other path that the apps see.

Wow I can't believe I overlooked this part. I looked at your mount_ext4.sh script and messed this part up. The files show up in the Gallery and Google Photos app with

am broadcast \
  -a android.intent.action.MEDIA_SCANNER_SCAN_FILE \
  -d file:///storage/emulated/0/DCIM/Camera/nfs-share/

SK4G avatar Oct 07 '25 00:10 SK4G

the files will always show up in an app with root access, need to use a regular app to make sure the mounting worked.

the am broadcast command is not strictly necessary, you can just force close & reopen google photos and it should have the same effect.

master-hax avatar Oct 07 '25 01:10 master-hax

When using NFS I found the media scan to be necessary.

I created a magisk module that reads a .nfs-mount.conf and mounts a NFS share at boot.

.nfs-mount.conf
# /sdcard/.nfs-mount.conf
# Example configuration file for NFS Mounter Magisk module

NFS_SERVER_IP="192.168.1.84"
NFS_REMOTE_PATH="/mnt/Seagate-14TB/Pictures/library/admin"
NFS_MOUNT="/data/nfs-share"
ANDROID_NFS_PATH="DCIM/nfs-share"
SDCARD_MOUNT="/storage/emulated/0/${ANDROID_NFS_PATH}"
BIND_MOUNT="/mnt/runtime/write/emulated/0/${ANDROID_NFS_PATH}"
BUSYBOX="/data/adb/magisk/busybox"
service.h
#!/system/bin/sh
# Magisk boot script: Mounts a NFS share at boot

CONFIG_FILE="/sdcard/.nfs-mount.conf"

BOOTWAIT_MAX_COUNT=8
BOOTWAIT_COUNT_INTERVAL=15s

# Wait for system boot to complete
bootwait_count=0
until [[ $(getprop sys.boot_completed) || ${bootwait_count} -ge ${BOOTWAIT_MAX_COUNT} ]]; do
    sleep ${BOOTWAIT_COUNT_INTERVAL}
    bootwait_count=$((bootwait_count+1))
done
if [ ${bootwait_count} -ge ${BOOTWAIT_MAX_COUNT} ]; then
    exit 1
fi

# Load external config file if it exists
if [ -f "$CONFIG_FILE" ]; then
    . "$CONFIG_FILE"
else
    echo "[nfs-mount] Config not found at $CONFIG_FILE" >> /cache/magisk.log
    exit 1
fi

# Create mount directories
mkdir -p "$NFS_MOUNT" "$SDCARDFS_MOUNT"

# Disable SELinux
setenforce 0

# Mount NFS share
$BUSYBOX mount -t nfs -o nolock "$NFS_SERVER_IP:$NFS_REMOTE_PATH" "$NFS_MOUNT"

# Make share visible to Android apps
mount -o bind "$NFS_MOUNT" "$BIND_MOUNT"

# Trigger media scan
am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "file://$SDCARD_MOUNT/"

nfs-mounter-v0.1.zip

SK4G avatar Oct 08 '25 17:10 SK4G

I'm a super beginner in all of this so I apologize if this is a dumb question, but would it be possible to mount an FTP network drive that was created by plugging a flash drive into a TP-link BE11000 router? And if so what would be the most streamlined way to do this? I was just able to root my Pixel XL (on stock Android 10) and am afraid I'm going to make a wrong move and brick it. Any help would be very appreciated!

miner141299 avatar Nov 14 '25 18:11 miner141299