Fix phpMyAdmin Error 1698: Access Denied for Root
phpMyAdmin shows 'Access denied for user 'root'@'localhost'' with error 1698. It's a MySQL auth plugin mismatch — here's the quick fix.
Quick answer for advanced users
Run this in your MySQL terminal: ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourNewPassword'; then FLUSH PRIVILEGES;. Restart phpMyAdmin and you're in.
Why this happens
If you're on Ubuntu 20.04+, Debian 10+, or any recent LAMP stack, MySQL 5.7+ and MariaDB 10.2+ changed the default authentication plugin for the root user from mysql_native_password to auth_socket. This means MySQL authenticates root by checking if you're logged into the system shell as root or via sudo — not by password. phpMyAdmin, which sends a TCP connection with a password, can't use that socket method. So it throws error 1698: Access denied. This tripped me up the first time too, and I've seen it on dozens of server setups for WordPress, Laravel, and custom apps.
The error usually shows up when you first install phpMyAdmin, or after a MySQL upgrade. You'll see the full message: #1698 - Access denied for user 'root'@'localhost'. It's not a password problem — it's an authentication plugin problem.
Fix steps (the only one you need 90% of the time)
- Open a terminal and log into MySQL as root using sudo — this works because of auth_socket:
sudo mysql -u root - Switch to the mysql system database:
USE mysql; - Check what auth plugin root is using right now:
You'll likely seeSELECT user, plugin FROM user WHERE user = 'root';auth_socketfor each root row. - Change the root user's authentication plugin and set a new password:
If you have multiple root entries (like 'root'@'%' or 'root'@'127.0.0.1'), repeat for each.ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourStrongPassword123!'; - Apply the changes:
FLUSH PRIVILEGES; - Exit MySQL:
EXIT; - Test the new password by logging in from terminal:
Enter the password you set. If it works, phpMyAdmin will work too.mysql -u root -p - In phpMyAdmin, update
/etc/phpmyadmin/config-db.phpor your phpMyAdmin config file to match the new password. Look for these lines:$dbuser='root';
$dbpass='YourStrongPassword123!'; - Restart phpMyAdmin (or Apache/Nginx):
sudo systemctl restart apache2orsudo systemctl restart nginx
Alternative fixes when the main one fails
Fix 1: Create a dedicated phpMyAdmin user (recommended over using root)
This is actually what I do on every production server. Root should never be used for web apps. Create a new user with full privileges:
CREATE USER 'pmauser'@'localhost' IDENTIFIED BY 'AnotherStrongPassword!';
GRANT ALL PRIVILEGES ON *.* TO 'pmauser'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES; Then update your phpMyAdmin config to use pmauser instead of root.Fix 2: If you're using MariaDB
MariaDB 10.4+ introduced unix_socket authentication, which behaves like auth_socket. The same ALTER USER command works, but you may need to specify the full host:
ALTER USER 'root'@'localhost' IDENTIFIED VIA mysql_native_password USING PASSWORD('YourPassword');
FLUSH PRIVILEGES;Fix 3: If you can't even log in via sudo mysql
This is rare, but sometimes the MySQL socket file is missing or permissions are wrong. Check if /var/run/mysqld/mysqld.sock exists. If not, restart MySQL: sudo systemctl restart mysql or sudo systemctl restart mariadb. Then try sudo mysql again.
Prevention tip
After you fix this, never use root for phpMyAdmin in production. Create a dedicated user with limited database access. For example: CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'Password'; GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost';. This limits damage if credentials leak. Also, consider using a config file outside the web root — most phpMyAdmin installs already do this, but double-check that /etc/phpmyadmin/config-db.php is not readable by the web server user. Set permissions to 640 and owner to root:www-data.
One last thing: If you upgrade MySQL or MariaDB later, the auth plugin might reset to auth_socket again. Just run the ALTER USER command again — it doesn't lose your existing databases.
Was this solution helpful?