Verified guide
This guide was verified by creating a cloud server and running every command in it, from start to finish, exactly as written.
- OS
- Ubuntu 24.04.5 LTS · x86_64
- Installed version
- MySQL 8.4.11 LTS (8.4.11-1ubuntu24.04)
- Test server
- DigitalOcean · 1 vCPU / 1 GB RAM / 25 GB SSD (s-1vcpu-1gb, sgp1)
- Last checked
- 2026-10-10
This guide contains affiliate links. If you sign up through them, Codesand may earn a commission. This doesn't affect the content or our assessments.
Add the official MySQL repository to an Ubuntu 24.04 server and install MySQL 8.4, the last version of MySQL 8 and an LTS version, then configure the firewall, apply the basic security settings and create a user and a database for remote access, and check that you can connect from your PC.
1. Requirements
- One Ubuntu 24.04 LTS server (1 GB of memory or more recommended)
- SSH access with an account that has
sudoprivileges - The public IP address of the PC you will connect from (e.g.
203.0.113.10)
If you don't have a server, create the smallest DigitalOcean Droplet (1 vCPU · 1 GB). This Droplet is enough to install MySQL 8.4. Every step in this guide was verified on a server created as a Droplet (1 vCPU · 1 GB memory · 25 GB SSD · Ubuntu 24.04 · Singapore).
2. Add the official MySQL repository
The MySQL version installed from the default Ubuntu 24.04 repositories is 8.0.
apt-cache policy mysql-server | head -3mysql-server:
Installed: (none)
Candidate: 8.0.46-0ubuntu0.24.04.4To install MySQL 8.4, add the official MySQL repository (repo.mysql.com). MySQL releases LTS versions with long-term support (8.4, 9.7) separately from Innovation versions, which add new features every few months. 8.4 is the last version of MySQL 8 and an LTS version.
The official repository is registered with the mysql-apt-config package. First, update the package list and download mysql-apt-config.
sudo apt update
wget https://repo.mysql.com/mysql-apt-config_0.8.40-1_all.debWhen mysql-apt-config is installed, it asks which version's repository to register. The first line selects mysql-8.4-lts in advance, and DEBIAN_FRONTEND=noninteractive on the second line installs the package with the selected value without showing the prompt screen.
echo "mysql-apt-config mysql-apt-config/select-server select mysql-8.4-lts" | sudo debconf-set-selections
sudo DEBIAN_FRONTEND=noninteractive dpkg -i mysql-apt-config_0.8.40-1_all.debSelecting previously unselected package mysql-apt-config.
(Reading database ... 75073 files and directories currently installed.)
Preparing to unpack mysql-apt-config_0.8.40-1_all.deb ...
Unpacking mysql-apt-config (0.8.40-1) ...
Setting up mysql-apt-config (0.8.40-1) ...Check the registered repositories. If you see mysql-8.4-lts, it is working.
cat /etc/apt/sources.list.d/mysql.list### THIS FILE IS AUTOMATICALLY CONFIGURED ###
# You may comment out entries below, but any other modifications may be lost.
# Use command 'dpkg-reconfigure mysql-apt-config' as root for modifications.
deb [signed-by=/usr/share/keyrings/mysql-apt-config.gpg] http://repo.mysql.com/apt/ubuntu/ noble mysql-apt-config
deb [signed-by=/usr/share/keyrings/mysql-apt-config.gpg] http://repo.mysql.com/apt/ubuntu/ noble mysql-8.4-lts
deb [signed-by=/usr/share/keyrings/mysql-apt-config.gpg] http://repo.mysql.com/apt/ubuntu/ noble mysql-tools
deb-src [signed-by=/usr/share/keyrings/mysql-apt-config.gpg] http://repo.mysql.com/apt/ubuntu/ noble mysql-8.4-ltsUpdate the package list, then check the version to be installed again. If Candidate starts with 8.4, it is working.
sudo apt update
apt-cache policy mysql-server | head -3mysql-server:
Installed: (none)
Candidate: 8.4.11-1ubuntu24.043. Install MySQL 8.4
sudo DEBIAN_FRONTEND=noninteractive apt install -y mysql-serverDEBIAN_FRONTEND=noninteractive is an option that uses the default values instead of showing configuration prompts during installation. When you install this way, no password is set for MySQL root, and it connects with the auth_socket method described in step 4.
When the installation finishes, check the installed version.
mysql --versionmysql Ver 8.4.11 for Linux on x86_64 (MySQL Community Server - GPL)4. Check the service status
When the installation finishes, the mysql service starts automatically.
sudo systemctl status mysql --no-pager● mysql.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysql.service; enabled; preset: enabled)
Active: active (running) since Sat 2026-10-10 08:21:19 UTC; 21s agoCheck which addresses and ports MySQL accepts connections on.
sudo ss -tlnp | grep mysqldLISTEN 0 151 *:3306 *:* users:(("mysqld",pid=3789,fd=22))
LISTEN 0 70 *:33060 *:* users:(("mysqld",pid=3789,fd=19))Port 3306 is used by regular MySQL clients, and port 33060 is the X Protocol port used by MySQL Shell and similar tools. * in the address field means that MySQL accepts connections on all of the server's addresses. MySQL 8.0 from the default Ubuntu repositories accepts connections only on 127.0.0.1, but MySQL from the official repository accepts remote connections right after installation. This is because the configuration file has no bind-address entry.
grep -v '^#' /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v '^$'[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
log-error = /var/log/mysql/error.logIf you connect from a remote PC in this state, you get the error below. The port is open, but there is no MySQL user yet that can connect from an external address.
ERROR 1130 (HY000): Host '203.0.113.10' is not allowed to connect to this MySQL serverNow check that you can connect to MySQL. Right after installation, you can connect as root without a password with sudo mysql.
sudo mysql -e "SELECT VERSION();"+-----------+
| VERSION() |
+-----------+
| 8.4.11 |
+-----------+You can see why no password is needed in the MySQL user list.
sudo mysql -e "SELECT user, host, plugin FROM mysql.user;"+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | auth_socket |
+------------------+-----------+-----------------------+The MySQL root user authenticates with auth_socket. auth_socket checks the name of the Linux account that connects to MySQL instead of a password, so you can connect as MySQL root only when you run the client with Linux root privileges (sudo).
5. Configure the firewall (ufw)
As you saw in step 4, port 3306 is already open to remote connections. Before you create users, configure the firewall first so that only your PC's IP can reach port 3306. Port 33060 is not allowed, so it can no longer be reached from outside. Always allow SSH before you enable the firewall. If you enable the firewall without allowing SSH, your connection to the server is cut off.
sudo ufw allow OpenSSH
sudo ufw allow from 203.0.113.10 to any port 3306 proto tcp
sudo ufw --force enable
sudo ufw statusStatus: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
3306/tcp ALLOW 203.0.113.10
OpenSSH (v6) ALLOW Anywhere (v6)6. Basic security settings
MySQL includes the mysql_secure_installation tool, which applies the basic security settings through a series of questions. The tool asks, in order, whether to set up the password validation component, set the root password, remove anonymous users, remove root accounts that can connect remotely, and remove the test database. In this guide, you run the user and database cleanup steps directly in SQL. Because root uses auth_socket, you do not set a password for it.
First, check the current list of databases.
sudo mysql -e "SHOW DATABASES;"+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+When MySQL is installed from the official repository packages, as the user list and database list above show, there are no anonymous users and no test database, and root can connect only from localhost. If you installed MySQL another way or have changed its settings, use the commands below to reach the same state. If the server is already in the state shown above, running them changes nothing and prints no output.
sudo mysql -e "DELETE FROM mysql.user WHERE User='';"
sudo mysql -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
sudo mysql -e "DROP DATABASE IF EXISTS test;"
sudo mysql -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';"
sudo mysql -e "FLUSH PRIVILEGES;"The first line deletes anonymous users that have no name, and the second line deletes root accounts that can connect from outside the server. The third and fourth lines delete the test database and its access privileges, and the last line applies the changed privileges immediately.
7. Create a user and a database
It is safer for applications to connect as a dedicated user instead of the admin account root. Create the database appdb and the user appuser. Be sure to replace the password with a value of your own, and replace 203.0.113.10 with the public IP of the PC you will connect from.
sudo mysql -e "CREATE DATABASE appdb;"
sudo mysql -e "CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'change-this-password';"
sudo mysql -e "CREATE USER 'appuser'@'203.0.113.10' IDENTIFIED BY 'change-this-password';"
sudo mysql -e "GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost', 'appuser'@'203.0.113.10';"MySQL identifies a user by user name@connecting host. 'appuser'@'localhost' is used when you connect from the server itself, and 'appuser'@'203.0.113.10' is used when you connect from your PC. Both users have all privileges on appdb only and cannot access other databases.
Check that the users were created.
sudo mysql -e "SELECT user, host, plugin FROM mysql.user WHERE user = 'appuser';"+---------+----------------+-----------------------+
| user | host | plugin |
+---------+----------------+-----------------------+
| appuser | 203.0.113.10 | caching_sha2_password |
| appuser | localhost | caching_sha2_password |
+---------+----------------+-----------------------+Connect as appuser on the server. The -p option means that the client asks for the password, and appdb at the end is the database to connect to.
mysql -u appuser -p appdb -e "SELECT CURRENT_USER(), DATABASE();"Enter password:
+-------------------+------------+
| CURRENT_USER() | DATABASE() |
+-------------------+------------+
| appuser@localhost | appdb |
+-------------------+------------+8. Check the connection from your PC
If the mysql client isn't installed on your PC, you can run the MySQL client with Docker and connect. Replace 203.0.113.20 with the server's IP. Because the --rm option is added, the container is deleted automatically when the command finishes. -it is an option that attaches a terminal so that you can enter the password.
docker run --rm -it mysql:8.4 mysql -h 203.0.113.20 -u appuser -p appdb -e "SELECT CURRENT_USER(), DATABASE();"Enter password:
+------------------------+------------+
| CURRENT_USER() | DATABASE() |
+------------------------+------------+
| appuser@203.0.113.10 | appdb |
+------------------------+------------+If your PC's IP is displayed after appuser@, remote access is working. Also check that the connection is encrypted.
docker run --rm -it mysql:8.4 mysql -h 203.0.113.20 -u appuser -p appdb -e "SHOW STATUS LIKE 'Ssl_version';"Enter password:
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| Ssl_version | TLSv1.3 |
+---------------+---------+TLSv1.3 means that the connection is encrypted with TLS. MySQL creates a self-signed certificate when it starts for the first time, and the client uses an encrypted connection when the server supports it.
9. Troubleshooting
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
MySQL root uses auth_socket, so you cannot connect with a password. On the server, connect with sudo mysql. For applications and external tools, use the appuser you created in step 7.
ERROR 1130 (HY000): Host '203.0.113.10' is not allowed to connect to this MySQL server
This means that there is no MySQL user registered for the IP of the PC you connected from. You get this error if you connect remotely before step 7. You also get the same error when the public IP of your home or office has changed. Check the registered host with sudo mysql -e "SELECT user, host, plugin FROM mysql.user WHERE user = 'appuser';".
ERROR 1045 (28000): Access denied for user 'appuser'@'203.0.113.10' (using password: YES)
This means that the password is wrong, or that there is no user for the user@host combination you connected with. With the settings in this guide, connecting as root from a remote PC gives the same error, Access denied for user 'root'@'203.0.113.10'.
10. Uninstall
To delete MySQL and all of its data, run the commands below. Because the database files are deleted as well, back up any data you need with mysqldump first.
sudo DEBIAN_FRONTEND=noninteractive apt purge -y 'mysql-*'
sudo apt autoremove -y
sudo rm -rf /etc/mysql /var/lib/mysql /var/log/mysql'mysql-*' is enclosed in quotes so that the shell does not expand * into file names and passes it to apt as is. When you run the command, several lines with the names of packages that are not installed are displayed, such as Package 'mysql-server-5.7' is not installed, so not removed. This is normal, because apt checks every package whose name starts with mysql-. This command also deletes the mysql-apt-config package you installed in step 2, and with it the official repository configuration file (/etc/apt/sources.list.d/mysql.list) and the signing key.
Also delete the port 3306 rule you added to the firewall.
sudo ufw delete allow from 203.0.113.10 to any port 3306 proto tcpRule deletedCheck that no MySQL packages remain. If 0 is displayed, everything has been deleted.
dpkg -l | grep -c mysql0Try it yourself
No server yet? You can spin up an Ubuntu server in a few minutes with one of these providers. We verified this guide on DigitalOcean.
Was this guide helpful? Let us know if anything is wrong or out of date.
Request a correction