Install MySQL on Ubuntu

Khimananda Oli 9 min read Virtualization
Install MySQL on Ubuntu

By Khimananda Oli | Last reviewed: August 2026

You need to install MySQL on Ubuntu to power a web application, but default configurations often leave databases exposed or poorly tuned for production workloads. This guide walks through installing MySQL 8.4 LTS on Ubuntu 24.04, securing the instance against common attack vectors, and validating connectivity before handing it off to developers. Before you begin, ensure your server baseline is hardened; I cover foundational OS security in my initial Ubuntu server setup guide which pairs directly with this database deployment.

apt updateRefresh Reposapt installmysql-serversecure_installHarden & AuthVerify & TestConnectivity
Standard workflow to install MySQL on Ubuntu: repository refresh, package installation, security hardening, and validation.

How do you install MySQL on Ubuntu 24.04 using APT?

The most reliable way to install MySQL on Ubuntu 24.04 LTS is via the official APT repositories. Ubuntu 24.04 ships with MySQL 8.4 LTS, which receives long-term support and security patches through 2029. Avoid adding third-party PPAs unless you have a specific version requirement that the official repos cannot satisfy; mixing sources is a frequent cause of dependency breakage during future upgrades.

Update package indexes and install the server

Always refresh your local package metadata before installing database software to avoid pulling outdated binaries with known vulnerabilities.

sudo apt update
sudo apt install -y mysql-server

The -y flag auto-confirms the installation. On a minimal Ubuntu server image, this pulls approximately 180 MB of dependencies including libaio1, mecab, and the client utilities. The service starts automatically after installation completes.

Verify the service is running

Confirm systemd has started MySQL and that it is enabled for boot persistence:

sudo systemctl status mysql
sudo systemctl enable mysql

You should see active (running) in green. If the service fails to start, check journalctl -u mysql --no-pager -n 50 for errors. Common causes include AppArmor profile conflicts or insufficient disk space on /var/lib/mysql.

How do you secure MySQL after installation on Ubuntu?

A fresh MySQL installation prioritizes usability over security. You must harden it before exposing it to any network traffic or application code. The mysql_secure_installation script handles the most critical post-install tasks interactively.

Run the security hardening script

sudo mysql_secure_installation

Respond to each prompt as follows for production environments:

  • VALIDATE PASSWORD COMPONENT: Press Y. Choose strength level 2 (STRONG) to enforce minimum 8 characters with mixed case, numbers, and special characters.
  • Root password: Set a strong root password. Store it in a password manager or secrets vault immediately; never embed it in scripts.
  • Remove anonymous users: Y. Anonymous accounts allow unauthenticated access from localhost, which attackers exploit for lateral movement.
  • Disallow root login remotely: Y. Root should only authenticate via Unix socket on the server itself.
  • Remove test database: Y. The test database is world-readable and serves no production purpose.
  • Reload privilege tables: Y. Applies all changes immediately without requiring a service restart.

Configure authentication plugin compatibility

MySQL 8.4 defaults to caching_sha2_password, which some older PHP drivers and legacy applications do not support. If your stack requires the older native authentication, create application users explicitly with the compatible plugin:

CREATE USER 'app_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Str0ng!Pass#2026';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app_user'@'localhost';
FLUSH PRIVILEGES;

For new applications, prefer caching_sha2_password as it provides stronger cryptographic guarantees. Only fall back to native authentication when driver compatibility demands it.

Client ConnectsCheck User Auth Plugincaching_sha2_passwordDefault · Secure · Fastmysql_native_passwordLegacy Compat · WeakerSHA-256 ChallengeDouble SHA-1 Hash
MySQL 8.4 authentication plugin comparison: caching_sha2_password is preferred for security; mysql_native_password exists only for legacy driver compatibility.

How do you configure MySQL for remote access and firewall rules?

By default, MySQL binds only to 127.0.0.1, rejecting all external connections. Many tutorials instruct changing bind-address to 0.0.0.0, but this exposes the database to every network interface without discrimination. In practice, bind to a specific private IP or use UFW to restrict access at the firewall layer first.

Edit the bind address safely

Open the main configuration file:

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

