Saturday, August 01, 2026

saga of decommissioned UPS

Dec 18, 2025 - email to the top executive officer of one of our institutions, saying that we could possibly make use of a decommissioned 10 kVA UPS

Feb 20, 2026 - email "received with thanks". It takes 20 65Ah lead acid batteries, trying to charge the batteries with 12V charger ordered on 25th Feb.

June 29, 2026 - requesting electrical people to wire up the batteries which were individually charged

July 23-26, 2026 - internal resistance testing shows 11 of the 20 batteries are bad, which makes the UPS trip when input power fails. So, decide to not use it.

July 31, 2026 - sent the good batteries to another institution. 

Tuesday, July 28, 2026

Android app policy violation triggered by old testing tracks - Blank release fix

We have multiple tracks in google play console for one of our Android apps. Currently we don't need all of them, we need only the production track. But unfortunately, google does not provide a way to delete unwanted tracks. Also, even releases in paused tracks can trigger "policy violation" of having app releases targeting older target SDK values - we need to update every year to the latest target SDK.

Asking Gemini via aistudio.google.com about this, it suggested a "Blank Release" method - create a new release, but don't upload any aab/apk file. We can do this for each of the testing tracks which we don't need. That would make the older releases "Inactive" and prevent the "policy violation" for old releases.

I've done this yesterday for one of our apps, and it seems to be working. The changes were approved after review in just an hour or less. The policy violation popup did not go away yesterday even after the changes were approved, but today I see that the policy violation popup is replaced with "Policy status - No policy issues found" in the "Monitor and improve" tab.

While we can upload the latest release to all of the tracks, and use the "Add from library" method for each track instead of uploading, the "Blank release" strategy above avoids that busy-work, hopefully permanently.

Saturday, July 25, 2026

slightly more user-friendly mass mailing script

Prompted Gemini via aistudio.google.com to make the mass-mailer using Google Apps Scripts a bit more user-friendly - displaying a checklist of actions to be performed for sending the emails, and picking up the rich-text html from a draft email instead of needing to write out the html by hand. Creating a custom menu and displaying a sidebar UI are done by these functions, using this html.

The Draft email with subject MassMailTemplate must not be deleted, it must remain available throughout the run of the script. The body of the email is taken from this Draft.

Inline images inside the draft will be sent as attachments, and it is better to avoid attachments to prevent our mails from being marked as spam. Formatted text is fine.

The Checklist in the Mass Mailer menu item is just for display, unchecking all the items can be done manually before the next send.

disk space alert and cleanup of MySQL databases with Moodle logs

We got an alert from our script that one of our servers had 95% utilization of the root disk. Asked Gemini via aistudio.google.com and carried out the following.

Find the Top 20 largest directories on the root partition:

sudo du -ahx / | sort -rh | head -20

Note: The `-x` flag ensures it only searches the root partition and doesn't scan external mounts or network drives.

Found that 29 GB was being used by MySQL databases.

Find individual files larger than 100MB:

sudo find / -xdev -type f -size +100M -exec ls -lh {} \;

Found that there were some .ibd files, with the names of Moodle table  like logstore_standard_log.ibd which were very large. Gemini suggested retaining only 180 or 365 days of logs instead of "Never delete logs" in Site administration > Plugins > Logging > Standard log.

Then, to get back space ...

First, logged on as the administrator of a particular database which we do not need, and dropped that database.
mysql -u thatusername -p
drop database unuseddbname

(sudo mysql does not work on this server, a root password is set, but I did not need the root password.)

That gave us 3-5 GB. Then, there were two options for Moodle logstore_standard_log - either just truncate the table - very quick, get back disk space instantly - or copy over the last 180 days' logs to a new table and then delete the old table.

(Other methods suggested by Gemini were very slow, mentioning only the good options below. Just deleting entries from a table would require an OPTIMIZE TABLE step afterwards, which would need enough disk space to create a full copy of the table.)

CREATE TABLE prefix_logstore_standard_log_new LIKE prefix_logstore_standard_log;

# find starting id to reduce copy time, since id is an indexed field
SELECT id FROM prefix_logstore_standard_log 
WHERE timecreated >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 180 DAY)) 
LIMIT 1;

