Skip to content
LibxaFrame
Sign In
Release 9 August 2026 5 min read

Libxa Desktop 0.2.0: phpMyAdmin, and per-site PHP that actually works

phpMyAdmin now installs in one click, configured against the managed database and bound to your own machine. Pinning it to a supported PHP version exposed a bug underneath: every site had been routed to a single php-cgi, so the per-site version dropdown was recorded, displayed and ignored.

phpMyAdmin now installs in one click, configured against the database Libxa Desktop already manages and served at phpmyadminlibxa.test. Getting it onto a PHP version it supports exposed a bug underneath, which turned out to be the more interesting half of this release.

phpMyAdmin, in one click

Open Services → Database tools and press Install. The app downloads 5.2.3 from files.phpmyadmin.net, checks it against the .sha256 the project publishes beside the archive, extracts it, and writes config.inc.php pointing at the managed MariaDB on whichever port Settings says.

The version comes from phpMyAdmin's own release feed rather than a number frozen into the app, so it tracks their releases without us shipping an update.

The generated config preserves its session secret across rewrites. Rotating it would silently sign you out, and a database tool that logs you out every time a setting changes is a database tool nobody trusts.

Two decisions about how it is served are worth stating plainly.

It is bound to your machine. phpMyAdmin administers the database as root, and nginx binds every interface. On a café network the default would be an open database console, so its server block carries:

allow 127.0.0.1;
allow ::1;
deny  all;

It gets no front-controller rewrite. phpMyAdmin is a classic multi-file application. A missing path should 404, not be rewritten into index.php the way a framework's front controller expects.

The bug underneath

phpMyAdmin 5.2.3 declares the PHP range it supports:

"php_versions": ">=7.2,<8.4"

Libxa Desktop will happily install 8.5. Serving phpMyAdmin on it produces deprecation spew or a blank page: a failure that reads as a broken install rather than a version mismatch. So the vhost picks the newest installed version inside the declared range.

Then we checked what it was actually running on:

PHP version: 8.4.19

Not 8.3. Not anything inside the range.

Per-site PHP versions had never been routed. nginx sent every site to a single fastcgi_pass 127.0.0.1:9000, and one php-cgi process serves exactly one PHP build. There was no second process to route to. The version dropdown on the Sites tab recorded your choice, displayed it back to you, and did nothing.

One process per version

The supervisor now starts one php-cgi for every PHP version in use, and each server block points at the matching port:

franky.test           → 127.0.0.1:9001   PHP 8.4
libxastack.test       → 127.0.0.1:9001   PHP 8.4
phpmyadminlibxa.test  → 127.0.0.1:9000   PHP 8.3

Both the supervisor and the config generator derive the same version-to-port map from the same site list, sorted. Sorting matters: an unsorted map would assign different ports on different runs, and a restart would leave the generated config pointing at a process that had moved.

phpMyAdmin now reports PHP 8.3.30, and every other site stays on 8.4.

Upgrading

This changes behaviour. Any site pinned to something other than your default was silently being served by the default; after updating, those sites move onto the version they were configured for. That is what they were meant to do all along, but it is a real change if you had come to rely on the old result.

Everything else is additive. The app updates itself: it checks on launch and every six hours, downloads in the background, and asks before installing.

Keep reading