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.
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 serverGood 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.
- Client at 10.0.0.20reaches MySQL(works)looked up in
- Accounts'app'@'localhost' onlyno account for 10.0.0.20(fails)
- No match for that hostERROR 1130(breaks here)
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:
sudo mysql+------------------+-----------+| 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:
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:
mysql -h 10.0.0.5 -u app -p shopIf 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 = ONIt’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 errorsThat’s a different thing, with a different fix:
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.