INSERT INTO prefix_logstore_standard_log_new 
SELECT * FROM prefix_logstore_standard_log 
WHERE id >= YOUR_NUMBER_FROM_ABOVE_STEP;

The copying of log entries into the new table took 51 seconds using this method for our smallest db.

The quick and dirty way, of deleting all the logstore standard log entries (this is only the "what has the user clicked" data - grades etc are not deleted) -
TRUNCATE TABLE prefix_logstore_standard_log; 

This completes in less than a second, and makes disk space available immediately.

Thursday, July 23, 2026

Azure portal - Review Azure Copilot agent access settings before 1 August

There was an email from Microsoft, letting us know that if we don't take action, we will be opted in for enabling Azure Copilot agents. In general, my instinct is to disable every new "feature' which Microsoft introduces, because sooner or later, that will be involved in some security incident. After consulting the other admins, I disabled "Azure Copilot" on both Azure tenants I have admin access to, with the result that these agents

Observability Agent
Deployment Agent
Troubleshooting Agent
Optimization Agent
Resiliency Agent
Migration Agent

will not be available.

When we navigate to Azure Copilot Admin Center (which we can access via the search at the top of portal.azure.com after logging in) to disable Azure Copilot, there is a link to toggle the control for <User> can manage access to all Azure subscriptions and management groups in this tenant. Since they recommend turning this off, I turned it on, disabled Copilot and turned it back on. The link to this control is https://portal.azure.com/#view/Microsoft_AAD_IAM/TenantProperties.ReactView

The documentation referencing this is at

Wednesday, July 22, 2026

transition to Moodle Marketplace - mod_book unavailable

We got an email from Moodle about moving the Plugins directory to Moodle Marketplace - 

"The transition to Moodle Marketplace may require you to make some adjustments to your Moodle site set-up. See what’s changed at Plugins Directory has moved to Moodle Marketplace."

Here is the list of plugins (at the bottom of the page in this link) which will not be supported after 31 August 2026,

In case any of the plugins we regularly use are listed there, they may not work (or may not be updated) after 31 Aug.

So, VLS got back saying that he 
reviewed the complete list with the list of installed plugins. I have identified 2 plugins, viz., mod_book, atto_fontfamily. 

ChatGPT suggested running SQL to check which courses use mod_book, which I ran - 

SELECT DISTINCT  c.id, c.shortname, c.fullname,
    COUNT(cm.id) AS number_of_books
    FROM prefix_course_modules cm
    JOIN prefix_modules m ON cm.module = m.id
    JOIN prefix_course c ON cm.course = c.id
    WHERE m.name = 'book'
    GROUP BY c.id, c.shortname, c.fullname
    ORDER BY c.fullname; 

On one of our instances, there were 5 courses with 6 "books" while two others had "books" only in "test" or "dump" courses.

Creating service account for accessing Google Drive API

There was a request from the developers to create a shared drive for them in our Google Workspace, and to create a service account to access it programmatically.

Accordingly, created a new shared drive (and have added email1 and email2 as managers)

I have created the service account under an existing google cloud project under my (admin) google account (initially created for rclone), and have added Google Drive Api to the project.

The service account is called 
servaccname@projectname.iam.gserviceaccount.com

I have added this account also as a Content Manager on the Shared drive and shared the json key with the dev team.

Shared Drive storage quota - According to google help, a single shared drive can theoretically hold up to 5 TB per file, but it is strictly capped at 500,000 total items (files, folders, and shortcuts). 


I've currently not put any other cap on the storage quota for this shared drive.

Tuesday, July 14, 2026

Manage your unused OAuth clients - Google cloud

We got emails from Google cloud, "the following projects that you manage have OAuth clients that have been inactive for at least 5 months, and will be deleted in 30 days unless you take action" - checked, and we're planning on allowing them to be deleted, since those seemed to be clients which are not currently in use.

Friday, July 10, 2026

Google apps script issue - script.google.com refused to connect - google glitch

One of our servers which had a google apps script embedded in a php page started showing "script.google.com refused to connect" - the issue was noticed last afternoon. We checked that no changes had been made to the script, we did have
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
as mentioned in

The only other change was to install and set up fail2ban on the server, that was unlikely to be the cause. 

"If no changes have been made to the script, then perhaps it is a transient google problem, and might be resolved in a few hours.

If not, we would need to check if google apps scripts have any recent policy changes."

It might have been a google glitch, since last night the issue was resolved by itself. Looked like the outage was for around 8-10 hours.

Tuesday, July 07, 2026

reminder to take a break - Mac version

I wanted to recreate the earlier "reminder to take a break" cron job script on MacOS. Asked Claude about it, and it suggested using launchd instead of cron, since cron jobs run without access to the display by default. After several rounds of trial and error, here is the method that worked.

nano ~/Library/LaunchAgents/com.yourname.walkreminder.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.yourname.walkreminder</string>

    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>osascript -e 'display notification "Time to take a walk" with title "Reminder" sound name "Ping"'; afplay /Users/yourusername/Sounds/Walk.mp3</string>
    </array>

    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>14</integer>
            <key>Minute</key>
            <integer>0</integer>
        </dict>
    </array>

    <key>StandardOutPath</key>
    <string>/tmp/walkreminder.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/walkreminder.err</string>
</dict>
</plist>

In the above, the schedule is to run once a day at 14:00 hours. For running every half an hour from the time the user was logged on, we can use 

<key>StartInterval</key>
  <integer>1800</integer>

instead of <key>StartCalendarInterval</key>

Or, in my case, since I wanted every half an hour aligned to 0:00 and 0:30 exactly, 

 <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Minute</key>
            <integer>0</integer>
        </dict> 
        <dict>
            <key>Minute</key>
            <integer>30</integer>
        </dict>
    </array>

We had to use a Sounds directory which we had created, since afplay could not access the Downloads directory when run from launchd.

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.yourname.walkreminder.plist

and test with

launchctl kickstart -k gui/$(id -u)/com.yourname.walkreminder

Troubleshooting can be done with
plutil -lint ~/Library/LaunchAgents/com.yourname.walkreminder.plist
launchctl list | grep walkreminder
cat /tmp/walkreminder.err


Saturday, July 04, 2026

Running OpenSpace on ARM64 hardware like Apple Silicon Macs

The OpenSpace project has officially removed support for Mac, and newer commits make OpenGL 4.6 the minimum required version. Since Apple has frozen OpenGL support on MacOS at 4.1 (and even that is without support for some features like double-precision math in shaders), getting OpenSpace to run natively on MacOS seems difficult

Unfortunately, even earlier releases of OpenSpace can't be built for Mac, even with patches, due to external dependencies whose referenced older commits have been rebased away. 

The way out seems to be to use the older official releases with VMWare Windows 11 for best performance, with the current official release running atop VMWare only with software rendering.


There is a table of performance tests on various configurations, OpenSpace versions and drivers at
https://github.com/hn-88/OpenSpace-AppImage/wiki/OpenSpace-on-Mac#running-openspace-on-vms-in-macos

Interestingly, 0.21.x official x86 OpenSpace releases can run on Win11-ARM VMs on VMWare - the prism virtualization handles the x86 to ARM translation.

But 0.22.x official x86 OpenSpace releases can't run on Win11-ARM VMs on VMWare - the minimum OpenGL requirement has been bumped to 4.6, while VMWare's Windows drivers currently supply up to OpenGL 4.3.

In order to run OpenSpace 0.22.x with software rendering on Windows, we need to copy opengl32.dll from https://github.com/mmozeiko/build-mesa/releases/latest as mentioned at https://github.com/hn-88/OpenSpace-AppImage/issues/141 - and the dll architecture must match the OpenSpace binary's architecture. Further, the prism emulation layer can't handle x86 OpenGL dlls. So, only the ARM build of OpenSpace 0.22.x can currently run with software rendering, with the limitations like lack of molecule module, etc.

Friday, July 03, 2026

incident and response - malicious bots

One of our servers, which hosted a dot net backend as well as some wordpress sites, showed some outages two days in a row, restored by restarting. Feeding the apache access logs to Gemini via aistudio.google.com, Gemini said,

