In this bog post I will tell you how I transformed my Redmi K20 pro into a server that hosts Nextcloud.

We are gonna need:

  • termux
  • tailscale/headscale or a public domain if you want to access it from anywhere Since I already bought my domain (the URL of this blog), I will use the latter.

Running Nextcloud

Setting up termux

Note: termux must be installed from f-droid and not from the playstore since PlayStore version hasn’t been updated in years.

Nextcloud setup was inspired by this reddit post and I added what I discovered while setting this up myself.

Note: If you have a computer I suggest you to run sshd as first command so you can ssh into the phone from your computer.

First of all we want all the commands to be read in aarch64 architecture by typing setarch aarch64 From what I understood the K20 Pro is already aarch64 since uname -m already returns “aarch64”, so we can skip this step.

Installing Dependencies

Termux is cool but but its repos might not contain all the necessary packages needed to run Nextcloud, so we’ll use a “proot-distro” to get get ourselves into an environment where all package dependencies are available. I choosed ubuntu since my experience tells me it’s the one where most things work out of the box but you can try using alpine which is lighter. To set up the proot-distro:

pkg install proot-distro
proot-distro install ubuntu
proot-distro login ubuntu-20.04

Once inside the environment we update the packages:

apt-get update && apt-get upgrade

Now we can proceed to install the dependencies:

Nextcloud is a php based web server application. I choose to use mariaDB since it’s faster and more scalable than MySQL

add-apt-repository ppa:ondrej/php
apt update
apt install php8.2 mariadb apache2 unzip wget

You’ll get a bunch of warnings like debconf: falling back to frontend: Readline telling us that a dialog-based graphical interface isn’t installed, so it’s falling back to a basic terminal interface (readline). That’s fine.

Setting Dependencies

We then need to create the apache configuration:

nano /etc/apache2/sites-available/nextcloud.conf

Paste in it:

<VirtualHost *:80>
    ServerAdmin admin@localhost
    DocumentRoot /var/www/nextcloud
    ServerName localhost

    <Directory /var/www/nextcloud/>
        Options +FollowSymlinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/nextcloud_error.log
    CustomLog ${APACHE_LOG_DIR}/nextcloud_access.log combined
</VirtualHost>

In /var/www we have to enable the nextcloud website

a2ensite nextcloud.conf
a2enmod rewrite headers env dir mime
service apache2 reload

To setup the database we first login without password, so we can set one for next runs.

mysqld_safe --skip-grant-tables --skip-networking &

We enter the mariaDB shell doing:

mysql

As said we want to setup password authentication to enter the database shell

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost'
  IDENTIFIED VIA mysql_native_password
  USING PASSWORD('DBpassword');
FLUSH PRIVILEGES;
exit

Once done, we can kill mariaDB

mysqladmin shutdown

Now we can access the DB shell using the password we created using mysql -p. It will prompt for a password and we enter the password we set before. Once inside the shell we will create nextcloud user

CREATE DATABASE nextcloud;
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'adminpassword';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'admin'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Installing Nextcloud

Nextcloud provides a zip file that contains an installer. To download it we use wget:

wget https://download.nextcloud.com/server/releases/latest.zip`

we will extract everything in nextcloud default folder:

cd /var/www
unzip ~/latest.zip -d .

And we set the correct permissions:

chown -R www-data:www-data /var/www/nextcloud
chmod -R 755 /var/www/nextcloud

Now you should be able to connect to http://localhost:8080 and continue the installation there setting the credentianls for the admin user we created before in the database.

Nextcloud on server boot

This section provides a quick guide to start nextcloud server on boot. We’ll use termux-services (runit) so each service will stay in the foreground so runit can supervise it and start it again if something goes wrong and the service stops.

pkg install termux-services
mkdir ~/.termux/sv

sshd service

mkdir ~/.termux/sv/sshd
nano ~/.termux/sv/sshd/run

paste in it

#!/data/data/com.termux/files/usr/bin/sh
exec sshd -D -p 2222

create a symlink for sv

ln -snf "$HOME/.termux/sv/sshd" "$PREFIX/var/service/sshd"

Enable the service

sv enable sshd

nextcloud service

mkdir ~/.termux/sv/nextcloud
nano ~/.termux/sv/nextcloud/run

paste in it

#!/data/data/com.termux/files/usr/bin/sh
set -eu

# Give Android time to mount storage / connect Wi-Fi (helps first boot after reboot)
sleep 25

PD="/data/data/com.termux/files/usr/bin/proot-distro"

exec "$PD" login ubuntu -- /bin/bash -lc '
  set -e

  # Start MariaDB/MySQL if not already running
  if ! pgrep -x mysqld >/dev/null 2>&1; then
    (service mariadb start || service mysql start) || true
  fi

  # Start PHP-FPM (adjust versions to what you installed)
  (service php8.3-fpm start || service php8.2-fpm start || true)

  # Start Apache if not already running
  if ! pgrep -x apache2 >/dev/null 2>&1; then
    apache2ctl start
  fi

  # Keep the proot session alive so daemons survive
  exec tail -F /var/log/apache2/error.log
'

create a symlink for sv

ln -snf "$HOME/.termux/sv/nextcloud" "$PREFIX/var/service/nextcloud"

Enable the service

sv enable nextcloud

Notes

I strongly suggest you to create another user from nexcloud gui when logged in as admin and use that account for all the rest while keeping the admin account clean

Remove some warnings and speeding up performances

Warnings and errors appear

Memcache

run apt install php8.2-apcu and add 'memcache.local' => '\OC\Memcache\APCu', in nextcloud config.php

Log level

'loglevel' => 3 in nextcloud config.php

Ajax -> cronie

According to this reddit post, changing the nextcloud job scheduler from ajax to cron drastically increases performances. This makes sense because ajax runs once when there is a click while cron we can schedule the cron jobs every x minutes, decreasing load when a page has to be loaded.

Since we are in a proot-distro cron jobs cannot be started from inside we have to start them from termux shell. We install cronie and make it start using sv.

pkg install cronie

We create a script

#!/data/data/com.termux/files/usr/bin/bash
proot-distro login ubuntu --user root --shared-tmp -- bash -c "su -s /bin/sh www-data -c 'php -f /var/www/nextcloud/cron.php'"

And add it to cronie crontab

*/5 * * * * /data/data/com.termux/files/home/scripts/run-nextcloud-cron.sh >> ~/log/nextcloud-cron.log 2>&1

Redis for locking files

It seems overkill and it might be, but it is very easy and straightforward to setup. Redis has a bug on ARM64 that might lead to data corruption. Fortunately we are not using Redis to store data but we are only using to track lock of files. To install redis:

apt install -y redis-server php8.2-redis

Then we edit the config at /etc/redis/redis.conf uncommenting/adding:

ignore-warnings ARM64-COW-BUG
daemonize yes
supervised no
port 6379
bind 127.0.0.1
save ""
appendonly no
# maxmemory 64mb
# maxmemory-policy noeviction

in the nextcloud config.php

    'filelocking.enabled' => true,
	'memcache.locking' => '\OC\Memcache\Redis',
	'redis' => array(
     'host' => 'localhost',
     'port' => 6379,
     'timeout' => 0.0,
      ),

also, we want to start redis automatically, so from termux shell we edit .termux/sv/nextcloud/run adding:

  if ! pgrep -x redis >/dev/null 2>&1; then
    redis-server /etc/redis/redis.conf
  fi