Desktop clients such as MySQL Workbench, HeidiSQL and DBeaver make it easy to browse tables, run queries and export data. The safe way to connect them to a VPS is through an SSH tunnel: the client logs in over SSH, then talks to MySQL on the server's own 127.0.0.1. Port 3306 stays closed to the internet, and all traffic is encrypted by SSH.
Before you start
- A Linux VPS running MySQL or MariaDB, listening on
127.0.0.1(the default on most installs). - SSH access to the VPS. Key-based login is strongly recommended; see Set up SSH keys.
- Your server's IP address, from your VPS provider's control panel. This guide uses
203.0.113.10and the SSH userdeploy. - A MySQL account for the client. Do not use
rootfor day-to-day work.
Why not open port 3306?
Opening 3306 lets anyone on the internet try passwords against your database. Bots scan for it all the time. With a tunnel, only people who can log in over SSH can reach MySQL at all. Check that MySQL is bound to localhost only:
sudo ss -tlnp | grep -E '3306|mysqld|mariadbd'You want to see 127.0.0.1:3306. If it shows 0.0.0.0:3306 or *:3306, set bind-address = 127.0.0.1 in the server's config file and restart MySQL. Keep 3306 closed in your firewall either way.
Create a MySQL user for the client
Log in on the server with sudo mysql (or mysql -u root -p) and create an account that connects from the local machine. Choose your own strong password; the one below is only a placeholder:
CREATE USER 'dbadmin'@'localhost' IDENTIFIED BY 'REPLACE_WITH_YOUR_OWN_PASSWORD';
CREATE USER 'dbadmin'@'127.0.0.1' IDENTIFIED BY 'REPLACE_WITH_YOUR_OWN_PASSWORD';
GRANT ALL PRIVILEGES ON shop.* TO 'dbadmin'@'localhost';
GRANT ALL PRIVILEGES ON shop.* TO 'dbadmin'@'127.0.0.1';Both host entries are created because a tunnelled connection arrives over TCP at 127.0.0.1, and depending on server settings MySQL may match it as either name. Limit the grants to the databases you actually need. For more on permissions, see Create MySQL users and grant privileges.
MySQL Workbench
- Open Workbench and click + next to MySQL Connections.
- Set Connection Method to Standard TCP/IP over SSH.
- Fill in the SSH fields:
- SSH Hostname:
203.0.113.10:22(use your SSH port if you changed it) - SSH Username:
deploy - SSH Key File: your private key, for example
C:\Users\you\.ssh\id_ed25519
- Fill in the MySQL fields:
- MySQL Hostname:
127.0.0.1 - MySQL Server Port:
3306 - Username:
dbadmin
- Click Test Connection, enter the MySQL password when asked, and save.
Workbench is built for MySQL. It can connect to MariaDB but may show a compatibility warning, and some features may not work.
HeidiSQL (Windows)
- Click New in the Session manager.
- Set Network type to MariaDB or MySQL (SSH tunnel).
- On the Settings tab, set Hostname / IP to
127.0.0.1, User todbadmin, the password, and Port3306. - On the SSH tunnel tab:
- SSH executable:
plink.exe(from PuTTY) or the Windows OpenSSHssh.exe, depending on what your HeidiSQL version offers. - SSH host + port:
203.0.113.10and22. - Username:
deploy. - Private key file: your key. plink needs a
.ppkkey;ssh.exeuses a normal OpenSSH key. - Local port: any free port, such as
3307.
- Click Open.
DBeaver
- Click New Database Connection and choose MySQL or MariaDB.
- On the Main tab, set Server Host to
127.0.0.1, Port to3306, and enter the username and password. - Open the SSH tab and tick Use SSH Tunnel.
- Set Host/IP to
203.0.113.10, Port to22, User Name todeploy, and Authentication to Public Key. Point it at your private key file. - Click Test Connection, then Finish. DBeaver may offer to download the database driver the first time.
Any client: a manual tunnel
If your tool has no SSH option, open the tunnel yourself from your computer, then point the client at 127.0.0.1:3307:
ssh -N -L 3307:127.0.0.1:3306 deploy@203.0.113.10-L forwards local port 3307 to port 3306 on the server, and -N keeps the session open without running a shell. Leave the window open while you work and press Ctrl + C to close the tunnel.
Check it works
- The client's test button reports success and you can see your databases.
- On the server,
SHOW PROCESSLIST;lists your client session with hostlocalhostor127.0.0.1. - From your computer, port 3306 on the server's public IP does not answer:
nc -vz -w 5 203.0.113.10 3306A timeout or "refused" result is what you want.
Troubleshooting
- "Access denied for user": the account does not exist for the host MySQL sees. Create it for both
localhostand127.0.0.1, as shown above, and check the password. - SSH step fails: test plain SSH first with
ssh deploy@203.0.113.10. If that fails too, see Fix SSH connection refused or timed out. - DBeaver says "Public Key Retrieval is not allowed": MySQL 8 accounts using
caching_sha2_passwordneed it. Open Driver properties and setallowPublicKeyRetrievaltotrue. The SSH tunnel already encrypts the traffic. - HeidiSQL cannot read the key: plink only accepts
.ppkfiles. Convert your key with PuTTYgen or switch the SSH executable tossh.exe. - "Can't connect to MySQL server on 127.0.0.1": MySQL is not running or listens on another port. Run
sudo systemctl status mysql(ormariadb) on the server.
Next steps
- Harden the database server itself: Secure MariaDB and MySQL after install.
- Make SSH logins quicker with host aliases: Use an SSH config file for shortcuts.
