If your DirectAdmin server cannot cleanly move to MariaDB 11.4 through CustomBuild, but you still need MariaDB 11.4 on the box, the safe manual model is straightforward: let Debian manage MariaDB 11.4, let DirectAdmin behave only as a client through da_admin, and remove the stale service files, binaries, and socket assumptions that collide with the new server.

This is not the preferred path on a modern DirectAdmin build. If your server can use current CustomBuild normally, use that. This guide is for the edge case where the panel layer is older, pinned, partially migrated, or otherwise constrained, while the operating system and database layer still need to move forward cleanly.

The good news is that MariaDB’s side of the process is well documented and predictable. The difficult part is not MariaDB 11.4 itself. The difficult part is integrating a modern MariaDB package set into a legacy DirectAdmin environment without letting older service definitions, wrapper binaries, or socket expectations interfere.

The working model is simple: Debian owns MariaDB, DirectAdmin connects to it through da_admin, and legacy leftovers do not get to control anything anymore.

If you manage older panel servers regularly, this tutorial fits naturally beside ServerSpan’s DirectAdmin Legacy License ends July 2026: what’s changing, the MariaDB 10.6 EOL trap, and your migration options and MariaDB vs. MySQL 8.0: Performance Benchmarks & Configuration Guide for VPS. If you need a clean server for this kind of work, start with ServerSpan Virtual Servers. If you want the database layer kept sane by someone else, that is where ServerSpan Linux Administration becomes the sensible option.

When this guide actually makes sense

Use this guide when all of the following are true:

  • you are on Debian or Ubuntu, or another Debian-style DirectAdmin host
  • MariaDB 11.4 is required on the system now
  • you are not taking the normal CustomBuild route for the database layer
  • DirectAdmin still needs to create users, databases, and grants through da_admin
  • you are prepared to validate the migration like a sysadmin, not like someone hoping the panel saves them

Do not use this guide on a fresh DirectAdmin deployment that already supports MariaDB 11.4 through the standard path. And do not use it on a server where you are not ready to make and verify backups first. Major MariaDB downgrade is not something you should treat as easy or routine.

Before you touch anything: understand the model

The typical failure mode in legacy DirectAdmin database stacks is not that MariaDB 11.4 is unstable. In most cases, the database layer behaves exactly as documented. The friction comes from package mixing and older DirectAdmin-era assumptions that were never cleaned up.

  • new MariaDB 11.4 packages are installed from the MariaDB APT repository
  • old MySQL or MariaDB binaries still exist under /usr/local/
  • a stale custom mysqld.service still lives under /etc/systemd/system/
  • old socket paths are still hardcoded in scripts or client defaults
  • DirectAdmin keeps talking to the wrong binary, the wrong socket, or the wrong account

The fix is not clever. It is disciplined. Freeze DirectAdmin monitoring, back up the datadir, stop every process that can still touch the database files, remove stale service and path collisions, install a clean MariaDB 11.4 package set, run the real upgrade tool, restore compatibility where needed, keep DirectAdmin on da_admin, and only then turn the panel back loose.

Phase 0: freeze DirectAdmin’s MySQL service monitor

Before you replace or restart anything, stop DirectAdmin from trying to “help” by restarting the wrong database service while you are working.

sed -i -e 's/mysqld=ON/mysqld=OFF/g' /usr/local/directadmin/data/admin/services.status

This matters because DirectAdmin monitors service state through that file. If you leave monitoring enabled during a manual database migration, the panel can interfere with shutdown, startup, or failure handling at exactly the wrong moment.

Phase 1: back up the datadir before doing anything destructive

Do not skip this. Back up the whole datadir before you clean up binaries, wrappers, or service units. If the data matters, your rollback plan is the backup you made before the upgrade, not wishful thinking afterward.

cp -a /var/lib/mysql /var/lib/mysql.pre-mariadb-11.4.$(date +%F-%H%M%S)

If the database is large, use a more serious backup method than cp -a. The principle does not change. Backup first. Cleanup second. Upgrade third.

Phase 2: stop everything that can still own the datadir

You need a genuinely clean stop. That means packaged service names, legacy helper names, and any leftover processes.

systemctl stop mysqld 2>/dev/null || true
systemctl stop mysql 2>/dev/null || true
systemctl stop mariadb 2>/dev/null || true

service mysqld stop 2>/dev/null || true
service mysql stop 2>/dev/null || true
service mariadb stop 2>/dev/null || true

pkill -TERM mysqld 2>/dev/null || true
pkill -TERM mariadbd 2>/dev/null || true
sleep 3

pkill -KILL mysqld 2>/dev/null || true
pkill -KILL mariadbd 2>/dev/null || true
sleep 2

ps -ef | egrep 'mariadbd|mysqld' | grep -v grep

If that last command prints anything, you are not ready to continue. Stop there and resolve the live process first. Do not upgrade a datadir that is still being touched by something you did not intend to keep alive.

Phase 3: remove stale systemd units and PATH shadowing