The logs clearly show an Apache HTTP
Server running PHP and hosting a WordPress application.

The logs indicate that your server was hit by an aggressive automated attack
(likely a botnet) starting around 07:33:35, which appears to have either
succeeded in exploiting a vulnerability or overloaded the server, causing it to
crash shortly after.

(Server had run out of memory). 

Gemini suggested the following - 

  1. Hide and Protect Your Origin IP - which we may not do
  2. Patch and Update the Server Software - which we're doing
  3. Implement a Web Application Firewall (WAF) - which is in place
  4. Clean Up WordPress Configuration - "Open your wp-config.php file, locate line 63, and remove the    duplicate definition of WP_AUTO_UPDATE_CORE. While this didn't cause the crash, it eats up server I/O and makes reading logs difficult."
  5. Restrict PHP Execution in Uploads Directories
  6. Implement Intrusion Prevention (Fail2Ban)

Then, feeding the access logs of the dot net api to Gemini 
and as suggested by Gemini,
journalctl -u ourapi.service --since "2026-06-28 07:15:00" --until "2026-06-28 07:45:00"

Gemini gave some recommendations like returning 0 instead of a 500 error for no data found -
"As we saw in the access logs, when the mobile app sees
    this 500 error, its poorly designed error-handling logic says: "Something
    went wrong! Retry the entire sync process!" It then proceeds to download 4MB
    of lesson data, hits the notification endpoint again, gets another 500
    error, and repeats the cycle every 15 seconds until your server runs out of
    memory and crashes."
- this may or may not be actually what is happening here, since Gemini just saw the logs and does not have access to the code.

In any case, I've enabled bot protection on Cloudflare for this domain, and also installed and configured Fail2ban.

On Cloudflare, 
ourdomain.org > Security > Security rules > Custom rules

Block .env scans
URI Path equals .env
Block

 also added Cloudflare's default rate limiting rule,

Leaked credential check [Template]
Password Leaked equals true
Block

also enabled Cloudflare's AI blocking tools - AI Labyrinth enabled, and Block AI training bots on all pages.

Then, installed and set up Fail2ban on the server, monitoring the apache web server and sshd logs. It will temporarily block ip addresses which fail authentication repeatedly, or which repeatedly request non-existent files like malicious bots.

Gemini via aistudio.google.com gave step-by-step instructions for installation and setup of Fail2ban. 

sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

(we can optionally edit these,
bantime  = 1h
findtime = 10m
maxretry = 5
)

Enable the Apache jails with
sudo nano /etc/fail2ban/jail.local
[apache-auth]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