Locate the bind-address directive and set it to your server's private IP or keep 127.0.0.1 if applications connect locally:

# Bind to private network interface only
bind-address = 10.0.1.50

Restart MySQL to apply: sudo systemctl restart mysql.

Create application-specific users with host restrictions

Never grant remote access to root. Create dedicated users scoped to the exact source IP or subnet:

CREATE USER 'web_app'@'10.0.1.%' IDENTIFIED BY 'C0mpl3x!DbPass#24';
GRANT ALL PRIVILEGES ON production_db.* TO 'web_app'@'10.0.1.%';
FLUSH PRIVILEGES;

The wildcard % in the host field allows connections from any IP in the 10.0.1.0/24 subnet. For tighter control, specify the exact application server IP.

Configure UFW firewall rules

If you followed the UFW firewall configuration guide, add MySQL access only from trusted sources:

sudo ufw allow from 10.0.1.0/24 to any port 3306 proto tcp comment 'MySQL from app subnet'
sudo ufw reload

Never open port 3306 to any without an explicit allowlist. Publicly exposed MySQL instances are compromised within hours by automated scanners.

What are the essential production tuning parameters for MySQL on Ubuntu?

Default MySQL configuration assumes a development environment with minimal memory allocation. Production servers require tuning to utilize available RAM efficiently and handle concurrent connections without swapping. These settings belong in a custom override file to survive package upgrades.

Create a production override configuration

sudo nano /etc/mysql/mysql.conf.d/production-tuning.cnf

Add these baseline parameters for a server with 8 GB RAM dedicated to MySQL:

[mysqld]
innodb_buffer_pool_size = 5G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1
max_connections = 200
thread_cache_size = 16
table_open_cache = 4000
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

Key explanations:

  • innodb_buffer_pool_size: Set to 60–70% of total RAM on a dedicated database server. This caches data and indexes in memory, reducing disk I/O dramatically.
  • innodb_flush_log_at_trx_commit = 1: Ensures ACID compliance by flushing logs to disk on every commit. Only change to 2 if you accept potential data loss for write performance.
  • slow_query_log: Captures queries exceeding 2 seconds. Review weekly to identify missing indexes or inefficient joins. Pair this with MySQL performance tuning techniques for deeper optimization.

Validate configuration before restarting

Syntax errors in MySQL config files prevent the service from starting, causing downtime. Always validate first:

sudo mysqld --validate-config
sudo systemctl restart mysql
ParameterDevelopment DefaultProduction Recommendation (8GB RAM)Impact
innodb_buffer_pool_size128M5GReduces disk reads by caching hot data
max_connections151200–400Prevents connection refused errors under load
innodb_log_file_size48M512M–1GImproves write throughput for bulk operations
slow_query_logOFFONEnables query performance auditing
innodb_flush_log_at_trx_commit11 (or 2 for perf)Balances durability vs. write latency
MySQL Memory Architecture (8 GB Server)InnoDB Buffer Pool5 GB (62% of RAM)Data PagesCached RowsIndex PagesB-Tree NodesRedo Log Filesinnodb_log_file_size = 512MWrite-Ahead Logging · Crash RecoveryConnection Threadsmax_connections = 200~1–2 MB per thread · Per-session buffersOS Cache + Swap (Avoid!)Reserve 1–2 GB for OS · Never let MySQL swapSwapping causes 100x latency spikes
MySQL memory layout on an 8 GB server: buffer pool dominates allocation, with reserved space for OS and connection threads to prevent swapping.

How do you verify MySQL installation and test connectivity?

After installation and configuration, validate that MySQL accepts connections as expected and that your application credentials work correctly. Skipping this step leads to confusing application errors that mask underlying permission or network issues.

Test local root access via Unix socket

sudo mysql -u root -p

On Ubuntu 24.04, root authenticates via auth_socket by default, meaning sudo mysql works without a password prompt. If you set a root password during secure installation, use -p to trigger the prompt.

Test application user connectivity

From the application server (not the database host), verify the dedicated user can connect:

mysql -u web_app -h 10.0.1.50 -p production_db

