How to Remote Access(Synchronise) with Termux | jarvisstaraq (Linux/MacOS)
Use SSH and rsync to easily share files between machines on the go
The thought is to utilize an Android telephone as a record server
so we can have our documents consistently on us. I utilize a LG G5 which
advantageously has a SD Card opening in which I put a 128 Gb card to store
records I utilize day by day with 4 unique machines. In this article, we will
investigate how Termux, SSH, scp, and rsync can assist us with working on our
work process without depending on the cloud.
First of all, you need
to try to introduce everything Termux-related (additional items) through
either the F-Droid application archive or Google PlayStore, however don't
blend additional items from both.
Termux just has perused
admittance to outside stockpiles (SD Cards); however utilizing the
accompanying order, it will make an
Android/information/com.termux/records/index where you can peruse and compose
utilizing Termux:
termux-setup-storage
The command will also create symlinks in your Termux folder on your Android device.
Now let’s update the Termux environment and install SSH:
pkg up # or apt-get update
pkg install openssh
We want the SSH server to run anytime Termux is running. You can run a command each time you log into Termux by creating (if it does not exist) and editing the .bash_profile file within the home directory:
nano ~/.bash_profile
Here we are adding a condition to only start the SSH server and run scripts only once, where we create a file in the temporary directory that is wiped every time Termux launches and check if the file exists not to run tasks again:
#!/data/data/com.termux/files/usr/bin/bashif [ ! -e “$TMPDIR/termux-started” ]
then
sshd
touch “$TMPDIR/termux-started”
fi
I personally added another line to change the directory I work in to the one Termux has control over on SD Card. It should come outside the if the condition so that it is executed each time I log into Termux:
cd ~/storage/external-1/
Let’s focus on making SSH connections seamless (no password required).
To connect from Termux to your remote machine, create the SSH public key in Termux:
ssh-keygen -b 4096 -t rsa
Copy the key to the remote machine:
ssh-copy-id -i ~/.ssh/id_rsa.pub username@192.168.xx.xx
To connect from your remote machine to Termux, create SSH public key on your remote machine:
ssh-keygen -b 4096 -t rsa
Copy the SSH public key to Termux, to make an SSH connection to Termux, and also using the ssh-copy-id command, you need to use the Termux listening port 8022:
ssh-copy-id -p 8022 -i ~/.ssh/id_rsa.pub username@192.168.xx.xx
From now on, to connect via ssh to our Termux instance we will need only to enter the following command:
ssh -p 8022 192.168.xx.xx
FTP
Caution: plain FTP is expostulated and uncertain in any case. Termux FTP
server upholds just mysterious login, there no any confirmation and
everybody on your organization can get to records on your gadget. Use SFTP
(OpenSSH) all things being equal!
Termux FTP server is based on
busybox and service is managed by [Termux-services]. If you decided to use
FTP server, install these packages:
pkg install busybox termux-services
After installation you need to restart session or source this
file:
source $PREFIX/etc/profile.d/start-services.sh
Now you ready to enable and start the FTP daemon service:
sv-enable ftpd sv up ftpd
FTP server will run on port 8021 in read-only mode.
If you
need to stop server, run sv down ftpd.
The Best way to use SSH with Termux
SSH provides a secure way for accessing remote hosts and replaces tools
such as telnet, rlogin, rsh, ftp. Termux provides SSH via two packages:
dropbear and openssh. If you never used these tools before, it is recommended
to install 'openssh' as it is more common.
Using the SSH client
You
can obtain an SSH client by installing either `openssh` or `dropbear`.
Usage
example
To login to a remote machine where the ssh daemon is
running at the standard port (22):
ssh user@hostname_or_ip
Same as above, but if the ssh daemon running on different port, e.g. 8022:
ssh -p 8022 user@hostname_or_ip
Using public key authentication with ssh running on the standard port and a
private key stored in the file `id_rsa`:
ssh -i id_rsa user@hostname_or_ip
Note, that if `id_rsa` will be stored in `~/.ssh` directory, you can omit specifying it in the command. But if you have multiple keys, it is necessary to pick a specific key with `-i {path_to_privkey}`.
SSH Agent
Significant note: this doesn't work for Dropbear.
If
you wish to use an SSH agent to avoid entering passwords, the Termux openssh
package provides a wrapper script named `ssha` (note the `a` at the end) for
ssh, which:
- Starts the ssh agent if necessary (or connect to it if already running).
- Runs the `ssh-add` if necessary.
- Runs the `ssh` with the provided arguments.
This means that the agent will prompt for a key password at first run,
but remember the authorization for subsequent runs.
Using the SSH server
OpenSSH
OpenSSH (also known as OpenBSD Secure Shell) is a suite of secure
networking utilities based on the Secure Shell (SSH) protocol, which provides
a secure channel over an unsecured network in a client–server architecture.
Default
SSH port in Termux is 8022.
Starting and stopping OpenSSH server
Since
Termux does not use initialization system, services are started manually from
command line.
To start OpenSSH server, you need to execute this command:
sshd
If you need to stop `sshd`, just kill it's process:
pkill sshd
SSH daemon does logging to Android system log, you can view it by
running logcat -s 'sshd:*'. You can do that either from Termux or
ADB.
Setting up password authentication
Password authentication is enabled by default. This will allow you to
get started with it much easier. Before proceeding, make sure that you
understand that password authentication is less secure than a pubkey-based
one.
1. Ensure that everything is up to date and package
`openssh` is installed:
pkg upgrade pkg install openssh
2. Password authentication is enabled by default in configuration file.
But you can still review it ($PREFIX/etc/ssh/sshd_config), it should be like
this:
PrintMotd yes PasswordAuthentication yes Subsystem sftp /data/data/com.termux/files/usr/libexec/sftp-server
3. Set new password. Execute command passwd. While program allows
minimal password length is 1 character, the recommended password length is
more than 8-10 characters. Passwords are not printed to console.
$ passwd New password: Retype new password: New password was successfully set.
Setting up public key authentication
Public key confirmation is the suggested way for signing in utilizing SSH. To
utilize this sort of confirmation, you really want to have a public/private
key pair. For fruitful login, the public key should exist in the approved keys
list on remote machine while private key ought to be remained careful on your
neighborhood have.
In the accompanying model it will be accepted
that you need to build up open key confirmation between your PC (have) and
your Android gadget running Termux (remote). It additionally will be accepted
that you running Linux dispersion on your PC.
1. If you do
not have keys, you can generate them. In this example we will generate RSA
key. On PC, execute this command:
ssh-keygen -t rsa -b 2048 -f id_rsa
The command shown above generates private RSA key with 2048 bit key length and
saves it to file `id_rsa`. In the same directory you can find a file
`id_rsa.pub` – it is a public key.
Significant note: 2048 piece is
the insignificant key length that is viewed as protected. You can utilize
higher qualities, yet don't utilize higher than 4096 as distant server may not
help enormous keys.
2. Copy key to the remote machine (Termux).
Password authentication has to be enabled in order to install pubkey on remote
machine. Now do:
ssh-copy-id -p 8022 -i id_rsa IP_ADDRESS
Do not forget to replace `IP_ADDRESS` with the actual LAN IP address of your
device. It can be determined by using command ifconfig.
Alternative you can manually copy the content inside "id_rsa.pub"(public key)
which is already on PC and looks like
ssh-rsa <A LOT OF RANDOM STRINGS> user@host user@host and
paste to the Termux file $HOME/.ssh/authorized_keys(remote
machine) Remember to connect through
ssh user@<Phone_IP> -p 8022 so you can copy the content of
public key using any text editor available on PC and paste inside Termux
If
everything was okay, you will see a message like this one:
Number of key(s) added: 1 Now try logging into the machine, with: "ssh -p '8022' '192.168.1.4'" and check to make sure that only the key(s) you wanted were added.
3. From this point password authentication can be disabled.
Edit file $PREFIX/etc/ssh/sshd_config and replace line beginning with
"PasswordAuthentication" by
PasswordAuthentication no
Then execute command pkill sshd; sshd in order to restart server
with updated configuration file.
Using Termux you can acces your Android device’s functionalities. You will
have to install the Termux:API add-on.
In termux install the following
package:
pkg install termux-api
Now you can access your battery info for example:
termux-battery-status
In order to parse the info in json form obtained through the previous command, install json parser (on macOS “brew install jq”):
pkg install jq
Now you can get what you need typing jq -r ‘.DICTIONARY_KEY’.
Let’s setup our RSYNC workflow, here is how it will work:
While the RSYNC script will run continuously, we need to check the battery status every 5 minutes and write the result in the file. Then we find the Android device’s IP on the network using the device’s mac address (it could serve as a hotspot or be on a local network), get the file from the Android device to the remote machine and move on with the transfer if there is enough left (a threshold of 20%) or the phone if plugged in, we transfer from the Android device to the remote machine and then vice versa, checking there have been changes to the folder or files.
Install rsync on Termux:
pkg install rsync
We execute the script ad vitam aeternam with:
while true
do
done
Get the battery status and write the JSON response in a .json file for later use.
echo $(termux-battery-status) > ~/storage/external-1/battery/script/folder/battery.json
Contrary to most scripts, we are not putting the script interpreter #!/bin/bash (#!/data/data/com.termux/files/usr/bin/sh in Termux) because we will be putting the interpreter into the command.
We need to create a daemon to run the script in the background. To do so, first make the script executable:
chmod +x ~/path/to/battery/script.sh
Then run the following command:
daemonize -p $PREFIX/var/run/script.pid $PREFIX/bin/bash ~/path/to/battery/script.sh
Now, you can run a command each time you log into Termux using the same .bash_profile file:
nano ~/.bash_profile
And add:
#!/data/data/com.termux/files/usr/bin/bashif [ ! -e “$TMPDIR/termux-started” ]
then
sshd
daemonize -p $PREFIX/var/run/get-battery.pid $PREFIX/bin/bash ~/storage/external-1/development/get-battery.sh
touch “$TMPDIR/termux-started”
fi
We get the IP address of our remote machine:
IP=`ifconfig en0 2>/dev/null|awk ‘/inet / {print $2}’`
Then, declare a variable to record last character of the IP string:
LAST_IP=”${IP: -1}”
And execute a loop which will remove the last character of the string each time to stop at the first ‘.’ so that we have the IP configuration of the network we are on.
while [ “${LAST_IP}” != “.” ]
do
IP=${IP%?} # Here we remove the last character of the IP string
LAST_IP=”${IP: -1}”
done
After which we map all IP address on the network through a ping scan:
echo $(nmap -sP “${IP}”0/24 >/dev/null)
We then get the IP address matching the mac address of our Android device:
IP_ADDRESS=`arp -an | grep mac:address:android:device | awk ‘{print $2}’ | sed ‘s/[()]//g’`
Our remote machine will use scp to copy the battery file over ssh to the current folder:
scp -P 8022 192.168.xx.xx:~/storage/external-1/path/to/battery/script/folder/battery.json /path/to/remote/machine/folder/
We get battery status from the battery.json file:
PLUGGED=`cat battery.json | jq -r ‘.plugged’`
PERCENTAGE=`cat battery.json | jq -r ‘.percentage’`
Check if either the device is plugged in or the percentage is high enough (here we set it at 20% battery):
OPERATIONAL=”false”
if [[ “$PLUGGED” | jq -r ‘.plugged’ == *”PLUGGED_AC”* ]]
then
OPERATIONAL=”true”
elif [[ “$PERCENTAGE” -ge “20” ]]
then
OPERATIONAL=”true”
fi
If one of the condition is true we start the synchronisation using rsync:
if [ “${OPERATIONAL}” == “true” ]
then
rsync -avr -e ‘ssh -p 8022’ — exclude-from=’/path/to/rsync-exclude.txt’ $IP_ADDRESS:~/storage/external-1 /path/to/remote/machine/folder
fi
Synchronise files from Android phone to the remote machine. We use the option — exclude-from= to use a file in which we declare which files and folders we don’t want to synchronise.
#!/bin/bashwhile true
do
IP=`ifconfig en0 2>/dev/null|awk ‘/inet / {print $2}’`
LAST_IP=”${IP: -1}”
while [ “${LAST_IP}” != “.” ]
do
IP=${IP%?}
LAST_IP=”${IP: -1}”
done
echo $(nmap -sP “${IP}”0/24 >/dev/null)
IP_ADDRESS=`arp -an | grep mac:address:android:device | awk ‘{print $2}’ | sed ‘s/[()]//g’`scp -P 8022 “${IP_ADDRESS}”:~/storage/external-1/development/battery.json .
PLUGGED=`cat battery.json | jq -r '.plugged'`
echo "${PLUGGED}"
PERCENTAGE=`cat battery.json | jq -r '.percentage'`
echo "${PERCENTAGE}"
OPERATIONAL=”false”
if [[ $PLUGGED == *”PLUGGED_AC”* ]]
then
OPERATIONAL=”true”
elif [[ “$percentage” -ge “20” ]]
then
OPERATIONAL=”true”
fi if [ “${OPERATIONAL}” == “true” ]
then
rsync -avr -e ‘ssh -p 8022’ — exclude-from=’/path/to/rsync-exclude.txt’ $IP_ADDRESS:~/storage/external-1/ /path/to/remote/machine/folder
fi
echo “sleep”
sleep 60s
done
When we want to synchronise from MacOS to Android, we use a similar approach, except that we first check if files and folders were modified or added in the directory we are synchronising.
First, we create a log file with the touch command to record the result of rsync and so we can easily see if past synchronisations succeeded or not.
LOGFILE=/path/to/remote/machine/folder/rsync_logs.txt
if [ ! -f “$LOGFILE” ]
then
touch “$LOGFILE”
fi
We create another file to record the date and time rsync ran successfully; because the script runs for the first time, we create a last_sync.txt file to write the date and time at which we did the last sync. We create the variable FILES that will be used in the condition checking for modified files before running rsync.
LASTSYNC=/path/to/remote/machine/folder/last_sync.txt
if [ ! -f "$LASTSYNC" ]
then
touch "$LASTSYNC"
FILES="first time"
else
LASTDATE=`cat "${LASTSYNC}"`
echo "${LASTDATE}"
LASTDATE=`date -r "$LASTDATE" +"%s"`
echo "${LASTDATE}"
now=`date +%s`
echo ${NOW}
PERIOD=$(( ($NOW - $LASTDATE) / 60 ))
echo ${PERIOD}
FILES=`find /path/to/remote/machine/folder -mmin -"${PERIOD}" | sort -n -r`
fi
If the file already exists, we get the last date and time from the file using “cat” and then parse the date as unix epoch time.
LASTDATE=`cat “${FILE}”`
LASTDATE=`date -r “$LASTDATE” +”%s”`
Then we subtract the current unix epoch time with the last date and time and get minutes:
PERIOD=$(( ($now — $last_date) / 60 ))
Now, let’s use the “find” command to check changes inside the sync folder. The following command will return a list of all changes inside the folder as well as the synchronised folder all files ordered by size.
FILES=`find ~/remote_machine_sync_folder -type f -mmin -”${period}”`
If the files variable is not null, we run rsync and then check if the command succeeded (when we write the date and time it did) or not and log the result into a rsync_logs.txt file:
if [[ $SYNCING -eq 0 ]]
then
echo “${SYNCING}” > “${LOGFILE}”
echo `date +%s > “${LASTSYNC}”`
echo “success and sleep”
sleep 10s
else
echo “${SYNCING}” > “${LOGFILE}”
echo “fail and sleep”
sleep 10s
fi
And finally, we write the date and time to the last_sync.txt file.
Synchronise files from MacOS to Android
#!/bin/bashwhile true
do
LOGFILE=/path/to/remote/machine/folder/rsync_logs.txt
if [ ! -f “$LOGFILE” ]
then
touch “$LOGFILE”
fi
LASTSYNC=/path/to/remote/machine/folder/last_sync.txt
if [ ! -f “$LASTSYNC” ]
then
touch “$LASTSYNC”
FILES=”first time”
else
LASTDATE=`cat “${LASTSYNC}”`
echo “${LASTDATE}”
LASTDATE=`date -r “$last_date” +”%s”`
echo “${LASTDATE}”
NOW=`date +%s`
echo ${NOW}
period=$(( ($NOW — $LASTDATE) / 60 ))
echo ${period}
FILES=`find /path/to/remote/machine/folder -mmin -”${period}” | sort -n -r`
fi
if [ “${FILES}” ]
then
IP=`ifconfig en0 2>/dev/null|awk ‘/inet / {print $2}’`
LAST_IP=”${IP: -1}”
while [ “${LAST_IP}” != “.” ]
do
IP=${IP%?}
LAST_IP=”${IP: -1}”
done
echo $(nmap -sP “${IP}”0/24 >/dev/null)
IP_ADDRESS=`arp -an | grep mac:address:android:device | awk ‘{print $2}’ | sed ‘s/[()]//g’`scp -P 8022 “${IP_ADDRESS}”:~/storage/external-1/development/battery.json /path/to/remote/machine/folder/
PLUGGED=`cat battery.json | jq -r '.plugged'`
echo "${PLUGGED}"
PERCENTAGE=`cat battery.json | jq -r '.percentage'`
echo "${PERCENTAGE}"
OPERATIONAL=”false”
if [[ $PLUGGED == *”PLUGGED_AC”* ]]
then
OPERATIONAL=”true”
elif [[ “$percentage” -ge “20” ]]
then
OPERATIONAL=”true”
fi if [ “${OPERATIONAL}” == “true” ]
then
rsync -avr -e ‘ssh -p 8022’ — exclude-from=’/path/to/rsync-exclude.json’ /path/to/remote/machine/sync/folder $IP_ADDDRESS:~/storage/external-1
SYNCING=$?
if [[ $SYNCING -eq 0 ]]
then
echo “${SYNCING}” > “${LOGFILE}”
echo `date +%s > “${LASTSYNC}”`
echo “success and sleep”
sleep 10s
else
echo “${SYNCING}” > “${LOGFILE}”
echo “fail and sleep”
sleep 10s
fi
fi
fi
done
To run these scripts on the remote machines we might also use daemonize, or we can use crontab that will execute the scripts for us at a given time or period of time.
First remove the while loop set in the scripts. In Linux and macOS, give rights to the script:
chmod u+x /path/to/remote_to_android.sh
Schedule the script using cron, type in the terminal:
crontab -e
Then type i to edit the file:
10 * * * * /path/to/remote_to_android.sh
Each * corresponds to:
minute(s) hour(s) day(s) month(s) weekday(s)
By writing 10 * * * * the script will run at the tenth minute of every hour.
By writing */10 * * * * the script will run every ten minutes of an hour.
If you want to get logs from the echo we make in the script. Logs will be found in /tmp/, stdout.log to get echo commands and stderr.log for errors:
10 * * * * /path/to/remote_to_android.sh >/tmp/stdout.log 2>/tmp/stderr.log
#rajbhx