I was working on a Laravel task and got this error in my logs:
SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)
My .env file had DB_PASSWORD=password, but MySQL was rejecting it. I tried the usual tricks and ran into a wall. Here is what was happening, what fixed it, and a few small things that confused me along the way. If you are a junior dev and any of this sounds familiar, this post is for you.
Step 1: Check if your Laravel .env is the problem first
Before anything wild, open your .env file and check these lines:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_app
DB_USERNAME=root
DB_PASSWORD=password
If your password is blank or wrong, just fix it and run:
php artisan config:clear
Done. If the password really is what you think it is and MySQL still rejects it, keep reading.
Step 2: Try the classic Ubuntu trick
On a lot of Ubuntu installs, the MySQL root user does not use a password at all. It uses something called socket authentication, which means you log in by being a Linux superuser. So this usually works:
sudo mysql
If that opens a MySQL prompt, great. You can set a real password from inside:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
FLUSH PRIVILEGES;
But in my case I got this:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
That means root already had a password set, just not one I knew. Time for the real recovery.
Step 3: Reset the password using an init file
The safest way to reset a forgotten root password is to start MySQL with a special init file. The init file runs SQL the moment MySQL boots, so you can change the password without ever logging in.
Here is a small bash script that does the whole thing. Save it as mysql-reset.sh:
#!/bin/bash
set -e
NEW_PASS='password'
INIT_FILE=$(mktemp /tmp/mysql-init-XXXXXX.sql)
cat > "$INIT_FILE" <<SQL
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '${NEW_PASS}';
FLUSH PRIVILEGES;
SQL
sudo chown mysql:mysql "$INIT_FILE"
sudo chmod 600 "$INIT_FILE"
echo "Stopping mysql..."
sudo systemctl stop mysql
echo "Starting mysql with the init file..."
sudo mysqld --user=mysql --init-file="$INIT_FILE" --daemonize
sleep 3
echo "Stopping the temporary mysqld..."
sudo pkill -f "mysqld --user=mysql --init-file=$INIT_FILE" || true
sleep 2
echo "Starting mysql normally..."
sudo systemctl start mysql
sudo rm -f "$INIT_FILE"
echo "Testing the new password..."
mysql -u root -p"$NEW_PASS" -e "SELECT 'OK' AS status;"
Then run it:
bash mysql-reset.sh
It will ask for your sudo password. After it finishes, root has the password you set. Mine is now password, which matches my Laravel .env.
Step 4: Create your database if it does not exist yet
mysql -u root -ppassword -e "CREATE DATABASE IF NOT EXISTS my_app;"
You will see a warning that goes like this:
mysql: [Warning] Using a password on the command line interface can be insecure.
That is just a warning, not an error. Your command still ran. We will fix that warning in the last step.
Now run your migrations:
php artisan migrate
If your tables get created, you are back in business.
Two confusing errors that tripped me up
After the reset I tried a couple of things that looked broken but were actually fine. If you see these, do not panic.
"sudo mysql" stops working
sudo mysql -e "ALTER USER 'root'@'localhost' ..."
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
This is correct now. We changed root from socket login to password login. So sudo mysql cannot just walk in anymore. You have to give the password:
mysql -u root -p
Just typing "mysql" fails
mysql
ERROR 1045 (28000): Access denied for user 'your_username'@'localhost' (using password: NO)
When you run mysql with no flags, it tries to log in using your Linux username with no password. There is no MySQL user with your Linux name, so it fails. This is normal. You need -u root -p.
Step 5: Stop typing your password every time
This was the nicest little win. You can put your client credentials in a config file and the mysql command will read it automatically.
Create ~/.my.cnf:
[client]
user=root
password=password
Lock down the permissions so other users on the machine cannot read it:
chmod 600 ~/.my.cnf
Now this just works:
mysql
No prompt, no flags, no warning. Quick test:
mysql -e "SELECT CURRENT_USER();"
You should see root@localhost.
A safer setup for real projects
Using root for your app is fine on a learning machine, but on anything you care about, make a dedicated user with access to one database only:
CREATE DATABASE IF NOT EXISTS my_app;
CREATE USER 'my_app_user'@'localhost' IDENTIFIED BY 'a_real_password';
GRANT ALL PRIVILEGES ON my_app.* TO 'my_app_user'@'localhost';
FLUSH PRIVILEGES;
Then point your .env at that user. If the app password ever leaks, your other databases are still safe.
Quick recap
- Check the
.envfirst. The simplest fix is usually the right one. - Try
sudo mysql. If it works, you are using socket auth and you can set a password right there. - If root already has a password you do not know, reset it with an init file. Do not edit
mysql.userby hand and do not run with--skip-grant-tablesif you can avoid it. - After the reset, remember that
sudo mysqlwill not work anymore. Usemysql -u root -p. - Drop a
~/.my.cnfwith mode 600 so you can just typemysqland get in. - For real projects, do not use root. Make an app user with access to one database.
Hope this saves someone an hour. Forgetting a database password feels scary, but the recovery is short once you know the steps.
Top comments (0)