How to Allow Remote Connections to MySQL Database Server

By 

Updated on

8 min read

MySQL Remote Connections

By default, the MySQL server listens for connections only from localhost, which means it can be accessed only by applications running on the same host.

However, in some situations, it is necessary to access the MySQL server from a remote location. For example, you may need to connect to the remote MySQL server from your local system or a multi-server deployment where the application is running on a different machine from the database server. One option would be to access the MySQL server through SSH Tunnel , and another is to configure the MySQL server to accept remote connections.

This article goes through the steps necessary to allow remote connections to a MySQL server. The same instructions apply for MariaDB.

Quick Reference

TaskCommand
Edit MySQL config (Ubuntu/Debian)sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Edit MySQL config (RHEL/Fedora)sudo nano /etc/my.cnf
Restart MySQL (Ubuntu/Debian)sudo systemctl restart mysql
Restart MySQL (RHEL/Fedora)sudo systemctl restart mysqld
Create remote userCREATE USER 'user'@'ip' IDENTIFIED BY 'password';
Grant database accessGRANT ALL ON db.* TO 'user'@'ip';
Allow MySQL port (UFW)sudo ufw allow from ip to any port 3306
Test remote connectionmysql -u user_name -h mysql_server_ip -p

For a printable quick reference, see the MySQL and MariaDB cheatsheet .

Configuring MySQL Server

The first step is to set the MySQL server to listen on a specific IP address or all IP addresses on the machine.

If the MySQL server and clients can communicate over a private network, the best option is to set the MySQL server to listen only on the private IP.

Otherwise, if you want to connect to the server over a public network, set the MySQL server to listen on all IP addresses on the machine. To do so, you need to edit the MySQL configuration file and add or change the value of the bind-address option. You can set a single IP address and IP ranges. If the address is 0.0.0.0, the MySQL server accepts connections on all host IPv4 interfaces. If you have IPv6 configured on your system, then instead of 0.0.0.0, use ::.

The location of the MySQL configuration file differs depending on the distribution. In Ubuntu and Debian the file is located at /etc/mysql/mysql.conf.d/mysqld.cnf, while in Fedora, RHEL, and Derivatives, the file is located at /etc/my.cnf.

Open the file with your text editor :

Terminal
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Search for a line that begins with bind-address and set its value to the IP address on which a MySQL server should listen.

By default, the value is set to 127.0.0.1 (listens only in localhost).

In this example, we will set the MySQL server to listen on all IPv4 interfaces by changing the value to 0.0.0.0:

mysqld.cnfini
bind-address           = 0.0.0.0
# skip-networking

If there is a line containing skip-networking, delete it or comment it out by adding # at the beginning of the line.

In MySQL 8.0 and higher, the bind-address directive may not be present. In this case, add it under the [mysqld] section.

Once done, restart the MySQL service for changes to take effect. Only root or users with sudo privileges can restart services.

To restart the MySQL service on Debian or Ubuntu, type:

Terminal
sudo systemctl restart mysql

On Fedora, RHEL, and Derivatives, to restart the service run:

Terminal
sudo systemctl restart mysqld

Granting Access to a User from a Remote Machine

The next step is to allow access to the database to the remote user.

Log in to the MySQL server as the root user by typing:

Terminal
sudo mysql

If you are using the old, native MySQL authentication plugin to log in as root, run the command below and enter the password when prompted:

Terminal
mysql -uroot -p

From inside the MySQL shell, first create the user with a password, then grant access to the database:

Terminal
CREATE USER 'user_name'@'ip_address' IDENTIFIED BY 'user_password';
GRANT ALL ON database_name.* TO 'user_name'@'ip_address';

Where:

  • database_name is the name of the database that the user will connect to.
  • user_name is the name of the MySQL user.
  • ip_address is the IP address from which the user will connect. Use % to allow the user to connect from any IP address.
  • user_password is the user password.

For example, to grant access to a database dbname to a user named foo with password my_passwd from a client machine with IP 10.8.0.5, you would run:

Terminal
CREATE USER 'foo'@'10.8.0.5' IDENTIFIED BY 'my_passwd';
GRANT ALL ON dbname.* TO 'foo'@'10.8.0.5';

Configuring Firewall