In case the logpath is custom - fail2ban looks by default for
Error logs: /var/log/apache2/*error.log
Access logs: /var/log/apache2/*access.log

In the case of one of our servers, we needed to change this to
logpath  = %(apache_error_log)s
           /var/www/mysite/logs/custom-error*.log

More Apache jails to enable - basically need to add the enabled = true line - 

[apache-badbots]
enabled  = true
port     = http,https
logpath  = %(apache_access_log)s
bantime  = 48h
maxretry = 1

[apache-noscript]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

[apache-overflows]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

[apache-nohome]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

[apache-botsearch]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

Then we can test

sudo systemctl start fail2ban
sudo systemctl enable fail2ban
sudo systemctl status fail2ban

and check the enabled jails with

sudo fail2ban-client status

On one server, we had to resolve
ERROR   Failed during configuration: Have not found any log file
for sshd jail

For that, we had to change the block to
[sshd]
enabled = true
port    = ssh
backend = systemd

since that server was using systemd, and traditional text log files like /var/log/auth.log (which Fail2Ban looks for by default for SSH) are no longer created. After the change, after restarting the service, we can check that jail alone with

sudo fail2ban-client status sshd

Then, for using a different port rather than port 22 for sshd - 

[sshd]
enabled = true
port    = 2022
backend = systemd
(if port 2022 is being used) 
and so on, because that is the port which fail2ban would ban using the machine's firewall, iptables or nftables as the case may be.

To see the rules, we can use
sudo nft list ruleset # for nftables, Ubuntu 24.04
sudo iptables -nL # for iptables, earlier Ubuntu etc



Tuesday, June 23, 2026

SIR online form submission - Election Commission of India

Currently, a "Special Intensive Revision" or SIR is going on for the elector rolls in many parts of India. My colleague told me about the process going on in the local administration's office, and told me that I could submit the form online also.

An internet search revealed

Luckily, my mobile phone number was already available in the system, so when I clicked on sign-up, it indicated that my number is already registered. Then tried log in - an OTP was sent to my phone, and I could log in. 

The process which I followed was
  • Using the search function, found my name in the 2002 electoral rolls - it was on page 2 or 3, I skimmed through the results based on polling station name (we need to be able to read Telugu, the local language, for doing this.) I saved the info listed there - Assembly constituency, polling station and  
  • Next, went to the home page and clicked on "Fill Enumeration form"
  • We have to go through several OTPs, confirm our details, ensure that the name displayed is the same name as on Aadhaar - otherwise we need to do the form submission manually, details of the BLO (Booth Level Officer) are displayed.
  • Then the form opens up, where we need to fill up details and a recent photograph. The initial photographs I uploaded were not recognized "no face was recognized in this photograph" or something like that, after a wait of a minute or two. Thinking that this might be due to spectacles in the picture, clicked a new photo of myself without spectacles, and tried the upload.
  • Yesterday at around 2.30 pm, the form came up for submission after that, though the photo was not visible in the preview. But when I clicked on submit, the "Aadhaar OTP" method of verification did not succeed, it said wrong OTP every time.
  • This morning at around 8.50 am, went through the same process, this time the "Aadhaar OTP" method of verification was successful - again had to wait for a few minutes after uploading the photo in order to get the submit form enabled - and I got a downloadable receipt of the form submitted, with the new polling station number, constituency name and so on.
  • Found that I could also download my voter-id card (EPIC - Election Photo Identity Card) - from https://voters.eci.gov.in/ 

Thursday, June 18, 2026

rewrite of restic backup script and adding email alert

Found that our restic backup script had stopped running from Apr 20th - the log files were dated as last modified on that date. This could have been due to 
(a) an update overwriting the restic binary with an older version of ubuntu's restic via apt, which did not work, giving "backend not supported" errors for Azure Storage
(b) an additional issue that our Azure Storage account had become unavailable at some point of time due to a lapsed subscription 

So, created a new Storage account in an active subscription in the same resource group, which defaulted to the same Central India region for the storage account as we wanted. Used the same name as the earlier script's storage account name, and created a Blob container also with the same name as used by the script. 

Due to the point (a) above, this was not sufficient to make the script work, even for it to initialize the storage with lines like
restic -r azure:our-data-bk:/ourdata init
Fatal: create repository at azure:our-data-bk:/ourdata failed: invalid backend

As suggested by Gemini, the solution was to uninstall restic via apt, and to then download the latest restic and copy it to /usr/local/bin

wget https://github.com/restic/restic/releases/download/v0.18.1/restic_0.18.1_linux_amd64.bz2
bzip2 -d restic_0.18.1_linux_amd64.bz2
chmod +x restic_0.18.1_linux_amd64
sudo mv restic_0.18.1_linux_amd64 /usr/local/bin/restic

sudo apt remove restic

Then,
restic version
-bash: /usr/bin/restic: No such file or directory

We needed to tell bash to refresh the location - 
hash -r

Then the restic version showed the correct version, and the init also was successful. 

I wanted to get emails on future failures instead of the script failing silently, so Gemini helped with this script, which I have modified to change the passwords etc

#!/bin/bash
#This will run Restic backups from cron.
export RESTIC_PASSWORD=ourpw
export AZURE_ACCOUNT_NAME=ourname
#export AZURE_ACCOUNT_SAS="sv=2022-11-02&ss=bfqt&srt=c&sp=not_used_this_time%3D"
export AZURE_ACCOUNT_KEY="mVthisisthekey99999wPlEA=="
# not using rclone+gdrive due to slow,timeouts,rate-limits
#RCLONE_CONFIG=/home/user/.config/rclone/rclone.conf
#create new repo
# https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#microsoft-azure-blob-storage
#restic -r azure:our-data-bk:/ourdata init
# take backups
/usr/local/bin/restic  -r azure:sssvv-data-bk:/1data  --verbose backup  /var/www/1_data_disk/1_data/filedir > /home/user/1resticlog.txt 2>&1
/usr/local/bin/restic  -r azure:sssvv-data-bk:/2data  --verbose backup  /var/www/1_data_disk/2_data/filedir > /home/user/2resticlog.txt 2>&1
/usr/local/bin/restic  -r azure:sssvv-data-bk:/3data  --verbose backup  /var/www1_data_disk/3_data/filedir > /home/user/3resticlog.txt 2>&1
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
    SUBJECT="SUCCESS: Weekly Restic Backup"
    MESSAGE="Your weekly restic backup completed successfully."
else
    SUBJECT="ALERT: Weekly Restic Backup FAILED"
    MESSAGE="WARNING: Your restic backup FAILED with exit code $EXIT_CODE. Please investigate immediately."
fi
mail -s "$SUBJECT" "my@email.org" << EOF
$MESSAGE

Here is the log output:
--------------------------------------------------
$(cat "/home/user/3resticlog.txt")
EOF



Wednesday, June 17, 2026

Updating expiring Azure Linux Virtual Machine Secure Boot 2011 certificates

Microsoft Azure's email notification asked us to update the secure boot certificates before the end of the month, and pointed us to verification, and if necessary updating, steps. The "vendor recommended" documentation for Ubuntu support was a bit contradictory - saying that rollout had been paused - so took the help of ChatGPT and Gemini for completing the process. First took up a non-critical VM, completed that, and then went on to the others.

sudo snap install fwupd
sudo fwupdmgr refresh
sudo fwupdmgr update
#(say yes, yes, and yes to reboot)

Gemini reassured that the devices listed with "no updates" are not a concern, we should only check whether the mokutil tests below work OK.

As per the verification link above, 
Tested with
mokutil --db | grep "2023"
            Not Before: Jun 13 19:21:47 2023 GMT
        Subject: C=US, O=Microsoft Corporation, CN=Microsoft UEFI CA 2023
mokutil --kek | grep "2023"
            Not Before: Mar  2 20:21:35 2023 GMT
        Subject: C=US, O=Microsoft Corporation, CN=Microsoft Corporation KEK 2K CA 2023

Removed the fwupd snap, and also removed snap itself to prevent bloat
sudo snap remove fwupd
(and remove snap itself on ELS)
snap list
(if nothing other than core, core20, lxd, or snapd, can remove)

sudo systemctl disable --now snapd.service snapd.socket
sudo apt-get purge -y snapd
sudo rm -rf /snap /var/snap /var/lib/snapd /var/cache/snapd /usr/lib/snapd

Found that the L VM was already up-to-date since it was a newer VM, created in 2025.

SDev2 had to be updated in the same manner as for the HAPROXY VM above.

SSS web server also had to be updated in the same manner.

On the AWS VM, I see

mokutil --sb-state
EFI variables are not supported on this system

Gemini says,

You do not need to do anything for this AWS VM. You are completely in the clear.
Seeing EFI variables are not supported on this system means that this specific EC2 instance is not using UEFI Secure Boot at all. In fact, it is likely booting using Legacy BIOS rather than UEFI.


With that, all the VMs seem to be accounted for.

Tuesday, June 16, 2026

Samsung phone Gboard voice typing icon vanished

At some point of time, after some upgrades / updates, the voice-typing mic icon vanished, for the Gboard keyboard on my Samsung M34 5G phone. 

There were lots of contradictory (and perhaps out-dated) info online on how to re-enable voice-typing, but what worked for me was as follows. Gboard was already set as the default keyboard, and not Samsung keyboard in the settings. 

When Gboard was visible, the path to set this was,
the icon to show more items - 
then the Gboard settings icon,

 followed by voice-typing

and finally slide to enable "Use voice typing" as below.

Then the mic icon at the top right corner of Gboard becomes visible.


Sunday, June 07, 2026

upgrade mesa on Ubuntu 22

For testing OpenSpace on Ubuntu 22, I wanted to upgrade the Mesa provided OpenGL to v4.6. According to https://linuxcapable.com/how-to-upgrade-mesa-drivers-on-ubuntu-linux/ - we have to use the repo kisak/turtle stable for Ubuntu 22.

sudo add-apt-repository ppa:kisak/turtle
sudo apt update
sudo apt upgrade
Calculating upgrade... Done
The following packages were automatically installed and are no longer required:
  libgl1-amber-dri libglapi-mesa
Use 'sudo apt autoremove' to remove them.
Get more security updates through Ubuntu Pro with 'esm-apps' enabled:
  libzvbi-common liburiparser1 libheif1 libmujs1 libavdevice58 ffmpeg
  libpostproc55 libavcodec58 libgstreamer-plugins-bad1.0-0 libavutil56
  libswscale5 freeglut3 libswresample3 libavformat58 libzvbi0 libde265-0
  libavfilter7
Learn more about Ubuntu Pro at https://ubuntu.com/pro
The following NEW packages will be installed:
  mesa-libgallium
The following packages will be upgraded:
  libdrm-amdgpu1 libdrm-common libdrm-intel1 libdrm-nouveau2 libdrm-radeon1
  libdrm2 libegl-mesa0 libgbm1 libgl1-mesa-dri libglx-mesa0 libllvm15
  libvdpau1 libxatracker2 mesa-va-drivers mesa-vdpau-drivers
  mesa-vulkan-drivers vdpau-driver-all
17 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.

income tax filing has become simplified

Income tax filing for us in India has now become further simplified. Bank interest and salary income are automatically being pre-filled via the AIS, so only capital gains if any, from sale of mutual fund units, needs to be entered by us. No need to keep track of any other deductions, since we've now moved to the new tax regime. Also, no need to report gift from parents / sister. So, my workflow was:

1. Download AIS from the income tax site
2. Check the salary component in AIS against the Form16 given to us from the office
3. Verify that the AIS contains the interest statements from all three banks in which I have accounts
4. Download Capital Gains statement from MFCentral 
5. Go through ITR2, entering only minor info (like "secondary address is same as primary address") and the capital gains schedules (which have also become simplified for me since most of the current redemptions are of assets purchased after 2018 and can be entered just as single consolidated figures).

Saturday, June 06, 2026

in-place upgrade Ubuntu 22.04 web server to Ubuntu 24.04

One of our web servers was running Ubuntu 22.04 and showed that an upgrade was available via 'do-release-upgrade'

I took the plunge, running the upgrade via screen in case our connection broke. (The upgrade process also auto-starts sshd on port 1022 also, in case the upgrade needs recovery. But thankfully, I didn't need it.)

Chose the default options every time for retaining the configuration files. Noticed that apache showed a "syntax error" in config files.

After the restart, checked apache status with

sudo systemctl status apache2
× apache2.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Sat 2026-06-06 04:18:46 UTC; 1min 46s ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 797 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
        CPU: 28ms
Jun 06 04:18:45 sssihms-web-vm2023 systemd[1]: Starting apache2.service - The Apache HTTP Server...
Jun 06 04:18:45 sssihms-web-vm2023 apachectl[821]: apache2: Syntax error on line 146 of /etc/apache2/apache2.conf: Syntax error on line 3 of /etc/apache2/mods-enabled/php8.1.load:>
Jun 06 04:18:46 sssihms-web-vm2023 systemd[1]: apache2.service: Control process exited, code=exited, status=1/FAILURE
Jun 06 04:18:46 sssihms-web-vm2023 systemd[1]: apache2.service: Failed with result 'exit-code'.
Jun 06 04:18:46 sssihms-web-vm2023 systemd[1]: Failed to start apache2.service - The Apache HTTP Server.

Claude pointed out that Ubuntu 24.04 has php8.3, so loading php8.1 would fail. So, 

sudo a2dismod php8.1

# Install php8.3
sudo apt install php8.3 libapache2-mod-php8.3
# this had already been installed during the upgrade

# Enable the new module
sudo a2enmod php8.3
sudo systemctl restart apache2

All good. Wordpress is also running fine.