
August 19, 2026
9 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
To correctly install MySQL on Ubuntu for a production web application, you must go beyond the default apt install command and configure authentication, memory buffers, and security hardening specific to your workload. Whether you are deploying a high-traffic eCommerce platform or a legal-tech portal, the difference between a fragile development setup and a resilient production database lies in post-installation tuning. For developers building data-driven applications, understanding this full lifecycle is as critical as mastering database-driven website development in Nepal or any global market where reliability directly impacts revenue and user trust.
sudo apt update && sudo apt install mysql-server-8.4, then immediately execute sudo mysql_secure_installation to enforce root authentication and remove test databases. Configure /etc/mysql/mysql.conf.d/mysqld.cnf for InnoDB buffer pool sizing and bind-address restrictions before restarting the service for production use.How Do You Correctly Install MySQL on Ubuntu 24.04 LTS?
The standard APT repository for Ubuntu 24.04 (Noble Numbat) ships with MySQL 8.4 LTS, which is the current long-term support release suitable for production environments in 2026. While some tutorials still reference MySQL 8.0, new deployments should target 8.4 for extended support coverage and recent performance improvements. Before running any installation commands, verify your OS version with lsb_release -a to ensure compatibility.
Installation Commands and Verification
Update your package index and install the server package. The mysql-server-8.4 metapackage pulls in all necessary dependencies including the client binaries and common libraries.
sudo apt update
sudo apt install mysql-server-8.4
# Verify the installed version
mysql --version
# Expected output: mysql Ver 8.4.x for Linux on x86_64
# Check service status immediately after install
sudo systemctl status mysql On Ubuntu 24.04, the MySQL service starts automatically after installation and is enabled for boot persistence. If the service fails to start, check journalctl -u mysql -n 50 --no-pager for errors related to AppArmor profiles or directory permissions. In my experience managing shared EC2 infrastructure for multiple client sites, AppArmor denials are the most common cause of startup failures after upgrades or custom path configurations.
Understanding Default Authentication Behavior
MySQL 8.4 on Ubuntu defaults to auth_socket authentication for the root user, meaning the database authenticates based on the operating system user rather than a password. This is secure for local administration but incompatible with remote connections or application drivers that expect password-based auth. You will address this during the secure installation step, but understanding this default prevents confusion when mysql -u root -p rejects passwords immediately after install.
What Security Steps Are Mandatory After You Install MySQL on Ubuntu?
The mysql_secure_installation script is not optional for production systems. It addresses five critical security gaps left by the default package installation. Run it immediately after the service starts:
sudo mysql_secure_installation The interactive prompts require deliberate choices. Here is the recommended configuration for production Laravel, Symfony, or WordPress applications:
- VALIDATE PASSWORD Component: Enable with MEDIUM strength. This enforces minimum length, mixed case, numbers, and special characters for all database passwords. For Nepal-based projects handling sensitive legal or financial data, STRONG is preferable.
- Root Password: Set a cryptographically strong password even if you plan to keep
auth_socketfor local admin. Some backup tools and monitoring agents require password-based root access. - Remove Anonymous Users: Yes. Anonymous accounts allow unauthenticated access from localhost and are a frequent vector in compromised shared hosting environments.
- Disallow Root Login Remotely: Yes. Administrative access should occur via SSH tunnel or
sudoon the server itself. Remote root access has no legitimate production use case. - Remove Test Database: Yes. The
testdatabase is world-accessible by default and serves no purpose after installation. - Reload Privilege Tables: Yes. Changes take effect immediately without service restart.
Creating Application-Specific Database Users
Never connect your application as root. Create a dedicated user with privileges scoped to the specific database. For a Laravel application named legal_portal:
sudo mysql
CREATE DATABASE legal_portal CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'legal_app'@'localhost' IDENTIFIED BY 'Str0ng!P@ssw0rd#2026';
GRANT ALL PRIVILEGES ON legal_portal.* TO 'legal_app'@'localhost';
FLUSH PRIVILEGES;
EXIT; The utf8mb4_unicode_ci collation is essential for Nepali Unicode content and emoji support. Using the older utf8 charset silently truncates characters outside the Basic Multilingual Plane, corrupting Devanagari text and causing subtle bugs in legal document storage. I have encountered this issue on multiple legal-tech portals where case filings contained Nepali metadata that appeared correct in the application but was corrupted at rest.
How Should You Configure MySQL Performance for Production Workloads?
The default MySQL configuration on Ubuntu assumes minimal resources and conservative safety margins. Production workloads require explicit tuning. Edit the main configuration file:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf Critical Performance Parameters
These settings assume a dedicated database server with 8GB RAM running a typical Laravel or WooCommerce workload. Adjust proportionally for your hardware.
| Parameter | Default | Production Value (8GB RAM) | Purpose |
|---|---|---|---|
innodb_buffer_pool_size | 128M | 5G | Caches table data and indexes in RAM. Set to 60-70% of available memory on dedicated DB servers. |
innodb_log_file_size | 48M | 512M | Reduces checkpoint frequency for write-heavy workloads like order processing. |
max_connections | 151 | 300 | Prevents connection exhaustion under load. Monitor with SHOW STATUS LIKE 'Threads_connected'. |
bind-address | 127.0.0.1 | 127.0.0.1 | Keep localhost-only unless application servers are on separate hosts. Never bind to 0.0.0.0 without firewall rules. |
slow_query_log | OFF | ON | Captures queries exceeding threshold. Essential for identifying N+1 problems and missing indexes. |
long_query_time | 10 | 1 | Threshold in seconds for slow query logging. One second catches most problematic queries without excessive noise. |
After editing, validate syntax and restart:
sudo mysqld --validate-config
sudo systemctl restart mysql A common mistake I see on client servers is setting innodb_buffer_pool_size too high on shared-memory instances, causing OOM kills during peak traffic. Always leave sufficient headroom for PHP-FPM workers, Nginx/Apache, and OS caches. On a 4GB VPS commonly used for Nepal SME projects, cap the buffer pool at 2GB maximum.
How Do You Integrate MySQL with Laravel and PHP Applications?
After you install MySQL on Ubuntu and complete security hardening, configure your application's database connection. Laravel 12 uses PDO with prepared statements by default, which protects against SQL injection when used correctly.
Environment Configuration
In your Laravel project's .env file:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=legal_portal
DB_USERNAME=legal_app
DB_PASSWORD=Str0ng!P@ssw0rd#2026
# Connection pooling and timeout tuning
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
DB_STRICT=true The DB_STRICT=true setting enables strict SQL mode, which prevents silent data truncation and invalid date insertion. This is non-negotiable for legal-tech applications where data integrity is paramount. I have debugged too many production issues caused by loose mode silently accepting malformed input that later broke reporting queries or document generation.
Verifying Connectivity and Character Encoding
Run migrations and verify the connection handles Unicode correctly:
php artisan migrate:fresh --seed
# Verify character set at runtime
php artisan tinker
>>> DB::select("SHOW VARIABLES LIKE 'character_set%'");
>>> DB::select("SHOW VARIABLES LIKE 'collation%'"); If you are building APIs, follow established patterns for Laravel API best practices including proper error handling for database exceptions and connection retry logic. For teams evaluating whether to handle this infrastructure internally, understanding the ongoing maintenance burden helps inform decisions about hiring a web developer in Nepal versus managing it with existing staff.
What Ongoing Maintenance Does MySQL Require After Installation?
Installing MySQL on Ubuntu is a one-time event; maintaining it is continuous. Production databases require proactive monitoring and scheduled maintenance to prevent degradation.
Automated Backup Strategy
Configure nightly logical backups using mysqldump or physical backups with Percona XtraBackup for larger datasets. For most Nepal-based SME projects under 50GB, mysqldump with compression is sufficient:
# /etc/cron.d/mysql-backup
0 2 * * * root mysqldump --single-transaction --routines --triggers \
-u backup_user -p'SecureBackupPass!' legal_portal | gzip > \
/var/backups/mysql/legal_portal_$(date +\%Y\%m\%d).sql.gz
# Retain 30 days of backups
0 3 * * * root find /var/backups/mysql -name "*.sql.gz" -mtime +30 -delete Test restores quarterly. A backup you cannot restore is not a backup. I maintain restore runbooks for every production system I manage, because discovering corruption during an actual outage is catastrophic.
Monitoring Key Metrics
Set up alerts for these indicators before they become incidents:
- Connections: Alert when
Threads_connectedexceeds 80% ofmax_connections. - Buffer Pool Hit Rate: Should stay above 99%. Below 95% indicates insufficient
innodb_buffer_pool_size. - Slow Queries: Any spike above baseline warrants immediate investigation.
- Disk Usage: Alert at 80% capacity. Binary logs and temporary tables can consume space unexpectedly.
- Replication Lag: If using read replicas, lag over 5 seconds degrades user experience.
Tools like Prometheus with mysqld_exporter provide granular visibility without significant overhead. For smaller deployments, a simple cron job parsing SHOW GLOBAL STATUS output and emailing anomalies may suffice. Match monitoring complexity to operational capacity — elaborate dashboards that nobody checks are worse than simple alerts that actually get attention.
Conclusion
When you install MySQL on Ubuntu for production, treat the package installation as merely the starting point. Security hardening via mysql_secure_installation, deliberate performance tuning in mysqld.cnf, proper character encoding for multilingual content, and automated backup verification are what separate reliable production databases from fragile development setups. These steps apply whether you are deploying a legal-tech portal in Kathmandu or a SaaS platform serving global users. If you need assistance configuring MySQL for a specific workload or auditing an existing installation, reach out to discuss your project requirements.