The last step is to configure your firewall to allow traffic on port 3306 (MySQL default port) from the remote machines.

Iptables

If you are using iptables cheatsheet as your firewall reference, the command below will allow access from any IP address on the Internet to the MySQL port. This is very insecure.

Terminal
sudo iptables -A INPUT -p tcp --destination-port 3306 -j ACCEPT

Allow access from a specific IP address:

Terminal
sudo iptables -A INPUT -s 10.8.0.5 -p tcp --destination-port 3306 -j ACCEPT

UFW

UFW cheatsheet is the default firewall tool in Ubuntu. To allow access from any IP address on the Internet (very insecure), run:

Terminal
sudo ufw allow 3306/tcp

Allow access from a specific IP address:

Terminal
sudo ufw allow from 10.8.0.5 to any port 3306

FirewallD

FirewallD is the default firewall management tool on Fedora, RHEL, and Derivatives. To allow access from any IP address on the Internet (very insecure) type:

Terminal
sudo firewall-cmd --permanent --zone=public --add-port=3306/tcp
sudo firewall-cmd --reload

To allow access from a specific IP address on a specific port, you can either create a new FirewallD zone or use a rich rule. We will create a new zone named mysqlzone:

Terminal
sudo firewall-cmd --new-zone=mysqlzone --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --zone=mysqlzone --add-source=10.8.0.5/32
sudo firewall-cmd --permanent --zone=mysqlzone --add-port=3306/tcp
sudo firewall-cmd --reload

Verifying the Changes

To verify that the remote user can connect to the MySQL server, run the following command:

Terminal
mysql -u user_name -h mysql_server_ip -p

Where user_name is the name of the user you granted access to, and mysql_server_ip is the IP address of the host where the MySQL server runs.

If everything is set up correctly, you will be able to log in to the remote MySQL server.

If you get an error like below, then either port 3306 is not open , or the MySQL server is not listening on the IP address .

output
ERROR 2003 (HY000): Can't connect to MySQL server on '10.8.0.5' (111)

The error below indicates that the user you are trying to log in with does not have permission to access the remote MySQL server.

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

Troubleshooting

ERROR 2003: Can’t connect to MySQL server
Port 3306 is not reachable. Check that the MySQL service is running (sudo systemctl status mysql), confirm bind-address is not set to 127.0.0.1, and verify your firewall rule allows traffic on port 3306 from the client IP.

ERROR 1130: Host is not allowed to connect
The user does not have a grant for that host. Log in locally and run SELECT host, user FROM mysql.user; to confirm the user exists with the correct host entry. Re-run GRANT ALL ON db.* TO 'user'@'ip'; if it is missing.

ERROR 1045: Access denied for user
The password is wrong or the user account does not exist for that host. Verify with SELECT host, user FROM mysql.user; and reset the password with ALTER USER 'user'@'ip' IDENTIFIED BY 'new_password';.

MySQL still only listens on 127.0.0.1 after config change
Confirm the bind-address line is under the [mysqld] section and that you restarted the service. Check the active listening address with ss -tlnp | grep 3306.

FAQ

Does this work with MariaDB?
Yes. MariaDB uses the same bind-address directive and GRANT syntax. The config file location and service name may differ slightly by distribution.

Can I allow a user to connect from any IP address?
Yes. Use % as the host in the CREATE USER and GRANT statements: CREATE USER 'user'@'%' IDENTIFIED BY 'password';. This is convenient but reduces security — restrict to a specific IP whenever possible.

Is there a safer alternative to opening port 3306 publicly?
Yes. Use an SSH tunnel to forward the MySQL port over an encrypted SSH connection without exposing port 3306 at all.

What does bind-address = 0.0.0.0 mean in MySQL?
It tells MySQL to listen on all available IPv4 interfaces instead of only 127.0.0.1. This allows remote clients to connect, but only if the firewall and user grants also permit access.

What is the default MySQL port?
MySQL listens on TCP port 3306 by default. You can change it with the port directive in mysqld.cnf.

Conclusion

MySQL by default listens for incoming connections only on localhost. To allow remote connections, you need to update the bind-address in the MySQL configuration, create a user account with the correct host grant, and open port 3306 in your firewall.

For a more secure alternative that avoids exposing the MySQL port entirely, consider using an SSH tunnel instead.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page