Introduction
MySQL is the world's most widely used open-source relational database, powering millions of applications from small blogs to high-traffic web platforms. It is the default database for WordPress, Laravel, Drupal, and most PHP-based frameworks, and it is the "M" in the LAMP and LEMP stacks.
Ubuntu 24.04 ships MySQL 8.0 in its default repositories, which means installation is straightforward and updates are handled through the standard APT package manager. MySQL 8.0 includes significant improvements over earlier versions: a transactional data dictionary, window functions, common table expressions (CTEs), and the caching_sha2_password authentication plugin for stronger credential security.
In this tutorial, you will install MySQL 8.0 from the Ubuntu default repository, run the security hardening script to lock down the installation, configure password-based authentication for the root user, create a dedicated application database and user, perform basic SQL operations to verify the setup, and optionally configure remote access. We tested every command on a Raff Tier 3 VM, where MySQL's InnoDB buffer pool benefits directly from NVMe SSD read speeds — a common configuration for customers running WordPress and Laravel applications on our platform.
Step 1 — Install MySQL Server
Update your package index and install the MySQL server package:
bashsudo apt update
sudo apt install -y mysql-server
APT installs MySQL 8.0 along with the MySQL client and required dependencies. The MySQL service starts automatically after installation.
Verify that MySQL is running:
bashsudo systemctl status mysql
You should see active (running) in the output. If MySQL is not running, start it manually:
bashsudo systemctl start mysql
sudo systemctl enable mysql
Check the installed version:
bashmysql --version
Expected output:
mysql Ver 8.0.39-0ubuntu0.24.04.2 for Linux on x86_64 ((Ubuntu))
Note
The exact patch version may differ. The important thing is that it shows MySQL 8.0.x.
Step 2 — Secure the MySQL Installation
MySQL ships with a security script that walks you through several important hardening steps. Run it:
bashsudo mysql_secure_installation
The script prompts you with several questions:
VALIDATE PASSWORD COMPONENT — Press y to enable the password validation plugin. This enforces minimum password strength for all MySQL users. When prompted for the validation level, enter 1 for MEDIUM (requires length ≥ 8, numeric, mixed case, and special characters).
Root password — The script will skip setting a root password and display: "Skipping password set for root as authentication with auth_socket is used by default." This is normal. On Ubuntu 24.04, the root MySQL user authenticates through the Unix socket — you log in with sudo mysql and no password is needed. You will configure password-based authentication in Step 3 if needed.
For the remaining prompts:
- Remove anonymous users? —
y— Anonymous users allow anyone to connect without credentials - Disallow root login remotely? —
y— Root should only connect from localhost - Remove test database? —
y— The test database is accessible by anonymous users - Reload privilege tables? —
y— Applies the changes immediately
All done!
Step 3 — Configure Root Authentication
On Ubuntu 24.04, the MySQL root user authenticates using the auth_socket plugin by default. This means you can only log in as root using sudo mysql — no password is needed because the system verifies your Linux user identity.
Log in to MySQL as root:
bashsudo mysql
You should see the MySQL prompt:
mysql>
For many production setups, you will want root to authenticate with a password instead. This is necessary if you use database management tools like phpMyAdmin or remote administration tools. Switch the root user to password-based authentication:
sqlALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_strong_root_password';
FLUSH PRIVILEGES;
Replace your_strong_root_password with a strong password that meets the validation requirements you set in Step 2.
Warning
After switching to password authentication, sudo mysql alone will no longer work. You must use mysql -u root -p and enter the password. Keep this password in a secure location — losing it requires a password reset procedure.
Exit the MySQL prompt:
sqlEXIT;
Test the new authentication method:
bashmysql -u root -p
Enter your root password when prompted. If you see the mysql> prompt, password authentication is working.
Step 4 — Create an Application Database and User
Running applications as the MySQL root user is a security risk. Create a dedicated database and user for each application. This limits the blast radius if credentials are compromised — a leaked application password only grants access to that one database, not the entire server.
Log in as root:
bashmysql -u root -p
Create a new database:
sqlCREATE DATABASE appdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
The utf8mb4 character set supports the full range of Unicode characters, including emojis. This is the recommended character set for all new databases.
Create a dedicated user and grant it full privileges on the new database only:
sqlCREATE USER 'appuser'@'localhost' IDENTIFIED BY 'strong_user_password_here';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
Replace appuser and strong_user_password_here with your chosen username and a strong password.
Verify the grants:
sqlSHOW GRANTS FOR 'appuser'@'localhost';
You should see output confirming that appuser has ALL PRIVILEGES on appdb and USAGE on everything else (meaning no access to other databases).
Exit the MySQL prompt:
sqlEXIT;
Step 5 — Test the Database with Basic Operations
Log in as the application user to verify it can access the database:
bashmysql -u appuser -p
Enter the password you set for appuser. Switch to the application database:
sqlUSE appdb;
Create a test table:
sqlCREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Insert some sample data:
sqlINSERT INTO products (name, price) VALUES
('Cloud VM Small', 3.99),
('Cloud VM Medium', 19.99),
('Cloud VM Large', 64.00);
Query the data:
sqlSELECT * FROM products;
Expected output:
+----+-----------------+-------+---------------------+
| id | name | price | created_at |
+----+-----------------+-------+---------------------+
| 1 | Cloud VM Small | 3.99 | 2026-04-02 10:30:00 |
| 2 | Cloud VM Medium | 19.99 | 2026-04-02 10:30:00 |
| 3 | Cloud VM Large | 64.00 | 2026-04-02 10:30:00 |
+----+-----------------+-------+---------------------+
3 rows in set (0.00 sec)
The 0.00 sec query time reflects the fast random read performance of NVMe SSD storage on Raff VMs — InnoDB buffer pool reads from disk complete in microseconds rather than milliseconds.
Clean up the test table when you are done:
sqlDROP TABLE products;
EXIT;
Step 6 — Configure the Firewall for MySQL
By default, MySQL listens on port 3306 and accepts connections only from localhost. If your application runs on the same server as MySQL, no firewall changes are needed — this is the most secure configuration.
If you need to allow MySQL connections from another Raff VM on the same private network, restrict the firewall rule to that specific IP or subnet:
bashsudo ufw allow from 10.0.0.0/24 to any port 3306
Warning
Never run sudo ufw allow 3306 without an IP restriction. This exposes your database to the entire internet. If you need remote database access, restrict it to specific IP addresses and always use TLS-encrypted connections.
Verify the firewall rules:
bashsudo ufw status
For applications running on the same server (WordPress, Laravel, Node.js), keep MySQL bound to localhost and skip firewall changes entirely. This is the default and most secure option.
Step 7 — Optional: Enable Remote Access
By default, MySQL only accepts connections from localhost. If your application runs on a separate server, you need to change the bind address.
Open the MySQL configuration file:
bashsudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
Find the bind-address line:
inibind-address = 127.0.0.1
Change it to your server's private IP address or 0.0.0.0 to accept connections on all interfaces:
inibind-address = 0.0.0.0
Tip
Binding to a specific private IP (e.g., 10.0.0.5) is more secure than 0.0.0.0. If your Raff VMs are connected via private networking, use the private IP so database traffic never traverses the public internet.
Save the file and restart MySQL:
bashsudo systemctl restart mysql
You also need to create a user that can connect from a remote host. Replace 10.0.0.% with the IP or subnet of your application server:
sqlCREATE USER 'appuser'@'10.0.0.%' IDENTIFIED BY 'strong_user_password_here';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'10.0.0.%';
FLUSH PRIVILEGES;
The % wildcard allows connections from any IP in the 10.0.0.x range.
Useful MySQL Administration Commands
Here are the commands you will use most frequently when managing MySQL:
bashsudo systemctl start mysql # Start the MySQL server
sudo systemctl stop mysql # Stop the MySQL server
sudo systemctl restart mysql # Restart MySQL
sudo systemctl reload mysql # Reload configuration without restart
sudo systemctl status mysql # Check server status
sudo systemctl enable mysql # Enable start at boot
Useful MySQL client commands (run inside the mysql> prompt):
sqlSHOW DATABASES; -- List all databases
SHOW TABLES; -- List tables in current database
DESCRIBE table_name; -- Show table structure
SHOW PROCESSLIST; -- Show active connections
SELECT user, host FROM mysql.user; -- List all MySQL users
SHOW VARIABLES LIKE 'max_connections'; -- Check configuration values
Configuration files to know:
/etc/mysql/mysql.conf.d/mysqld.cnf— Main MySQL server configuration/etc/mysql/conf.d/— Additional configuration files (drop-in directory)/var/log/mysql/error.log— MySQL error log
Conclusion
You have installed MySQL 8.0 on your Raff Ubuntu 24.04 VM, secured the installation, configured password-based authentication, created a dedicated application database and user, and verified the setup with basic SQL operations. Your server is ready to host database-driven applications.
From here, you can:
- Install WordPress which uses MySQL as its database backend
- Build a LEMP stack combining Nginx, MySQL, and PHP for dynamic web applications
- Tune MySQL performance by adjusting
innodb_buffer_pool_sizeinmysqld.cnf— a common starting point is 50-70% of your VM's total RAM - Set up automated backups using
mysqldumpcombined with Raff's VM snapshot feature for complete server-level protection
For workloads that are more query-intensive, consider the Raff 4 vCPU / 8 GB RAM tier ($36.00/month). MySQL's InnoDB engine benefits significantly from both CPU cores (for parallel query execution) and RAM (for a larger buffer pool that reduces disk reads). Raff VMs with NVMe SSD storage deliver the fast random I/O that MySQL needs for index lookups and join operations.
If your application uses PostgreSQL instead of MySQL, see our Install PostgreSQL on Ubuntu 24.04 tutorial for a similar step-by-step setup.
This tutorial was tested by our systems engineering team on a Raff CPU-Optimized Tier 3 VM with MySQL 8.0.

