Wednesday, April 30, 2025

development for Android / iOS - preliminaries

Seeing that the mobile devices were quite competitive with the desktop's processing power in a previous post, thought about working on porting various tools like OCVWarp to Android and iOS if feasible.

OpenCV Android - had earlier cloned / forked NDK samples.

The binaries are available here 
only up to OpenCV v3.4.3, but iOS framework seems to be available at
and

To check if swift playgrounds is available on 9th gen ipad - https://www.theverge.com/2021/6/15/22534902/ipad-pro-apple-swift-playgrounds-4-wwdc-2021

To check if example opencv apps can run on ipad.

Tuesday, April 29, 2025

info about various ARM platforms

 https://www.baeldung.com/linux/arm64-armel-armhf-overview

So, arm64 is sometimes referred to as aarch64. But the github arm64 appimage builds are not compatible with Ubuntu on raspberry pi 4 etc, maybe because of library differences, since the github runners are Ubuntu 24.04. 

Monday, April 28, 2025

simple logger created by chatgpt

I wanted to make a simple load-average logger. Thought of making ChatGPT do the typing, instead of me creating the simple code.

The result was quite OK.


The prompts and conversation are in the issues tab.

moving Virtualbox VMs to external drive

VirtualBox Manager
> Right-click on the VM
> Select "Move"
> Choose the new location and click "Move"

(Tho' the progress bar doesn't seem to work, it moved the VM and associated files to the external drive in approx the usual time it would take for a 12 GB file move.)

Sunday, April 27, 2025

OCVWarp AppImage won't run on Raspberry Pi

The OCVWarp AppImage compiled on github's ARM64 runner will not run on Raspberry Pi 4, error screenshot below.


But OCVWarp runs when compiled on the Pi itself.

( 
In hindsight, 
This might be a problem with 
(a) /tmp not allowing executable permissions
(b) the ld-linux-aarch64.so not having executable permissions
)

Google's "free to try" AI Studio

Google AI Studio has image generation, video generation and more, in addition to text chat. But even Google's Gemini does not know this:) 

Unless we enable "auto-save" in the settings (I guess) our prompts are not saved in History.

Choosing the model Gemini2.0 Flash (image generation)
"Create an image of a sunset over a sandy beach" - result is below.


Not bad.

By clicking the Video generation tab, Veo 2 generated the following videos on the respective prompts. Not very good, but it's a good start. And the best part is that it's free. And it took less than a minute to generate.

"Create a video of overcast clouds over sunset on a sandy beach" - resulted in a timelapse-style video below:


"Generate a 360 degree equirectangular video of sunset over a beach" resulted in:

Since this was not really an equirectangular 360 degree video, tried by running the same prompt again. Then it gave:

 Refining my prompt, changed it to "Generate a VR360 equirectangular video of sunset over a beach" which resulted in this:

I didn't want any human beings or birds in the video, so I tried adding a negative prompt of birds, men, women - and the same prompt as above. But the result still had this woman,

All right. Maybe it will do better when given an image to work with. So, I uploaded the sunset image earlier generated with Gemini 2.0 Flash, and gave the prompt "Generate a VR360 equirectangular video from this image by panning left to right."
But it did not pan, instead added birds!

In summary, a long way to go. But since it's fast and free (the video generation did not specify any queries per day limits, but the Gemini models did specify 1500 requests per day and so on in the free tier), we can definitely try out some stuff. And perhaps upscale locally or with google colab. 







Geekbench scores - Android phone, iPad, laptop, desktop, Raspberry Pi

Thought of doing some benchmarks to rate the performance of the various devices to which I have access. Samsung Galaxy M34 Android phone, Raspberry Pi 4 8 GB without cooling fan, i5-4430 processor desktop with GTX 1050 graphics card, i5-1235U processor laptop with Intel graphics, 9th gen iPad.

https://www.geekbench.com/download/

Higher scores are better.

Example benchmarks also linked in the page above.

CPU single-core / multi-core - the Android phone was surprisingly close to the desktop. The iPad crashed this test, so I've not added it in the lineup below. The pi overheated without the cooling fan, hence it gave a worse multi-core performance than could be possible with better cooling.

