Skip to content
ohsudo, Home
Databases

MySQL "ERROR 1130: Host is not allowed to connect": an account is a user and a host

Fix MySQL ERROR 1130 "Host is not allowed to connect to this MySQL server": see which accounts exist, create one for the right host and grant it access, without root.

Beginner4 min readApplies to MySQL 5.7+ · MySQL 8.x · MariaDB 10.x · Docker

by OhSudo ··

Not sure this is your cause?Find it step by step: Can't connect to the database →

ERROR 1130 (HY000): Host '10.0.0.20' is not allowed to connect to this MySQL server

Good news first: the network is fine. You reached MySQL, and it answered. It’s refusing you because no account matches the address you came from.

In MySQL, an account isn’t only a name, but a name and a host. 'app'@'localhost' and 'app'@'10.0.0.20' are two separate accounts, with their own passwords and rights. This error means that for 10.0.0.20, there isn’t any account at all, whichever user you gave.

  1. Client at 10.0.0.20reaches MySQL(works)
  2. Accounts'app'@'localhost' only
  3. No match for that hostERROR 1130(breaks here)
The network is fine: you reached MySQL. No account exists for the address you came from, whichever user you send.

TL;DR

On the server, as an admin:

SELECT user, host, plugin FROM mysql.user;
CREATE USER 'app'@'10.0.0.20' IDENTIFIED BY 'new-password-here';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'10.0.0.20';

No restart is needed, and no FLUSH PRIVILEGES either.

1. Look at the accounts

Get in locally, where you do have an account:

Terminal window
sudo mysql
SELECT user, host FROM mysql.user ORDER BY user, host;
+------------------+-----------+
| user | host |
+------------------+-----------+
| app | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+

So app can only log in from the server itself. The address in your error is what MySQL sees, which is worth checking. Behind a NAT, a load balancer or in Docker, it may not be the address you expected.

2. Create an account for that host

Use an account for the application, not root:

CREATE USER 'app'@'10.0.0.20' IDENTIFIED BY 'new-password-here';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'10.0.0.20';

The Password Generator gives you a strong password, with a shell-safe option that won’t need escaping in a config file.

The host can also be a range, with % as a wildcard:

Host Allows
'10.0.0.20' That one machine
'10.0.0.%' A private subnet
'%.example.internal' Machines by name, which relies on reverse DNS
'%' Anywhere

Prefer the narrowest that works. To see what an account can do:

SHOW GRANTS FOR 'app'@'10.0.0.20';

Old guides show GRANT ... IDENTIFIED BY. That creates a user in one step, and it was removed in MySQL 8, where it gives a syntax error. Use two statements, as above.

3. Test it

From the machine that’s connecting:

Terminal window
mysql -h 10.0.0.5 -u app -p shop

If you now get ERROR 1045: Access denied, then the account exists and the password doesn’t match: see MySQL error 1045. That’s progress.

4. Docker

Here the problem has a twist. The host MySQL sees is the container’s or bridge’s address, such as 172.18.0.3, and it can change whenever the container is recreated. The official image handles this if you let it create the user, as it uses '%':

services:
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: shop
MYSQL_USER: app
MYSQL_PASSWORD: ${DB_PASSWORD}

Those variables only work the first time, on an empty data folder. If the volume already exists, changing them does nothing, and that’s a common cause of confusion. Either create the account by hand as in section 2, or remove the volume if there’s nothing to keep.

Don’t publish the database’s port for other containers: they connect by name. See connecting to localhost from a container.

5. Name lookups

Host 'ip-10-0-0-20.ec2.internal' is not allowed means MySQL looked up a name for your address, and matched on that. Slow connections can come from those lookups as well. To use addresses only, set this, and then accounts must use addresses too:

[mysqld]
skip_name_resolve = ON

It’s a good setting, and it needs a restart, so check your accounts first, as any account with a name for a host stops matching.

6. Too many failed attempts

A similar error appears after many broken connections:

ERROR 1129 (HY000): Host '10.0.0.20' is blocked because of many connection errors

That’s a different thing, with a different fix:

TRUNCATE TABLE performance_schema.host_cache;

Or mysqladmin flush-hosts. Then find out what keeps failing, as it’s often a health check that connects and drops.

Warning

Don’t answer this with CREATE USER 'root'@'%', as many guides do. That lets anyone reaching port 3306 try to guess your most powerful password, and bots try constantly. Create an account per application, from a specific address, with the rights it needs. The Port Lookup explains why 3306 shouldn’t be public. To compare the syntax on other databases, see the SQL Dialect Reference.

Shell, we have a problem!

Similar, but different: ERROR 1045 means the account exists, with another password. ERROR 2003 means you never reached the server. ERROR 2002 is the local socket. ERROR 1044: Access denied for user to database means you logged in, without rights to that database.

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles