MySQL "Host Is Not Allowed to Connect to This MySQL Server" (ERROR 1130) vs "Can't Connect to MySQL Server" (2003): Remote Access on EC2 and RDS
ERROR 1130 (HY000): Host '10.89.1.12' is not allowed to connect to this MySQL server means MySQL received your connection and refused it because no account on the server allows connections from your address. Every MySQL account is a user name and a host, such as 'app'@'localhost', and an account for localhost doesn't cover a connection from another server. The fix is to create the account for the right host, for example CREATE USER 'app'@'%' IDENTIFIED BY '...'; followed by a GRANT. It's a different problem from ERROR 2003 "Can't connect to MySQL server", which means the connection never reached MySQL at all: (111) is refused, usually MySQL listening only on 127.0.0.1 or a wrong port, and (110) is a timeout, usually a security group on AWS. Here's the twist that confuses everyone: the error you get depends on other users' accounts, so the same login can produce 1130 today and "Access denied" (1045) tomorrow without anything changing for that user. This page decodes every variant, shows the MySQL 8 commands that replace the old GRANT ... IDENTIFIED BY answers, and covers EC2 and RDS.
Ethan, a developer, moved the booking app for his friend Jake's phone repair shop to its own EC2 server, with MySQL on a second one. The app's first connection failed with ERROR 1130. Ethan copied a fix from an old forum answer, and MySQL rejected that with a syntax error.
New to these terms? An EC2 instance is a server you rent, and a security group is its firewall. MySQL has a second gate of its own: its accounts, each tied to where the user connects from.
Which error, which layer
A remote MySQL connection passes three gates: the network, MySQL's listener, and MySQL's accounts. Each error tells you which one stopped it. These are the real messages from a MySQL 8.4 server and a client on another machine:
| Error | Gate | Meaning |
|---|---|---|
| ERROR 2003 ... (110) | Network | Timed out: nothing answered, often a security group or firewall dropping packets |
| ERROR 2003 ... (111) | Listener | Refused: the machine answered, but nothing listens on that address and port |
| ERROR 1130 Host '...' is not allowed | Accounts | MySQL answered, and no account at all matches your host |
| ERROR 1045 Access denied for user 'app'@'10.89.1.5' | Accounts | Some account matches your host, but not this user name and password |
Work from the top: there's no point creating users while packets are being dropped, and no point opening firewalls when MySQL is already answering with 1130.
Why 1130 happens: accounts have a host
On a default MySQL install, every account belongs to localhost:
SELECT user, host FROM mysql.user ORDER BY user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| app | localhost |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
A connection from another server finds no account for its address, so MySQL refuses it before even looking at the user name. That applies to every user, root included:
ERROR 1130 (HY000): Host '10.89.1.12' is not allowed to connect to this MySQL server
Now the twist. Create one account that allows remote connections, 'app'@'%', and try root from the same remote machine again. The answer changes:
ERROR 1045 (28000): Access denied for user 'root'@'10.89.1.15' (using password: YES)
MySQL now has an account that matches the host, so it moves on to the user name, finds no root account for remote hosts, and reports "Access denied" instead. The root account didn't change at all. That's why answers that say "1130 means X" and "1045 means Y" seem to contradict each other: the message depends on every account on the server.
Jake: "So the guard turns away anyone from our street, until one person from our street gets on the list?"
Ethan: "Then he checks names. Same door, different excuse."
Fix 1130: create the account for the right host
Create the user for the host it connects from, then grant it what it needs. % means any host:
CREATE USER 'app'@'%' IDENTIFIED BY 'App-pass-123';
GRANT ALL PRIVILEGES ON shop.* TO 'app'@'%';
That's enough; MySQL 8 applies it immediately, without FLUSH PRIVILEGES. The connection from the app server now works:
SELECT CURRENT_USER();
app@%
On AWS, a narrower host pattern is better than %, because the account then only works from your own network:
| Host part | Allows connections from |
|---|---|
'%' | Anywhere the network lets through |
'10.0.%' | Any address starting 10.0., such as a VPC's range |
'10.0.1.25' | One server's private IP address |
'localhost' | Only the database server itself |
A read-only account limited to one subnet, for example:
CREATE USER 'report'@'10.89.%' IDENTIFIED BY 'Rep-pass-123';
GRANT SELECT ON shop.* TO 'report'@'10.89.%';
A user name with two hosts is two separate accounts, with separate passwords and grants: 'app'@'localhost' and 'app'@'%' don't share anything.
Why the old answers fail on MySQL 8: 1064 and 1410
Most answers you'll find for ERROR 1130 were written for MySQL 5.7, where one GRANT statement created the user and set its password at once. On MySQL 8, that statement is a syntax error:
GRANT ALL PRIVILEGES ON *.* TO 'app'@'%' IDENTIFIED BY 'App-pass-123';
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY 'App-pass-123'' at line 1
Dropping the password part doesn't help either, because GRANT no longer creates users at all:
ERROR 1410 (42000) at line 1: You are not allowed to create a user with GRANT
The MySQL 8 way is always two statements, CREATE USER and then GRANT, as above. And notice what the old answer granted: ALL PRIVILEGES ON *.*, every database on the server. An application needs its own database, shop.*, and nothing more.
ERROR 2003 (111): connection refused
When the connection is refused, MySQL never saw it. Two common causes, both shown by these real messages:
ERROR 2003 (HY000): Can't connect to MySQL server on 'dblocal:3306' (111)
ERROR 2003 (HY000): Can't connect to MySQL server on 'dbhost:3307' (111)
The first server listens only on 127.0.0.1, so it accepts connections from itself alone; the second connection used the wrong port. Check what the server listens on:
SELECT @@bind_address, @@port;
* means all addresses, and 127.0.0.1 means local connections only. To accept remote connections, set bind-address = 0.0.0.0, or the server's private IP address, in the [mysqld] section of the server's configuration file, and restart MySQL. Then the security group decides who can actually reach it, which is the next gate.
ERROR 2003 (110): timed out, usually a security group
A timeout means nothing answered at all, and the client waited until it gave up:
ERROR 2003 (HY000): Can't connect to MySQL server on '10.255.255.1:3306' (110)
On AWS, the usual cause is a security group that doesn't allow port 3306 from the client. Security groups drop blocked traffic silently, so you get a timeout rather than a refusal. Add an inbound rule on the database server's security group for TCP port 3306, with the app server's security group as the source rather than an IP range. Then the rule follows the app servers wherever they are, and nothing else can connect. Other causes of timeouts are network ACLs, a missing route between VPCs, or connecting to a private address from outside the VPC; our security groups vs network ACLs guide covers the difference.
Never open port 3306 to 0.0.0.0/0. Databases exposed to the internet are scanned constantly, and the account host patterns above are only a second line of defense.
Test each gate from the app server
Before you change anything, find out which gate is closed, from the server that needs to connect. Bash can test a TCP port without installing anything:
timeout 5 bash -c '</dev/tcp/10.0.1.25/3306' && echo open
Replace the address with your database server's. The result points straight at the gate:
open: the network and listener are fine; any error now comes from MySQL's accounts, so look at 1130 or 1045.Connection refused: the machine answered, but nothing listens on that port; checkbind_addressand the port number.- No output after five seconds, exit code 124: something drops the traffic; check the security group, network ACLs and routes.
- Once the port test says
open, connect with themysqlclient and runSELECT CURRENT_USER();to see which account you matched. - Only then start the application, so its own errors aren't confused with the setup's.
Jake: "So you knock first, before you argue with the guard?"
Ethan: "If nobody opens, it's the road. If someone opens and says no, it's the list. Different fixes."
MySQL on EC2: the remote access checklist
For a MySQL server on one EC2 instance and an app on another, set it up in this order:
- Allow TCP 3306 into the database server's security group from the app server's security group.
- Check
SELECT @@bind_address;on the database server, and changebind-addressif it says127.0.0.1. - Create the app's account for the app's host pattern with
CREATE USER, andGRANTit its own database only. - Connect from the app server with the
mysqlclient before you deploy the app, and runSELECT CURRENT_USER();. - Keep the password in Secrets Manager, not in the app's code.
On Amazon RDS, steps 2 and 3 work differently: RDS manages the listener, and the master user you created with the database can connect from your network. So on RDS, connection problems are almost always network problems, ERROR 2003 with a timeout, and our RDS connection guide goes through them. Accounts you create yourself on RDS still need the right host part, exactly as on EC2.
Troubleshooting by symptom
ERROR 1130: Host is not allowed to connect to this MySQL server
No account matches your host. Create one for it: CREATE USER 'app'@'%' (or your network's pattern), then GRANT.
ERROR 1064 near IDENTIFIED BY in a GRANT
MySQL 8 removed GRANT ... IDENTIFIED BY. Run CREATE USER first, then GRANT without a password.
ERROR 1410: You are not allowed to create a user with GRANT
The account in the GRANT doesn't exist. Create it with CREATE USER, including the same host part.
ERROR 2003 Can't connect to MySQL server (111)
Refused: MySQL isn't listening on that address or port. Check @@bind_address and @@port.
ERROR 2003 Can't connect to MySQL server (110)
Timed out: a security group, network ACL or route blocks the traffic. Allow port 3306 from the client's security group.
ERROR 1045 Access denied after fixing 1130
Your host is now allowed, but this user name or password isn't. Check the account for that exact user and host.
MySQL remote access: frequently asked questions
What does Host is not allowed to connect to this MySQL server mean?
MySQL received the connection, but no account on the server allows connections from your address.
How do I fix ERROR 1130 in MySQL 8?
Run CREATE USER 'app'@'%' IDENTIFIED BY 'password'; then GRANT the privileges it needs on its database.
Why does GRANT ... IDENTIFIED BY give a syntax error?
MySQL 8 removed that form. Create the user with CREATE USER, then GRANT separately.
What does ERROR 1410 You are not allowed to create a user with GRANT mean?
GRANT no longer creates users in MySQL 8. Create the account first with CREATE USER.
What is the difference between ERROR 1130 and ERROR 1045?
1130 means no account matches your host. 1045 means some account matches your host, but not your user name or password.
What does ERROR 2003 Can't connect to MySQL server mean?
The connection never reached MySQL. (111) means refused; (110) means timed out.
What does the % mean in 'app'@'%'?
Any host. Use a narrower pattern, such as '10.0.%', to allow only your network.
How do I allow remote connections to MySQL on EC2?
Open port 3306 from the app's security group, make MySQL listen on all addresses, and create the account for the app's host.
How do I check MySQL's bind address?
Run SELECT @@bind_address. 127.0.0.1 means it only accepts local connections.
Do I need FLUSH PRIVILEGES after CREATE USER?
No. CREATE USER and GRANT take effect immediately. FLUSH PRIVILEGES is only for direct edits to the grant tables.
Why does my RDS MySQL connection time out?
Usually the security group or network: allow port 3306 from your client, and check the instance's public accessibility.
Should I open port 3306 to 0.0.0.0/0?
No. Allow it only from your app servers' security group, or from your own network.
Can root connect remotely to MySQL?
Only if a root account exists for a remote host. Default installs have root@localhost only, which is safer.
Are 'app'@'localhost' and 'app'@'%' the same user?
No. They are separate accounts with separate passwords and privileges.
How do I see which hosts a MySQL user can connect from?
Run SELECT user, host FROM mysql.user WHERE user = 'app';
Why did my 1130 error change to 1045?
Someone created an account for your host. MySQL now checks the user name and password and reports 1045 instead.
Ethan created 'app'@'10.0.%' with CREATE USER, granted it the shop's database and nothing else, and allowed port 3306 only from the app server's security group. The booking app connected on the next try. Jake asked why the copied answer had failed. "It was written for an older MySQL," Ethan said. "The idea was right; the grammar had changed."
📌 If you keep one line from this page
ERROR 1130 means no account matches your host: CREATE USER for the right host, then GRANT; ERROR 2003 means the network or listener, so check the security group and bind_address first.
1130 = host · 1045 = user/password · 2003 (111) = refused · 2003 (110) = timed out · no IDENTIFIED BY in GRANT.
Revision note. Written October 13, 2026, for MySQL 8.4 and 8.0 on Amazon EC2 and Amazon RDS. "Knock and the door shall be opened," says the old line; with MySQL, knock from an address it knows.