Pi4 (292/519) < M34 (960/2072) < Desktop (1062/2813) < Laptop (2131/7460)

GPU OpenCL / Vulkan - the Pi4 gave an error, unknown CL platform, so it is not listed below. But the Pi5 seems to have a rating of only 96! And the iPad perhaps outperformed the Laptop.

M34 (2306/2339) < Laptop (11723/15237) < iPad (13914 (Metal)) < Desktop (22555/NA)

Conclusion - The Raspberry Pi 4 did much worse than I expected, and the mobile devices - the phone and the iPad - did better than I expected. 


Saturday, April 26, 2025

Ubuntu using userland on Android

Trying out UserLAnd - https://userland.tech/features

Rs. 190 to buy pro version.

Downloaded 80 MB, on 5G took less than 2 minutes.

Setting up file system - another 2 minutes, then came up without any browser or remote desktop.

Find ip address from Android settings > Wifi > Connection > scroll down to Details.

Port is 5951, Via

xtightvncviewer

VNC pw is found via Filesystem > long press on "apps" > Edit 

sudo apt update
Reading package lists... Error!
W: Unable to read /etc/apt/sources.list - RealFileExists (38: Function not implemented)

sudo apt-get update
works
sudo apt-get upgrade
says 204 packages to be upgraded.

Connection failed, since vnc was being upgraded.

ssh with username=userland did not work over the network on port 22, but worked OK on localhost.

Problems when trying to install a browser - 

Preparing to unpack .../firefox_1%3a1snap1-0ubuntu2_arm64.deb ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 78.)
debconf: falling back to frontend: Readline
=> Installing the firefox snap
==> Checking connectivity with the snap store
===> System doesn't have a working snapd, skipping
Unpacking firefox (1:1snap1-0ubuntu2) ...
Setting up firefox (1:1snap1-0ubuntu2) ...
update-alternatives: using /usr/bin/firefox to provide /usr/bin/gnome-www-browser (gnome-www-browser) in auto mode
update-alternatives: using /usr/bin/firefox to provide /usr/bin/x-www-browser (x-www-browser) in auto mode

Command '/usr/bin/firefox' requires the firefox snap to be installed.
Please install it with:

snap install firefox

 sudo apt-get install snapd
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
snapd is already the newest version (2.67.1+22.04).

 sudo snap install firefox 
error: cannot communicate with server: Post "http://localhost/v2/snaps/firefox": dial unix /run/snapd.socket: connect: no such file or directory

snap install firefox
error: cannot communicate with server: Post "http://localhost/v2/snaps/firefox": dial unix /run/snapd.socket: connect: no such file or directory

via
 wget http://http.us.debian.org/debian/pool/main/f/firefox/firefox_137.0.2-1_arm64.deb

sudo dpkg -i firefox*.deb
Selecting previously unselected package firefox.
(Reading database ... 59497 files and directories currently installed.)
Preparing to unpack firefox_137.0.2-1_arm64.deb ...
Unpacking firefox (137.0.2-1) ...
dpkg: dependency problems prevent configuration of firefox:
 firefox depends on libasound2t64 (>= 1.0.16); however:
  Package libasound2t64 is not installed.
 firefox depends on libatk1.0-0t64 (>= 1.12.4); however:
  Package libatk1.0-0t64 is not installed.
 firefox depends on libc6 (>= 2.39); however:
  Version of libc6:arm64 on system is 2.35-0ubuntu3.9.
 firefox depends on libevent-2.1-7t64 (>= 2.1.8-stable); however:
  Package libevent-2.1-7t64 is not installed.
 firefox depends on libglib2.0-0t64 (>= 2.38.0); however:
  Package libglib2.0-0t64 is not installed.
 firefox depends on libgtk-3-0t64 (>= 3.13.7); however:
  Package libgtk-3-0t64 is not installed.
 firefox depends on libnss3 (>= 2:3.109~); however:
  Version of libnss3:arm64 on system is 2:3.98-0ubuntu0.22.04.2.
 firefox depends on libvpx9 (>= 1.12.0); however:
  Package libvpx9 is not installed.
 firefox depends on libxcomposite1 (>= 1:0.4.6); however:
  Version of libxcomposite1:arm64 on system is 1:0.4.5-1build2.

dpkg: error processing package firefox (--install):
 dependency problems - leaving unconfigured
Processing triggers for desktop-file-utils (0.26-1ubuntu3) ...
Processing triggers for hicolor-icon-theme (0.17-2) ...
Processing triggers for man-db (2.10.2-1) ...
Errors were encountered while processing:
 firefox

via

userland@localhost:~$ sudo dpkg -i firefox*.deb
dpkg: warning: downgrading firefox from 137.0.2-1 to 136.0+build3-0ubuntu0.20.04.1
(Reading database ... 59587 files and directories currently installed.)
Preparing to unpack firefox_136.0+build3-0ubuntu0.20.04.1_arm64.deb ...
Unpacking firefox (136.0+build3-0ubuntu0.20.04.1) over (137.0.2-1) ...
dpkg: warning: unable to delete old directory '/usr/share/firefox/distribution': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox/browser/defaults/preferences': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox/browser/defaults': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox/browser/chrome/icons/default': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox/browser/chrome/icons': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox/browser/chrome': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox/browser': Directory not empty
dpkg: warning: unable to delete old directory '/usr/share/firefox': Directory not empty
dpkg: dependency problems prevent configuration of firefox:
 firefox depends on libgdk-pixbuf2.0-0 (>= 2.22.0); however:
  Package libgdk-pixbuf2.0-0 is not installed.

dpkg: error processing package firefox (--install):
 dependency problems - leaving unconfigured
Processing triggers for desktop-file-utils (0.26-1ubuntu3) ...
Processing triggers for hicolor-icon-theme (0.17-2) ...
Processing triggers for man-db (2.10.2-1) ...
Errors were encountered while processing:
 firefox

sudo apt-get install  libgdk-pixbuf2.0-0
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
You might want to run 'apt --fix-broken install' to correct these.
The following packages have unmet dependencies:
 libgdk-pixbuf2.0-0 : Depends: libgdk-pixbuf-xlib-2.0-0 (>= 2.40.2-2build4) but it is not going to be installed
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).
userland@localhost:~$ sudo apt-get install  libgdk-pixbuf     
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package libgdk-pixbuf
userland@localhost:~$ sudo apt --fix-broken install
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Correcting dependencies... Done
The following additional packages will be installed:
  firefox
The following packages will be upgraded:
  firefox
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
1 not fully installed or removed.
Need to get 72.3 kB of archives.
After this operation, 248 MB disk space will be freed.
Do you want to continue? [Y/n] 
Get:1 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 firefox arm64 1:1snap1-0ubuntu2 [72.3 kB]

(which again fails due to snap being broken.)

via


firefox
[Parent 32675, Main Thread] WARNING: read-only dup failed (Permission denied); not using memfd: file /builds/worker/checkouts/gecko/ipc/glue/SharedMemory_posix.cpp:218
[GFX1-]: glxtest: ManageChildProcess failed

[GFX1-]: No GPUs detected via PCI

[32675] Sandbox: Couldn't open video device /dev/video215
[32675] Sandbox: Couldn't open video device /dev/video102
[32675] Sandbox: Couldn't open video device /dev/video9
[32675] Sandbox: Couldn't open video device /dev/video8
[32675] Sandbox: Couldn't open video device /dev/video155
[32675] Sandbox: Couldn't open video device /dev/video11
[32675] Sandbox: Couldn't open video device /dev/video216
[32675] Sandbox: Couldn't open video device /dev/video6
[32675] Sandbox: Couldn't open video device /dev/video214

etc