This is one of the ugliest parts of older DirectAdmin database stacks. A stale /etc/systemd/system/mysqld.service or an old wrapper in /usr/local/bin can keep pointing at a dead MySQL or MariaDB tree even after you installed MariaDB 11.4 correctly from packages.

MariaDB itself is not the problem there. The problem is that the host still contains older service plumbing that no longer belongs in the active stack.

Archive old custom service files first:

mkdir -p /root/old-systemd-units
mv /etc/systemd/system/mysqld.service /root/old-systemd-units/mysqld.service.$(date +%F-%H%M%S) 2>/dev/null || true
mv /etc/systemd/system/mysql.service  /root/old-systemd-units/mysql.service.$(date +%F-%H%M%S) 2>/dev/null || true

Then archive wrappers or shadow binaries under /usr/local/bin:

mkdir -p /root/old-mysql-bin
mv /usr/local/bin/mariadb-upgrade /root/old-mysql-bin/ 2>/dev/null || true
mv /usr/local/bin/mariadb         /root/old-mysql-bin/ 2>/dev/null || true
mv /usr/local/bin/mysql           /root/old-mysql-bin/ 2>/dev/null || true
mv /usr/local/bin/mysql_upgrade   /root/old-mysql-bin/ 2>/dev/null || true
hash -r

Now verify what the shell will really use:

type -a mariadb mariadb-upgrade mysql mysql_upgrade
/usr/bin/mariadb --version
/usr/bin/mariadb-upgrade --version

After this step, the live client tools should come from /usr/bin, not from leftovers under /usr/local/bin.

Phase 4: add the MariaDB 11.4 repository and install 11.4 cleanly

MariaDB’s documented Linux upgrade flow is clear and consistent. The cleanest approach here is to follow that package model directly and keep the version set matched.

Clear conflicting repository files first, then configure the official MariaDB 11.4 repository.

