Screenshot of Termux running the script in this tutorial People sometimes store sensitive information within Termux, like SSH Keys or PGP Keys. Within Android, this is fairly secure. No other app can access the Termux storage without explicit user consent. But our phones aren't secure devices for most people. Most people have a really short pin or password (or even none at all). So if our devices get stolen or seized, this data can easily be extracted. This short tutorial will show you a way to encrypt the whole Termux filesystem, so this data cannot be extracted once the phone has turned off or the filesystem is unmounted and closed again.

Procedure

We're creating a separate filesystem in an encrypted image file, which we're then mounting at /data/data/com.termux/files, which contains all of Termux' data.

Requirements

Rooted phone

Unfortunately, this only works with a rooted device, as you need access to cryptsetup and mount

Blank Termux

It is recommended to start out with a freshly installed Termux. This is the host Termux, that will only be used to mount the encrypted Termux. You can do it on an existing Termux installation, but be aware that all data that is already in your Termux installation, will not be encrypted. If you want encrypt an existing installation you need to make a backup of it now and then reset your Termux.

rsync -a /data/data/com.termux/files /data/data/com.termux/files-backup

Make sure to delete this backup at the end.

After that you can delete /data/data/com.termux/files to reset your Termux (restart after doing so). Beware that this will delete all your files. Make sure you've backed them up.

Packages

Install the root repo:

pkg install root-repo

Install required packages:

pkg install util-linux cryptsetup tsu e2fsprogs rsync

Create filesystem

Step 1: Create a blank image file

To create an encrypted filesystem you need to first create a blank '.img' file. Adjust the size to your preference. Beware that it will use up this space on your device instantly.

fallocate -l 16G /data/data/com.termux/termux-fs.img

Step 2: Encrypt image file using LUKS

Next we are encrypting this '.img' using LUKS.

sudo cryptsetup luksFormat /data/data/com.termux/termux-fs.img

Answer the first prompt with YES and then enter a passphrase twice:


WARNING!
========
This will overwrite data on /data/data/com.termux/termux-fs.img irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /data/data/com.termux/termux-fs.img:
Verify passphrase:

Step 3: Temporarily open image file

To format the image file we need to temporarily open it.

sudo cryptsetup open /data/data/com.termux/termux-fs.img termux-fs-tmp

You will be prompted to enter your passphrase

Step 4: Format the image file

Create a ext4 filesystem inside the encrypted volume.

sudo mkfs.ext4 /dev/mapper/termux-fs-tmp

Step 5: Close the image file again

sudo cryptsetup close termux-fs-tmp

Entering the encrypted Termux

Now that we created the encrypted disk we simply need to mount it. Since we need to do this every time we boot our device, it's best we create a script for that. Use this script to enter your new filesystem:

#!/usr/bin/env bash
u=$(whoami)
export LD_PRELOAD=
/sbin/su -c "cryptsetup luksOpen /data/data/com.termux/termux-fs.img termux-fs"
/sbin/su -c "mount /dev/mapper/termux-fs /data/data/com.termux/files"
/sbin/su -c "/system/bin/chown $u.$u /data/data/com.termux/files"

You will be prompted your passphrase. This will mount your filesystem to /data/data/com.termux/files. After you've run this script, exit your Termux App and open it again. The first time you do this the Termux App will reinstall your base system inside your encrypted dist.

Congratulations you are now in your encrypted filesystem. You will need to run this script again after a restart.

Find your su binary

Since mounting a filesystem at /data/data/com.termux/files will cause all Termux command to temporarily break, we need to make sure we're not running any Termux commands in this script. Therefore you need to specify your su binary with an absolute path. In most cases this is /sbin/su, so you can use the script as is. If your su is somewhere else, check these paths and replace the command in the script accordingly:

  • /sbin/su
  • /system/sbin/su
  • /system/bin/su
  • /system/xbin/su
  • /su/bin/su
  • /magisk/.core/bin/su

Restore your existing installation

If you've created a backup of your existing installation (described here) you can restore that backup now.

rsync -a --delete /data/data/com.termux/files-backup/ /data/data/com.termux/files/

If everything worked, remember to delete this unencrypted backup.

rm /data/data/com.termux/files-backup -rf

Unmounting your filesystem

Unmounting your encrypted Termux is a bit annoying. Since it is always in-use you need to specify (-l) lazy mode.

sudo umount /data/data/com.termux/files -l

After that can restart your Termux again to be in the unencrypted filesystem again. Your encrypted filesystem is still open however, so you need to close it now.

sudo cryptsetup close termux-fs

If there are any processes still accessing your encrypted Termux, this will fail. You need to either find and close these processes, or restart your device.

Accessing your unencrypted Termux while in the encrypted environment

It is sometimes necessary to do maintenance (updates for example) on the unencrypted Termux. Unmounting your filesystem is one possibility, but is quite annoying. You can however use unshare and chroot to access your unencrypted Termux while the encrypted Termux is still running. I created this script to do that:

#!/usr/bin/env bash
OPTIND=1
UNSHARED=false
while getopts ":U" opt; do
    case "$opt" in
        U)
            UNSHARED=true
            ;;
        *) ;;

    esac
done

shift $((OPTIND - 1))
if [ ! "$UNSHARED" == "true" ]; then
    user="$(whoami)"
    vars=""
    vars+=" HOME=$HOME"
    vars+=" PATH=$PREFIX/bin"
    vars+=" PREFIX=$PREFIX"
    vars+=" TMPDIR=$TMPDIR"
    vars+=" SHELL=$PREFIX/bin/login"
    vars+=" exec $PREFIX/bin/login"
    args=""
    if [ -n "$1" ]; then
        args="-c '$@'"
    fi
    $PREFIX/bin/sudo unshare -m $0 -U "$user" "$HOME" "$vars $args"
else
    mount --bind /data/data/com.termux /data/data/com.termux
    user="$1"
    user_home="$2"
    vars="$3"
    cd $user_home
    groups=${user},inet,everybody,${user}_cache,all_$(echo $user | cut -d "_" -f 2)
    exec chroot --skip-chdir --userspec=$user:$user --groups=$groups / sh -c "$vars"
fi

Running this will drop you inside your unencrypted Termux. Since we used unshare this only applies to this process. Other sessions remain unaffected. To return to your encrypted Termux simply exit this process.

Caveats

Termux:Tasker

If you install the Termux:Tasker add-on, Tasker will not be able to execute the tasks in ~/.termux/tasker, because it checks your for these files in your unencrypted Termux. If you want to use this functionality you need to create blank executable files in your unencrypted Termux with the same name as the ones in your encrypted Termux. It will actually execute the scripts in your encrypted environment.

I think this is a really interesting bug. I wrote a detailed bug report here: https://github.com/termux/termux-tasker/issues/45

SELinux

I've run into issues using SELinux. It may be necessary to run this command after mounting:

/sbin/su -c "/system/bin/restorecon -R /data/data/com.termux/files"

If you run into continuing issues, add this to your mounting script (edit the path to su as described here)