[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0
[GFX1]: no fonts - init: 1 fonts: 14 loader: 0


etc

firefox opens, but all tabs crash.

Gah - your tab just crashed.

(Then it crashes the userland ubuntu also.)

sudo apt-get epiphany-browser
(package name via software manager on desktop)

Trying to run OCVWarp ARM64AppImage on the userland ubuntu,

did install fuse with
sudo apt-get install libuse2

but

fuse: failed to open /dev/fuse: Permission denied

Cannot mount AppImage, please check your FUSE setup.


 sudo modprobe -v fuse
bash: line 1: modprobe: command not found

 squashfs-root/AppRun
GST_PLUGIN_SCANNER=
GST_PLUGIN_SYSTEM_PATH=/home/userland/Downloads/OCVWarp-4.01/build/squashfs-root/lib/aarch64-linux-gnu/gstreamer-1.0
GST_PLUGIN_PATH=/home/userland/Downloads/OCVWarp-4.01/build/squashfs-root/lib/aarch64-linux-gnu/gstreamer-1.0
squashfs-root/AppRun: 101: exec: /home/userland/Downloads/OCVWarp-4.01/build/squashfs-root/usr/lib/ld-linux-aarch64.so.1: Permission denied


sudo  squashfs-root/AppRun
GST_PLUGIN_SCANNER=
GST_PLUGIN_SYSTEM_PATH=/home/userland/Downloads/OCVWarp-4.01/build/squashfs-root/lib/aarch64-linux-gnu/gstreamer-1.0
GST_PLUGIN_PATH=/home/userland/Downloads/OCVWarp-4.01/build/squashfs-root/lib/aarch64-linux-gnu/gstreamer-1.0
squashfs-root/AppRun: 101: exec: /home/userland/Downloads/OCVWarp-4.01/build/squashfs-root/usr/lib/ld-linux-aarch64.so.1: Permission denied

sudo apt-get install epiphany-browser 

running the above from vnc would crash.

run from ssh on local shell, installed 100+ MB of dependencies.

epiphany-browser  

** (epiphany:2707): WARNING **: 04:54:34.367: Disabled hardware acceleration because GTK failed to initialize GL: No GL implementation is available.

** (epiphany:2707): WARNING **: 04:54:34.400: WebKitWebContext:use-system-appearance-for-scrollbars property is deprecated and does nothing

** (epiphany:2707): WARNING **: 04:54:34.526: WebKitWebContext:use-system-appearance-for-scrollbars property is deprecated and does nothing

** (epiphany:2707): WARNING **: 04:54:35.209: webkit_settings_set_enable_dns_prefetching is deprecated and does nothing.
bwrap: Can't read /proc/sys/kernel/overflowuid: Permission denied

** (epiphany:2707): ERROR **: 04:54:35.657: Failed to fully launch dbus-proxy: Child process exited with code 1
Trace/breakpoint trap

And using qemu, once again, likely to be too slow - 

(on ipad, ubuntu was taking 30 minutes+ to boot up.)

So, I could try the ARM64 OCVWarp on raspberry pi instead. (which won't work out of the box, may need to compile on the Pi, since Raspberry Pi may use a different architecture compared to the github ARM64 runner - https://linuxvox.com/blog/what-is-difference-between-arm64-and-armhf/ .)

Wednesday, April 23, 2025

airtel's horrendous "AI" customer service

I was trying to recharge another prepaid Airtel number with "international roaming plan 2997" for 365 day validity.

Tried with Airtel thanks app from my Airtel mobile - failed.

Tried from website - failed.

Tried calling customer care - they said try going to a shop.

Tried from shop - failed.

Tried sending them an email to 121@in.airtel.com - "We noticed that you're contacting us from an email ID that isn't linked to your Airtel account. 

You shall write back to us from your registered ID or reach out to airtel thanksapp get instant support 24x7 right from the help and support section."

The help and support section is a chatbot. There didn't seem to be any option to contact a human being. 

Finally, I thought maybe trying from the Airtel app on the actual prepaid account for which Intl. Roaming was needed - success. Edit - half an hour later, that transaction was reversed, too!  

Airtel's own customer service people did not know this, the shop guys (tried two different shops) did not know this, it is not mentioned anywhere that these intl. roaming plans need to be bought from the phone which is actually going to roam! 

UTM for OpenSpace on iOS / MacOS

Found on https://getutm.app/faq/#what-are-the-limitations
"The lack of hardware virtualization on Apple A-chips means that even for ARM code we must re-compile it with JIT. Therefore performance would never reach the levels possible with KVM. There is also no support for GPU virtualization so that means no DirectX or OpenGL. This makes most modern games non-playable." So, OpenSpace is most probably not suitable to run via UTM on iPad / iOS.


"UTM does not currently support GPU emulation/virtualization on Windows and therefore lacks support for 3D acceleration (e.g. OpenGL and DirectX). You may be able to run older games with software rendering options, but nothing with hardware acceleration. There is experimental support for hardware OpenGL acceleration on Linux through Virgl."
So, OpenSpace on Ubuntu might be doable - at least with performance similar to a Windows box without NVidia graphics - on a Mac with UTM.

---------------------------
Details of what didn't work

Found the limitations the hard way, trying for many hours on the (9th gen) iPad (since I don't have access to a Mac at the moment). 
UTM SE - with no JIT - took half an hour or more to boot Ubuntu 14.04 (that's not a typo, it really was the old version 14.04)

Trying to enable JIT - 

Directly on AltStore - need a Hackintosh or Mac for it? - https://github.com/altstoreio/AltStore/issues/1349

says use stikJIT - https://stikdebug.xyz/


Apparently enabling JIT is a one-time installation - https://faq.altstore.io/altstore-classic/enabling-jit

We can't use Altstore PAL since we're not in the EU - tried and failed.

To install a downloaded ipa, go to Altstore > My apps (at the bottom), and click the + on the top. The ipa should be visible. 

(if ipa is not visible, we may need to navigate using the files app, and "open with" Altstore.
Then, it asks for apple creds.)

Transferred the pairing file using icloud drive.

Long press on UTM, then "enable jit", then try to open the vm, then
error trying to connect to spice server.

If StosVPN is turned off, then AltJIT not found, can't run VMs without JIT.

FAILED TO CONNECT TO SPICE

To force quit, 
swipe up and hold to open app switcher, then swipe up on the app to force-quit it.

Jitstreamer EB on Debian guide is here,

To try - minimal Ubuntu or something like that without 3d acceleration, which may not need spice.

debian 11 ARM64 lxde with spicetools installed, from gallery.

It was a zip file. Open in Downloads > unzipped. Long press and open in UTM.

But same error, QEMU exited no error message.

UTM also says Virtualization is not supported on your device.
So we can only use Emulate.

Still, same error. Then, I tried UTM SE, which took half an hour to boot the old version of Ubuntu as noted at the top of this post.


Tuesday, April 22, 2025

cloudflare plugin for certbot

Found this option, 

--dns-cloudflare      Obtain certificates using a DNS TXT record (if you are using Cloudflare for DNS). (default: False)

from

https://eff-certbot.readthedocs.io/en/stable/man/certbot.html

And documentation for this plugin is at

https://certbot-dns-cloudflare.readthedocs.io/en/stable/index.html

(example invocation at end)

and how to install plugin is 

sudo apt-get -y install python3-certbot-dns-cloudflare

https://installati.one/install-python3-certbot-dns-cloudflare-ubuntu-20-04/

Monday, April 21, 2025

automating backup with python - rclone and google drive

There was a python script written to
1. Compress the audio files that are created from the previous backup date to now into a folder and zip it 
2. Export the zip file to Gdrive.
2. Extract the mysql backup into a .sql file, export that also into the gdrive folder.
3. delete the past backups. 

For this, rclone and zip needed to be installed. After that, I passed on abbreviated instructions for setting up an rclone remote for GDrive - 

You will need to use the method "(N) running rclone on a machine without web browser" from the instructions onscreen, which are also shown at

As mentioned here, 
you need to download the latest rclone and install on your local system (where you have access to a web browser, where you can log on to google and give permission for rclone etc when prompted), and follow the onscreen instructions to set up rclone config for your desired google drive login.

After they set up the script, remote etc and found them working, set up a daily cron for 12:15 midnight,
15 0 * * Sun /usr/bin/python3 /home/path-to/backup_service.py 
which the user can edit from their login using
crontab -e

Sunday, April 20, 2025

migrating web servers and associated scripts using rclone copy

As mentioned in the previous post, our server migration involved consolidating a web server into a DB server - we chose this method, since cloning the DB server was quick, while export followed by import of MySQL databases takes quite a bit longer as noted in the earlier 2024 migration post.

Copied the ssh private key for the destination server to the source server, and created an rclone remote using SFTP to the destination server. 

zip -r -q webserver1.zip /path/to/webserver/files

(repeated this for all the web server directories later)

rclone copy webserver1.zip rcloneremote:/home/azureuser

(repeated this for all the other zip files later)

From the destination server,

unzip webserver1.zip

cd path/to/webserver/

sudo mv files /path/to/webserver

cd /path/to/webserver

sudo chown -R azureuser:www-data .

sudo chmod -R 775 .

----------------------------------------------

Then, the apache config files - 

sudo zip -r -q etcapache.zip /etc/apache2

(rclone copy etc, and change ownership to root)

and the letsencrypt certificates etc,

sudo zip -r -q etclets.zip /etc/letsencrypt

(rclone copy etc, and change ownership to www-data for the file/directory which it needs, and the others to root)

-----------------------------------------------

With these, the files to be copied for the web servers were done. And I could start them up - 
sudo a2ensite webserver1
sudo systemctl reload apache2
etc.

Also needed were

  • installing all the necessary apache and php modules - which I had done earlier using the steps at the 2024 migration post.
  • installing restic for backups as per the backups section of that post.
  • rclone copy, individually, for the .sh backup scripts and the notifier directory.
  • Copy-pasting lines from .config/rclone/rclone.config  as noted in the restic backup script - the rclone config was modified by copy pasting the extra remotes from source to destination.
  • Copy-pasting cron jobs from both crontab -e and sudo crontab -e
  • Setting up postfix with gmail smtp as mentioned at this post for which 
    sudo apt remove ssmtp
    sudo apt install mailutils postfix

    and then editing the conf files was required.
-----------------------------------------------

Then, we had awstats running, so 
sudo zip -r -q etcawstats.zip /etc/awstats
for the config files, and
sudo apt install awstats
with editing out the cron which is auto installed at
sudo nano /etc/cron.d/awstats

and then copying across the awstats data - the DataDir was set to this directory -  
sudo zip -r -q varlibawstats.zip /var/lib/awstats
(then rclone copy, then unzip on the destination machine, move and set appropriate permissions etc) 

----------------------------------------------------

Tested the backup and load alert notification scripts, checked awstats the next day to verify that the stats were updating correctly.

------------------------------------------------------
Edit: one week later - some more configurations which were missed out.

sudo apt install certbot python3-certbot-apache
sudo certbot --apache

This was sufficient to enable auto-updates for the letsencrypt SSL certificates which had been copied over from the old server.

On another server, onto which we had migrated a single domain, but which already had other active letsencrypt SSL encrypted websites,

sudo certbot --cert-name subdomain.ourdomain.org
for renewing only this one, without disturbing the others.

For removing a certificate later, we can use
certbot delete --cert-name example.com
[so you will need to know the exact cert-name - not the specific FQDN(or domain name) within the cert]
[you can get the cert names with: certbot certificates]


-----------------------------------------------------------

One of the Moodle instances gave an error, Adhoc task failed: assignfeedback_editpdf\task\convert_submission,The configured path to ghostscript is not correctly set: The ghostscript path points to a non-existent file

Solution was to install ghostscript,
sudo apt install ghostscript

--------------------------------------------------------

Then the php max_file_upload also had to be modified according to this earlier post, https://hnsws.blogspot.com/2021/03/some-post-install-changes-needed-for.html

sudo nano /etc/php/8.3/apache2/php.ini

( Ctrl+w to find and change post_max_size

Ctrl+w to find and change upload_max_filesize

Ctrl+w to find and change max_execution_time  - set to 600 for now.)

sudo systemctl restart apache2

and also did the same for /etc/php/8.3/cli/php.ini

-----------------------------------------------------------

When upgrading a plugin, a warning was shown that php extension soap was not installed, and that update will continue only after it is installed. So,

sudo apt install php-soap

-------------------------------------------------------------

Edit - a few days later - 

https://linuxize.com/post/how-to-change-hostname-on-ubuntu-22-04/

sudo hostnamectl

sudo hostnamectl set-hostname our-desired-hostname

-------------------------------------------------------------

Then, a warning while updating a plugin - max_input_vars must be at least 5000

sudo nano /etc/php/8.3/apache2/php.ini

sudo nano /etc/php/8.3/cli/php.ini

sudo systemctl restart  apache2

-------------------------------------------------------------

migrating Azure VM from one tenant to another

Azure documentation talks about migrating a VM from one region to another region - https://learn.microsoft.com/en-us/azure/resource-mover/tutorial-move-region-virtual-machines


but with some changes - instead of a file share, creating a disk from snapshot seems to need a blob container for the "Create Managed Disk" applet nowadays. Following the exact steps as above results in not finding any container in that storage account.

Shifted using the following steps:

1. Enabled CLI maintenance mode on the Moodle instances with 
sudo -u www-data /usr/bin/php admin/cli/maintenance.php --enable
- verified that this does stop the cron also, which would otherwise hit the database every minute.

2. Shut down the database VM, went to its OS disk, created snapshot, went to the snapshot's page, "Export snapshot", copied the export snapshot url. 

3. I had earlier created a test VM in the destination tenant, in the Central India region which is the cheapest at present. Had also created a storage account, and a blob container. Also, had installed azcopy on that VM with the following - https://www.thomasmaurer.ch/2019/05/how-to-install-azcopy-for-azure-storage/
#Download AzCopy
wget https://aka.ms/downloadazcopy-v10-linux
 
#Expand Archive
tar -xvf downloadazcopy-v10-linux
 
#(Optional) Remove existing AzCopy version
sudo rm /usr/bin/azcopy
 
#Move AzCopy to the destination you want to store it
sudo cp ./azcopy_linux_amd64_*/azcopy /usr/bin/


4. Created SAS token (Shared Access Signature) from Azure portal > thestorageaccount - the default 3600 seconds may be too short if we need to do multiple operations. Enabled container, blob and file, all three, and copied the blob url and sas token strings. The blob url would be of the form https://storageaccountname.blob.core.windows.net/?sv=SAS-token - we need to edit this, and add nameofourcontainer/desired-name-of-file.vhd before the ?sv=SAS-token

5. SSH'd into that VM, and ran azcopy. (I could have avoided creating the VM, installing azcopy etc by using an Azure shell instead.) The command will be of the form:
azcopy copy "https://md-abcefg12nmg.z12.blob.storage.azure.net/snapshot/abcd?sv=2018-03-28&sr=b&si=this-is-the-snapshot-url-1234566b61d3&sig=zj9jh0ABCDEDFGHHJtnkD9yK0rvJ44I%3D" "https://lmsmigratestorage.blob.core.windows.net/testcontainer/LMSDBsnapshot.vhd?sv=2024-11-04&ss=bfqt&srt=sco&sp=abcdefghytfx&se=2025-04-21T11:49:12Z&st=2025-04-20T03:49:12Z&spr=https&sig=qwertyuiopasdfghjkABCDEFGuLYlgBQlWZE%3D"

# Actually ran steps 2 and 5 three times, azcopy took the following times:
# Elapsed Time (Minutes): 2.034 <-- LMS db OS disk
# Elapsed Time (Minutes): 1.2004 <-- LMS php disk
# Elapsed Time (Minutes): 22.0734 <-- LMS data disk
 
6. From Azure portal, in the destination tenant, Home > Create > Managed Disks > (Choosing Source as Blob storage) > Browse > choosing our VHD snapshot file in blob storage. Creating disk from snapshot, creating snapshot etc are very fast operations, these operations complete in less than a minute.  

7. From the created disk, if it is an OS disk, Create VM. Note that in our case, the default "Operating System type" was v1, but our original VM was v2, so I created the new VM also as v2. 

8. The data disk can be attached later to the VM, even when it is running - "Attach existing disk". Caution - attaching an OS disk as data disk does not seem to work properly - that new OS disk becomes the primary OS disk! 

9. In our case, we were cloning the db VM and copying the php files (and postgresql db) from the php server into the db VM, since we wanted to consolidate the two VMs into a single one. So, I had to copy over from the old VM to the new VM using rclone copy. What I needed to copy, and the steps taken, will be a separate post.

(What does not work:
1. "Export disk" and trying to use that using azure cli - this will not work. We need to create a snapshot first, then export the snapshot, and use the snapshot to re-create the disk in the new tenant.
2. Mounting azure blob storage on a VM and using wget to copy the snapshot VHD to blob storage will not help us to create the disk in the new tenant - azcopy is mandatory.
3. wget -O mydisksnapshot.vhd "https://snapshot-export-URL" followed by
azcopy copy mydisksnapshot.vhd "https://blob-storage-url" will work, but takes double the time - azcopy works fine directly from snapshot url to blob storage url. Caveat is that we must make a container first, and then use azcopy copy.) 

Saturday, April 19, 2025

clearing up after docker

 Via https://stackoverflow.com/questions/76833923/safe-way-to-clean-var-lib-docker

/var/lib/docker was using up 16 GB. 

sudo docker system prune --all --volumes

WARNING! This will remove:

  - all stopped containers
  - all networks not used by at least one container
  - all anonymous volumes not used by at least one container
  - all images without at least one container associated to them
  - all build cache

Total reclaimed space: 7.794GB


installed an alarm applet

 On Linux Mint running Xfce, via https://forums.linuxmint.com/viewtopic.php?f=47&t=191832

Installed via Software Manager.

KAlarm needed to download 400 MB! So, instead chose Alarm-clock-applet which was only 563 kB. Shows up in the Applications menu as Alarm Clock. Can set time or timer.

Thursday, April 17, 2025

postgres restore from backup - 2 minutes

A quick note on time taken - 


rclone config

then rclone copy

rclone copy *.sql remotename2024:/home/theuser

psql -h 127.0.0.1 -U username -d databasename < dbdump-noowner.sql -W ThePassWord

This took just two minutes.

decided not to migrate Moodle from MySQL to Postgres

Though Moodle is believed to have better performance on PostgreSQL than on MySQL, 

There is a migrate tool

But could have issues,
Some troubles you may find when using this tool:

If there is any object in the current database (columns, tables,...) not included in the XMLDB schema or the other way around the dbtransfer won't be executed until these objects are removed (this may happen if Moodle has been upgraded from earlier versions, if some plugin hasn't been correctly uninstalled...).

Also, "Depending on the size of your database, the process may take several hours."

So, decided not to migrate to Postgres at the moment.

Edit - update in Aug 2026 - ChatGPT says, (private URL for my reference - https://chatgpt.com/c/6a9267b3-5d78-83ee-9bed-f3db27750248 ) "My current assessment is that a PostgreSQL migration before the Moodle 5.3 upgrade is unlikely to deliver enough performance improvement to justify the migration effort and testing risk. I'd spend the effort on caching, PHP tuning, and perhaps a RAM upgrade first."

ChangeExpected impact
MySQL → PostgreSQL0–10%
MySQL tuning5–20%
Redis/MUC tuning10–50%
Faster CPUOften noticeable
More RAM (8 → 16 GB)Often more useful than DB migration

Tuesday, April 15, 2025

moving a MySQL database from one host to another

We had earlier moved a Moodle install from one server to another, and now wanted to move its database also to localhost.

Using this to set up mysql, creating database + user, and later testing a connection - 

sudo mysql -p worked for logging in as root user.

create database our_master_db;

CREATE USER 'our_db_admin'@'%' IDENTIFIED BY 'OurPassword';
GRANT ALL ON our_master_db.* TO 'our_db_admin'@'%';

to export and restore dbs.

date; mysql -h 127.0.0.1 -u our_db_admin -p our_master_db < our_master_db.OldServerdb-2024.15-04-2025.sql; date

This showed that it completed in some 20 minutes. After that, needed to change the connection settings and port in Moodle's config.php

resize OS disk for Azure VM

Wanted to resize one of our Azure VM OS disks. ChatGPT gave instructions including a manual rescan and expanding of filesystem - 

Rescan Disk: echo 1 | sudo tee /sys/class/block/sda/device/rescan

Expand Filesystem: sudo resize2fs /dev/sda1

But actually, just needed to stop the vm in azure portal, resize in azure portal, then start in azure portal - since it is the OS disk and we're rebooting, the changes are automatically noted.

Microsoft's documentation for Windows VM also notes this, lower down in this page.