Remote MySQL connections let an application on one server connect to a MySQL database on a different server. This is common when your website runs on one machine but needs to reach a database hosted elsewhere, or when a local development tool needs to query a production or staging database directly.
By default, MySQL only listens for connections from
localhost
. Allowing remote connections requires changes to the MySQL configuration, user permissions, and firewall rules. Each step has security implications, and skipping any one of them means the connection either will not work or will work but leave your database exposed.
This guide walks through the full setup, the security risks at each step, and how managed hosting platforms handle this differently.
Why MySQL blocks remote connections by default
MySQL ships with a conservative default: it only accepts connections from the machine it is running on. This is intentional. A database that accepts connections from anywhere on the internet is an attack surface. Brute force login attempts, credential stuffing, and SQL injection exploits all become directly reachable if MySQL is exposed to the network.
The default
bind-address
is set to
127.0.0.1
, which means MySQL only listens on the loopback interface. No amount of correct usernames and passwords will establish a connection from another machine unless this setting is changed, the MySQL user is granted permission to connect from that IP, and the firewall allows traffic on port 3306.
These three layers – network binding, user authentication, and firewall rules – work together. Each one independently blocks unauthorized access, and a properly secured remote MySQL setup has all three configured correctly.
Step 1: Change the bind-address
The
bind-address
directive in MySQL’s configuration file controls which network interface MySQL listens on. By default, it is set to
127.0.0.1
, restricting MySQL to local connections only.
To allow remote connections, edit the MySQL configuration file. On most Linux distributions, this is at
/etc/my.cnf
or
/etc/mysql/my.cnf
, or a file within
/etc/my.cnf.d/
:
[mysqld]
bind-address = 0.0.0.0
Setting
bind-address
to
0.0.0.0
tells MySQL to listen on all available network interfaces. This means MySQL will accept connection attempts from any IP address, which is why the next two steps – user grants and firewall rules – are critical.
If you only need connections from a single known IP, you can bind to that specific network interface instead of
0.0.0.0
, but in most practical setups the filtering is handled at the firewall and user permission level rather than the bind address.
After changing the configuration, restart MySQL:
sudo systemctl restart mysqld
Verify MySQL is listening on the correct address:
ss -tlnp | grep 3306
You should see MySQL listening on
0.0.0.0:3306
instead of
127.0.0.1:3306
.
A note on skip-networking
Older MySQL configurations sometimes include
skip-networking
, which disables TCP/IP connections entirely and forces MySQL to use only Unix socket connections. If this directive is present, remove or comment it out. MySQL cannot accept any network connections – local or remote – while
skip-networking
is enabled.
Step 2: Create a MySQL user with remote access
MySQL user accounts include a host component. The user
admin@localhost
and the user
admin@203.0.113.50
are two different accounts with separate passwords and privileges, even though they share a username.
To create a user that can connect from a specific remote IP:
CREATE USER 'app_user'@'203.0.113.50' IDENTIFIED BY 'strong_password_here';
GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'app_user'@'203.0.113.50';
FLUSH PRIVILEGES;
The host part of the user definition is where security starts. Some important considerations:
Never use the wildcard host
-- Do NOT do this in production
CREATE USER 'app_user'@'%' IDENTIFIED BY 'password';
The
%
wildcard allows connections from any IP address. This means anyone who obtains or guesses the credentials can connect from anywhere. Combined with
bind-address = 0.0.0.0
, this effectively opens your database to the entire internet.
If you need access from multiple IPs, create separate user entries for each IP, or use subnet notation if your MySQL version supports it. The minor inconvenience of managing multiple user entries is worth the security benefit.
Grant minimum necessary privileges
Do not grant
ALL PRIVILEGES
to remote users. Grant only the specific privileges the application needs:
-- For a read-only reporting tool
GRANT SELECT ON your_database.* TO 'reporting_user'@'203.0.113.50';
-- For an application that reads and writes
GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'app_user'@'203.0.113.50';
Avoid granting
DROP
,
ALTER
,
CREATE
, or administrative privileges to remote users unless absolutely necessary. If the credentials are compromised, the damage is limited to what the grants allow.
Require SSL for remote users
Remote connections travel over the network, which means they can be intercepted. MySQL supports SSL/TLS encryption for client connections, and you can require it per user:
CREATE USER 'app_user'@'203.0.113.50' IDENTIFIED BY 'strong_password_here' REQUIRE SSL;
With
REQUIRE SSL
, MySQL will reject any connection attempt from this user that does not use an encrypted connection. This prevents credentials and query data from being transmitted in plain text across the network.
To connect with SSL from the mysql client:
mysql -h your_server_ip -u app_user -p --ssl-mode=REQUIRED
Most modern MySQL client libraries support SSL. The MySQL Connector for Python, PHP’s PDO and MySQLi, and Node.js mysql2 all support SSL connections with configuration options for certificate verification. Note that MySQL 8.0 changed the default authentication plugin to `caching_sha2_password`, which can affect remote connections from older client libraries – see MySQL vs MariaDB: which should you use for details on authentication differences between versions.
Step 3: Configure the firewall
Even with MySQL listening on all interfaces and a user granted remote access, the connection will fail if the server’s firewall blocks port 3306. This is a good thing – the firewall is your last line of defense if MySQL’s user permissions are misconfigured.
firewalld (Rocky Linux, AlmaLinux, RHEL, CentOS)
Most RHEL-based distributions use firewalld. Rather than opening port 3306 to all traffic, create a rich rule that restricts access to specific IPs:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.50" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload
This allows MySQL connections only from
203.0.113.50
. All other IPs are still blocked at the firewall level, regardless of MySQL’s bind-address or user permissions.
To allow a subnet:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload
ufw (Ubuntu, Debian)
sudo ufw allow from 203.0.113.50 to any port 3306
sudo ufw reload
iptables
sudo iptables -A INPUT -p tcp -s 203.0.113.50 --dport 3306 -j ACCEPT
Cloud provider firewalls
If your server runs on a cloud provider (DigitalOcean, Linode, AWS, etc.), the cloud provider’s firewall operates separately from the OS-level firewall. You need to allow port 3306 in both the cloud firewall and the server firewall for the connection to work.
On AWS, this means adding an inbound rule to the security group. On DigitalOcean and Linode, it means updating the cloud firewall attached to your droplet or Linode instance. In all cases, restrict the source IP rather than opening port 3306 to
0.0.0.0/0
.
Step 4: Test the connection
From the remote machine, test the connection:
mysql -h your_server_ip -u app_user -p --ssl-mode=REQUIRED
If the connection fails, troubleshoot in order:
- Network reachability: Can you reach port 3306 at all?
telnet your_server_ip 3306ornc -zv your_server_ip 3306will tell you if the port is open. If it is not, the issue is the firewall or bind-address. - MySQL listening: Is MySQL listening on the correct address? Check with
ss -tlnp | grep 3306on the server. - User permissions: Does the MySQL user exist with the correct host? Run
SELECT user, host FROM mysql.user WHERE user = 'app_user';on the server. - SSL requirement: If you created the user with
REQUIRE SSL, make sure your client is connecting with SSL enabled.
Common use cases for remote MySQL
Local development connecting to a staging database
Developers often need to query a staging database from their local machine for debugging or data analysis. Rather than copying database dumps back and forth, a remote MySQL connection lets you query the data directly.
Create a dedicated read-only user for this purpose with access limited to your office or VPN IP. Do not reuse the application’s database credentials for developer access. Be aware that remote connections are more susceptible to timeout-related disconnections than local ones – if you encounter dropped connections during long-running queries, see MySQL server has gone away: what it means and how to fix it for diagnosis steps.
A separate application server
In some architectures, the web server and database server are separate machines. The application server connects to the database server over the internal network. In this case, create the MySQL user with the application server’s private IP address (not its public IP) and configure the firewall rule on the internal network interface.
Using private network connections between application and database servers avoids exposing port 3306 to the public internet entirely.
Connecting from a content management tool
Databases management tools like DBeaver, MySQL Workbench, TablePlus, or HeidiSQL can connect to a remote MySQL database for administration. These tools support SSL and SSH tunnel connections, both of which add security layers beyond a direct connection.
An SSH tunnel is often preferable for administrative access because it does not require opening port 3306 in the firewall at all:
ssh -L 3306:127.0.0.1:3306 user@your_server_ip
This tunnels your local port 3306 through SSH to the server’s localhost MySQL. You connect your database tool to
127.0.0.1:3306
on your local machine, and the traffic travels encrypted through the SSH connection.
External analytics or reporting
Business intelligence tools, data warehouses, or third-party analytics services sometimes need direct database access for reporting. These connections should be read-only, IP-restricted, and SSL-encrypted. Consider whether a database replica or a read-only endpoint would be more appropriate than granting access to the primary database.
Security considerations
Exposing MySQL to remote connections increases the attack surface of your server. Every additional network-accessible service is a potential target.
Brute force attacks
Once port 3306 is reachable from the internet, automated scanners will find it and attempt to log in with common credentials. IP-restricted firewall rules prevent this entirely for IPs not on the allow list. For allowed IPs, strong passwords are essential. MySQL supports account locking after failed attempts (MySQL 8.0+):
CREATE USER 'app_user'@'203.0.113.50'
IDENTIFIED BY 'strong_password_here'
FAILED_LOGIN_ATTEMPTS 5
PASSWORD_LOCK_TIME 2;
Credential exposure
If your application’s database credentials are stored in a configuration file, environment variable, or secrets manager, treat them with the same care as SSH keys. Remote MySQL credentials are more dangerous than local-only credentials because they can be used from anywhere the user’s host permission allows.
Encrypted connections
Unencrypted MySQL connections transmit queries and results in plain text. On a local network this risk is limited but not zero. Over the public internet, it is a real concern. Always require SSL for remote users and verify that the connection is actually encrypted:
-- Run this after connecting to verify encryption
SHOW STATUS LIKE 'Ssl_cipher';
If the result is empty, the connection is not encrypted.
Audit and monitoring
Enable MySQL’s general query log or audit log plugin for remote user activity if your security requirements call for it. At minimum, monitor the MySQL error log for failed connection attempts from unexpected IP addresses.
How managed hosting handles remote MySQL
On managed hosting platforms, you typically do not have direct access to the MySQL configuration file or the server firewall. The provider handles the infrastructure layer, and remote MySQL access is managed through a control panel.
The general approach on managed hosting is:
- You request remote MySQL access through the hosting dashboard
- The platform creates a dedicated external database user
- You specify which IP addresses are allowed to connect
- The platform configures the firewall and MySQL user grants automatically
This abstraction removes the need to edit configuration files or manage firewall rules manually, and it reduces the risk of misconfiguration.
How it works on Hostney
Hostney’s control panel has a dedicated external MySQL user feature under the MySQL manager. Rather than modifying the server’s MySQL configuration yourself, the platform handles the full setup:
Creating an external user: You create a dedicated external MySQL user from the control panel. The platform generates a username and a strong password automatically. You provide a label (so you remember what the user is for) and specify the IP addresses allowed to connect.
IP restrictions: Each external user has an explicit list of allowed IP addresses. The platform validates these and rejects wildcards, localhost addresses, and overly broad ranges. You can allow individual IPs or a limited CIDR range (minimum /24 for IPv4). If your IP changes, you update the allowed IPs through the control panel and the platform reconfigures both the MySQL user grants and the firewall rules automatically.
SSL enforcement: All external MySQL users are created with
REQUIRE SSL
by default. There is no option to create an unencrypted external user. This means every remote connection to a Hostney database is encrypted in transit, regardless of whether the connecting application explicitly requests SSL.
Firewall automation: When you add an IP to an external user, the platform creates a firewall rule on the server that allows MySQL traffic (port 3306) from that specific IP. When you remove an IP, the rule is removed. You do not need to manage firewall rules manually, and port 3306 is never opened broadly.
Database-level grants: After creating an external user, you assign it to specific databases with specific privileges. The platform applies the grants per-IP, so each allowed IP gets its own MySQL user entry with the correct permissions. This follows the same principle as the manual setup described above – per-IP user entries rather than wildcard hosts.
Updating and cleanup: You can change the external user’s password, update allowed IPs, or delete the user entirely from the control panel. When you delete an external user, the platform drops all associated MySQL user entries, removes the firewall rules, and cleans up metadata. No manual server access is needed.
This approach gives you the functionality of remote MySQL without the operational overhead of managing bind-address settings, firewall rules, and MySQL user grants across multiple servers. The security defaults – mandatory SSL, IP whitelisting, no wildcard hosts – are enforced by the platform rather than relying on the user to configure them correctly.
When not to allow remote MySQL connections
Not every scenario requires a direct database connection. Consider these alternatives:
API layer: If a remote application needs to read or write data, building a REST API in front of the database gives you better access control, rate limiting, and the ability to change the database schema without breaking external consumers.
Database replication: If you need a copy of the data on another server for reporting or redundancy, MySQL replication is more robust than querying the primary database remotely.
SSH tunnels for admin access: If you only need occasional access for database administration, an SSH tunnel avoids opening port 3306 entirely. This is better for ad-hoc access than a permanent firewall rule.
Scheduled exports: If a third-party service needs periodic data, consider exporting the data on a schedule rather than giving it live database access.
Direct remote MySQL connections are the right choice when your application architecture requires real-time database access from another server and the alternatives add unnecessary complexity. For everything else, consider whether a less exposed approach would work.
Summary
Allowing remote MySQL connections requires three coordinated changes: setting
bind-address
to accept network connections, creating MySQL users with specific remote host permissions, and opening port 3306 in the firewall for authorized IPs only.
Each layer serves a security purpose. The bind-address controls whether MySQL listens on the network at all. User grants control who can authenticate and what they can do. Firewall rules control which IPs can even reach the port. Skipping any one of these either blocks the connection or leaves the database exposed.
For self-managed servers, the setup is straightforward but requires careful attention to each step. Use per-IP user entries instead of wildcard hosts, require SSL for all remote users, grant minimum necessary privileges, and restrict firewall rules to specific source IPs.
On managed hosting platforms like Hostney, the same security principles apply but the platform automates the implementation. External users are created with mandatory SSL, IP-restricted firewall rules, and per-database privilege grants – removing the risk of misconfiguration while giving you the same remote access functionality.