If this fails, diagnose systematically:

  1. Check MySQL is listening on the expected interface: ss -tlnp | grep 3306
  2. Verify UFW allows the source IP: sudo ufw status verbose
  3. Confirm user host permissions: SELECT user, host FROM mysql.user WHERE user='web_app';
  4. Review MySQL error log: sudo tail -50 /var/log/mysql/error.log

Automate health checks for monitoring

Add a simple health check script for your monitoring stack. This returns exit code 0 only if MySQL responds to queries:

#!/bin/bash
mysqladmin -u monitor_user -p'Mon!torPass24' ping >/dev/null 2>&1
exit $?

Create the monitor user with minimal privileges:

CREATE USER 'monitor_user'@'localhost' IDENTIFIED BY 'Mon!torPass24';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'monitor_user'@'localhost';
FLUSH PRIVILEGES;

This user cannot read or modify data, satisfying least-privilege principles while enabling uptime monitoring. Integrate this check with Prometheus, Nagios, or your preferred observability platform.

Install MySQL on Ubuntu: Next Steps for Production Readiness

You now have a functional, secured MySQL installation on Ubuntu 24.04. However, installation is only the foundation. Before going live, implement automated backups using mysqldump or Percona XtraBackup, enable TLS for encrypted connections, and establish a patching schedule aligned with Ubuntu's USN advisories. For teams managing multiple environments, consider infrastructure-as-code approaches covered in my Terraform practical guide to make database provisioning reproducible and auditable.

If your workload demands high availability, evaluate whether self-managed MySQL on EC2/VPS makes sense versus managed alternatives; I break down the cost and operational trade-offs in the RDS vs self-managed MySQL comparison. For personalized architecture review or help hardening your database layer for SOC 2 or ISO 27001 compliance, reach out directly to discuss your specific requirements.

Frequently Asked Questions

Run sudo apt update followed by sudo apt install mysql-server. This installs the latest stable MySQL version available in the official Ubuntu repositories for your specific release.

Yes, the MySQL Community Edition included in Ubuntu repositories is completely free and open source under the GPL license for both personal and commercial production use.

Execute sudo mysql_secure_installation to set a root password, remove anonymous users, disable remote root login, and delete the test database to harden your fresh installation against common attacks.

Yes, the mysql-server package automatically starts and enables the systemd service upon installation completion, so the database is ready for connections without manual intervention.

Check status with systemctl status mysql or connect using sudo mysql. A successful connection prompt confirms the server process is active and accepting local socket connections properly.

Ubuntu packages configure auth_socket for the root user by default, allowing passwordless access via sudo mysql while requiring explicit configuration changes for traditional password-based remote authentication methods.

Log in as root and run CREATE USER 'username'@'localhost' IDENTIFIED BY 'password'; then GRANT ALL PRIVILEGES ON database. TO 'username'@'localhost'; followed by FLUSH PRIVILEGES; to apply permissions immediately.

The primary configuration file is /etc/mysql/mysql.conf.d/mysqld.cnf for server settings, while /etc/mysql/my.cnf acts as the main include file that loads additional configuration directories.

Yes, add the official MySQL APT repository from dev.mysql.com to access specific versions like 8.4 LTS instead of relying on the potentially older version in Ubuntu's default repositories.

Stop MySQL, start with --skip-grant-tables, connect without password, update the mysql.user table authentication string, flush privileges, restart normally, then verify login works with the new credentials.

MySQL listens on TCP port 3306 by default, though Ubuntu installations bind only to localhost initially, requiring explicit bind-address configuration changes to accept remote network connections.

Minimum viable production requires 1GB RAM, but 2GB or more is recommended for decent performance since InnoDB buffer pool size directly impacts query speed and concurrent connection handling capacity.

Common causes include insufficient disk space, AppArmor permission denials, corrupted data directory, or port conflicts. Check journalctl -u mysql and /var/log/mysql/error.log for specific failure diagnostics.

MariaDB offers full MySQL compatibility with some performance improvements and is Ubuntu's historical default, but choose Oracle MySQL if you require specific enterprise features, official support, or application-certified compatibility.

Run sudo apt purge mysql-server mysql-client mysql-common mysql-server-core- mysql-client-core-* then sudo rm -rf /etc/mysql /var/lib/mysql to remove all packages, configs, and data files entirely.