rm -f /etc/apt/sources.list.d/*mariadb*.list /etc/apt/sources.list.d/*mariadb*.sources 2>/dev/null || true

curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | bash -s -- \
  --mariadb-server-version="mariadb-11.4"

apt update
apt-cache policy mariadb-server

If the candidate version is not 11.4, stop and fix the repository before installing anything.

Then install a matched 11.4 package set:

ver="$(apt-cache madison mariadb-server | awk '/11\.4/{print $3; exit}')"
echo "$ver"

apt install -y \
  mariadb-server="$ver" \
  mariadb-client="$ver" \
  mariadb-server-core="$ver" \
  mariadb-client-core="$ver" \
  mariadb-common="$ver" \
  libmariadb3="$ver" \
  mariadb-backup="$ver" \
  galera-4

The version pinning is not decoration. It reduces the chance of package skew and makes the install easier to reason about later if something still looks off.

Phase 5: start the real MariaDB 11.4 server and run the real upgrade tool

Once the packaged server is installed, start the actual Debian-managed service.

systemctl daemon-reload
systemctl enable mariadb
systemctl start mariadb
systemctl status mariadb --no-pager -l

If mariadb.service does not come up cleanly here, stop and fix that first. Do not run the upgrade utility against a broken or half-started service.

Then run the upgrade tool explicitly from /usr/bin, not from whatever your shell happens to find first.

If local root uses socket authentication, which is normal on Debian-family MariaDB installs, use:

/usr/bin/mariadb-upgrade \
  --no-defaults \
  --protocol=socket \
  --socket=/run/mysqld/mysqld.sock \
  --user=root \
  --force

If your local root still uses a password, add -p:

/usr/bin/mariadb-upgrade \
  --no-defaults \
  --protocol=socket \
  --socket=/run/mysqld/mysqld.sock \
  --user=root \
  -p \
  --force

The explicit path and explicit socket are important because old defaults, old wrappers, or old socket assumptions are exactly what create confusion in legacy panel environments. MariaDB’s own side of the process is more predictable than the surrounding leftovers.

Phase 6: restore service-name compatibility without reviving the wrong service

On a clean Debian MariaDB install, the real service is mariadb.service. Older tooling may still ask for mysqld or mysql. The safe fix is not to restore an old unit. The safe fix is to alias the old names to the real service.

ln -s /lib/systemd/system/mariadb.service /etc/systemd/system/mysqld.service
ln -s /lib/systemd/system/mariadb.service /etc/systemd/system/mysql.service

systemctl daemon-reload
systemctl reset-failed mariadb mysqld mysql 2>/dev/null || true

The goal is simple: one real service, older names resolving cleanly to it, no custom unit left behind that points at stale binaries.

Phase 7: fix socket compatibility

Newer DirectAdmin builds moved the preferred socket path toward /run/mysql/mysql.sock, while older clients and scripts often still expect /var/lib/mysql/mysql.sock or the traditional /run/mysqld/mysqld.sock. The practical answer on a manual Debian-based deployment is not to move the real socket. It is to give older callers compatibility paths.

mkdir -p /run/mysql
ln -sfn /run/mysqld/mysqld.sock /run/mysql/mysql.sock
ln -sfn /run/mysqld/mysqld.sock /var/lib/mysql/mysql.sock

That keeps both newer and older callers happy without changing where the real server listens.

Phase 8: keep DirectAdmin on da_admin, not MariaDB root

This is where the integration becomes clean again. DirectAdmin should use da_admin through /usr/local/directadmin/conf/mysql.conf. It should not depend on MariaDB root for ordinary panel operations.

Check the file:

cat /usr/local/directadmin/conf/mysql.conf

It should look like this in principle:

user=da_admin
passwd=YOUR_DA_DB_PASSWORD

If you need to reset the account inside MariaDB:

/usr/bin/mariadb --protocol=socket --socket=/run/mysqld/mysqld.sock
ALTER USER 'da_admin'@'localhost' IDENTIFIED BY 'daadminpass';
GRANT ALL PRIVILEGES ON *.* TO da_admin@localhost WITH GRANT OPTION;
FLUSH PRIVILEGES;

Then update /usr/local/directadmin/conf/mysql.conf to match and test it directly:

/usr/bin/mariadb \
  --protocol=socket \
  --socket=/run/mysqld/mysqld.sock \
  -uda_admin -p \
  -e "SHOW DATABASES;"

If that works, DirectAdmin-side database connectivity is in good shape.

Also check for conflicting local defaults such as /root/.my.cnf if DirectAdmin still behaves strangely. Hidden client overrides are a classic cause of misleading authentication failures.

Phase 9: understand root, debian-start, and unix_socket before “fixing” them

Do not delete /etc/mysql/debian-start. Do not delete helper scripts just because they produce a warning you do not like. Debian-family MariaDB installs commonly use unix_socket authentication for root@localhost, which means local root access works through the Unix user identity instead of a database password.

That does not break DirectAdmin, because DirectAdmin should still use da_admin. These are separate concerns:

  • local Linux root can keep local MariaDB root access through socket auth
  • DirectAdmin keeps using da_admin from mysql.conf
  • those two models do not need to be merged

If local root socket auth is working, test it directly:

/usr/bin/mariadb --protocol=socket --socket=/run/mysqld/mysqld.sock -e "SELECT VERSION();"

If local root works and da_admin works, leave it alone. There is no reason to manufacture extra complexity around database root unless your environment explicitly requires it.

Phase 10: re-enable DirectAdmin monitoring

Only re-enable monitoring after all of these are true:

  • mariadb.service is healthy
  • the compatibility service names resolve cleanly
  • the socket compatibility links exist
  • da_admin can connect successfully
sed -i -e 's/mysqld=OFF/mysqld=ON/g' /usr/local/directadmin/data/admin/services.status
systemctl restart directadmin

Final verification checklist

Now run a short, boring checklist. Boring is exactly what you want here.

systemctl status mariadb --no-pager -l
systemctl is-active mariadb mysqld mysql
ps -ef | egrep 'mariadbd|mysqld' | grep -v grep
ss -xl | grep mysql

type -a mariadb mariadb-upgrade mysql mysql_upgrade

/usr/bin/mariadb --protocol=socket --socket=/run/mysqld/mysqld.sock -e "SELECT VERSION();"
/usr/bin/mariadb --protocol=socket --socket=/run/mysqld/mysqld.sock -uda_admin -p -e "SHOW DATABASES;"

If the results show all of the following, the migration is done:

  • mariadb.service is active
  • mysqld and mysql resolve cleanly as compatibility names
  • there is exactly one live mariadbd
  • the server version is 11.4.x
  • da_admin can connect and list databases

What not to do

  • Do not mix old DirectAdmin-era client tools in /usr/local/bin with Debian-packaged MariaDB 11.4 tools in /usr/bin.
  • Do not keep an old custom /etc/systemd/system/mysqld.service once the real MariaDB package is installed.
  • Do not edit /usr/local/directadmin/conf/my.cnf and expect it to stay that way.
  • Do not delete Debian helper scripts just to hide warnings you do not understand.
  • Do not assume rollback from a failed major upgrade is easy without a real pre-upgrade backup.

The theme is always the same: ambiguity is what breaks these servers. Remove ambiguity, and MariaDB 11.4 behaves much more like the clean packaged server it is supposed to be.

Bottom line

The sysadmin path here is not elegant, but it is reliable: freeze DirectAdmin monitoring, back up the datadir, stop every process that can still touch the database files, remove stale service files and wrapper binaries, install a matched MariaDB 11.4 package set, start the real Debian-managed service, run the real /usr/bin/mariadb-upgrade, restore compatibility for service names and sockets, keep DirectAdmin on da_admin, and only then hand control back to the panel.

That gets you MariaDB 11.4 on a legacy DirectAdmin environment without waiting for CustomBuild to rescue a server that no longer fits the clean path. It also gives MariaDB what it generally likes best: a clean package-managed deployment, a predictable service model, and fewer legacy surprises around it.

If you would rather not do this by hand on a production host, use DirectAdmin Management or Linux Administration and keep the box boring for the right reasons.

Source & Attribution

This article is based on original data belonging to serverspan.com blog. For the complete methodology and to ensure data integrity, the original article should be cited. The canonical source is available at: Tutorial: How to use MariaDB 11.4 with a legacy DirectAdmin environment on Debian, the sysadmin way.