After a MariaDB upgrade, accounts that logged in fine before can suddenly fail with ERROR 1698 (28000): Access denied for user 'root'@'localhost' or a message about a plugin that cannot be loaded. The cause is almost always the authentication plugin attached to the account, not a wrong password. This guide shows you how to find the plugin each user is using, switch between unix_socket and mysql_native_password, and regain access when you are locked out.
The fix is usually one ALTER USER statement. The hard part is knowing which statement to run and which account is affected.
Before you start
You need:
- SSH access to your Linux VPS with a sudo-capable account or root.
- The MariaDB or MySQL client installed (
mariadbon newer MariaDB releases,mysqlon older ones and on MySQL). - The name of the account that fails, and whether the app connects over a Unix socket or TCP.
Take a full dump before you change any account. Authentication changes are reversible, but a backup removes all risk.
sudo mariadb-dump --all-databases --single-transaction --routines --events \
> /root/all-databases-$(date +%F).sqlWarning: Do not edit rows in mysql.user or mysql.global_priv by hand. Direct edits are ignored or overwritten by the server, and they can leave accounts in a state that no longer matches the privilege tables. Always use CREATE USER, ALTER USER and GRANT.
Why upgrades break authentication
MariaDB 10.4 changed the default for root@localhost from mysql_native_password to unix_socket. With unix_socket, the server checks the operating system user instead of a password: if you are logged in as root over SSH, sudo mariadb works with no password at all. If you connect as any other OS user, or over TCP, the check fails.
That is why the same account can behave differently depending on how you connect:
sudo mariadbas root — succeeds through the Unix socket.mysql -u root -pas a normal user — fails with error 1698.- A PHP or Python app connecting to
127.0.0.1— fails, because TCP never usesunix_socket.
The second common failure is a plugin that is not loaded, which produces ERROR 1524 (HY000): Plugin 'unix_socket' is not loaded or a similar message naming mysql_native_password.
Check which plugin a user uses
Log in as root through the socket, which works even when passwords are broken:
sudo mariadbThen list the accounts and their plugins:
SELECT User, Host, plugin FROM mysql.user WHERE User IN ('root', 'deploy');On MariaDB 10.4 and later you can also inspect a single account in full:
SHOW CREATE USER 'deploy'@'localhost';The output shows the plugin name and, for password-based accounts, the hash. A blank or unix_socket plugin means no password is accepted for that account.
Fix unix_socket login failures
If sudo mariadb works but mysql -u root -p returns error 1698, root only has unix_socket. Two options.
Option 1 — give root a password as well. This keeps socket login working for the OS root user and adds password login:
ALTER USER 'root'@'localhost'
IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('ChangeMe-Str0ng!');
FLUSH PRIVILEGES;Option 2 — create a dedicated application user. This is the better habit. Applications should not run as root:
CREATE USER 'deploy'@'localhost'
IDENTIFIED VIA mysql_native_password USING PASSWORD('ChangeMe-Str0ng!');
GRANT ALL PRIVILEGES ON appdb.* TO 'deploy'@'localhost';
FLUSH PRIVILEGES;Note the MariaDB syntax: IDENTIFIED VIA... USING PASSWORD(...). MySQL uses IDENTIFIED WITH... BY 'password'. If you copy a snippet from a MySQL tutorial into MariaDB, or the reverse, it will fail with a syntax error.
Tip: If the app connects to 127.0.0.1 rather than localhost, create the user for 'deploy'@'127.0.0.1' too, or use 'deploy'@'%' only if you have a firewall in front. localhost and 127.0.0.1 are different hosts in the privilege tables.
Fix mysql_native_password errors
When the error names a plugin that is not loaded, check the plugin list:
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM information_schema.PLUGINS
WHERE PLUGIN_NAME LIKE '%password%' OR PLUGIN_NAME LIKE '%socket%';If unix_socket shows NOT INSTALLED, load it for the current session:
INSTALL SONAME 'auth_socket';To make it permanent, add it to the server configuration and restart MariaDB:
[mysqld]
plugin_load_add = auth_socketmysql_native_password is built into MariaDB, so it normally needs no loading. On MySQL 8.4 and later it is disabled by default, and the recommended replacement is caching_sha2_password. Plugin defaults change between releases, so check the vendor documentation for the exact version you run before switching a production account.
Warning: Restarting MariaDB drops every open connection. Do it in a maintenance window, or at least confirm no long-running import or backup is in progress.
Reset a locked-out root password
If no account can authenticate, start the server with grant checks disabled. This is a recovery mode, not a normal state.
sudo systemctl stop mariadb
sudo mysqld_safe --skip-grant-tables --skip-networking &--skip-networking keeps the server off the network while it is unprotected. Connect locally:
mariadbFLUSH PRIVILEGES;
ALTER USER 'root'@'localhost'
IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('NewStrongPass!');
FLUSH PRIVILEGES;Then shut the recovery instance down and start the service normally:
sudo mysqladmin shutdown
sudo systemctl start mariadbCheck it works
Test both paths — socket and TCP — because they use different plugins:
sudo mariadb -e "SELECT CURRENT_USER(), VERSION();"
mysql -u deploy -p -h 127.0.0.1 appdb -e "SELECT CURRENT_USER();"The first should return root@localhost, the second deploy@127.0.0.1 or deploy@localhost depending on how the account is defined. Then restart your application and confirm it connects without touching the config file.
Troubleshooting
ERROR 1698 (28000): Access denied for user 'root'@'localhost'— root has onlyunix_socket. Run the client withsudo, or addmysql_native_passwordto the account as shown above.ERROR 1045 (28000): Access denied for user 'deploy'@'localhost'— wrong password, or a host mismatch. Check theHostcolumn:localhost,127.0.0.1and%are separate accounts. See fix MySQL error 1045.ERROR 1524 (HY000): Plugin 'unix_socket' is not loaded— the plugin is missing from the server. Load it withINSTALL SONAME 'auth_socket';and addplugin_load_addto the config.ERROR 2059 (HY000): Authentication plugin... cannot be loaded— the client library is older than the server's plugin. Upgrade the client package, or move the account tomysql_native_password.- Works from the CLI but not from the app — the app connects over TCP, so
unix_socketnever applies. Give the application user a password-based plugin. - Changes disappear after a restart — you edited
mysql.userdirectly instead of usingALTER USER. Recreate the account withALTER USERso the change is written tomysql.global_priv.
Next steps
- Install and secure MariaDB or MySQL, and allow remote access safely — set up accounts correctly from the start.
- How to create a database and user for a web app — the safe pattern for application credentials.
- Tune MySQL and MariaDB memory settings for a small VPS — keep the server stable after your changes.
- Restore MariaDB from a mariabackup backup — if an account change goes wrong and you need to roll back.
