DevOps
How to Install MySQL 8 on Ubuntu Server: APT, systemd, and first lockdown
Install MySQL 8 through stock apt packages on Ubuntu Server, wire it into systemd, bootstrap root access with sudo mysql, then walk mysql_secure_installation so the instance is sane before apps connect—pairing naturally with nginx or PostgreSQL VMs.

MySQL is still the relational workhorse behind plenty of Laravel, WordPress, and custom services I support. Ubuntu Server ships a tested MySQL 8 stack through apt, and pairing that path with systemd plus mysql_secure_installation gives you parity with everything else DevOps-ish on the box—including the nginx plus UFW command slab I reuse whenever the same VPS also terminates TLS.
MySQL listens on 3306, survives reboots cleanly when the unit is enabled, and behaves best when privilege hygiene happens before apps connect—not after passwords leak. That single-page nginx install snippet covers the mirrored apt-and-systemctl cadence web tiers rely on.
⏱️ Estimated setup time: 10–15 minutes.
First things first: refresh apt caches
Stale indexes cause “unable to locate package”—refresh before you bind disk I/O:
sudo apt update
Install MySQL Server with apt
Pull down the distro-maintained binaries and tooling:
sudo apt install mysql-server
Start and enable MySQL with systemctl
Notice how systemd keeps you out of brittle init-script habits—bring the daemon online once, then latch it onto boot:
sudo systemctl start mysql.service
sudo systemctl enable mysql.service
Initial setup: sudo mysql and root credentials
Ubuntu plugs root through auth_socket first—the socket handshake is why you dodge a password gate here:
sudo mysql
Once you drop into the shell, stash a credential your apps can reconcile with—even if later you tighten auth plugins:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
exit
Harden MySQL with mysql_secure_installation
mysql_secure_installation interrogates risky defaults—each prompt maps almost 1:1 to Ubuntu’s packaging choices. Kick it off as any sudo-capable login:
1. Password validation prompts
Would you like to setup VALIDATE PASSWORD COMPONENT?
Press y|Y for Yes, any other key for No:
- Choose
ywhen you want the server grading password guesses. - You get LOW / MEDIUM / STRONG tiers spanning length plus complexity requirements.
Then pick a policy level:
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG:
- MEDIUM (
1) or STRONG (2) is the pragmatic default—it gives disciplined protection against guessable passwords.
2. Existing root password check
The script reviews what you configured through sudo mysql. If entropy is thin, absorb the embarrassment now and regenerate.
3. Remove anonymous users
Remove anonymous users?
- Always say
y—anonymous binds are never worth keeping on networked hosts.
4. Disallow remote root login
Disallow root login remotely?
- Choose
yso root survives only via localhost transports; remote admin should funnel through SSH plus scoped accounts.
5. Remove the test database
Remove test database and access to it?
- Opt in (
y). The sandbox schema buys little and enlarges footprint.
6. Reload privilege tables
The wizard reloads grants automatically so every choice above sticks immediately—no orphaned privileges linger in memory.
Paths, ports, and logs worth memorizing
Keep these anchors nearby when tuning mysqld or diagnosing connectivity:
| Item | Typical location |
|---|---|
| Main daemon config | /etc/mysql/mysql.conf.d/mysqld.cnf |
| Listen port | 3306/tcp unless you remap it deliberately |
| Data directory | /var/lib/mysql |
| Error + trace logs | /var/log/mysql |
Verify installation: read mysql version output
Confirm the toolchain on disk matches expectations—this catches PATH oddities (mysql command not found ubuntu) before CI scripts fire:
mysql --version
That prints the distro-pinned semver plus compiler metadata you can compare against app requirements.
Connect using the mysql client as root
Exercise password auth the same way remote operators eventually will:
mysql -u root -p
Enter the passphrase you hardened earlier; if login fails while sudo mysql still works, you are chasing plugin or socket mismatches—not missing packages.
Stack builds rarely stop at databases—the Ubuntu nginx command snippet pairs with the PostgreSQL apt walkthrough and the full Nginx install narrative when interns need cohesive VPS stories.
Troubleshooting with MySQL error logs
When upgrades misfire or replication prep fails mid-flight, tails beat guessing:
sudo tail -f /var/log/mysql/error.log
That stream surfaces InnoDB crashes, privilege denials, and bind failures while you tweak configs.
Baseline complete: mysqld listens, boots clean after systemctl, and hardened defaults behave more like production.
⏱️ Total setup time: approximately 15 minutes.
Frequently asked questions
How do I install MySQL on Ubuntu Server using apt?
Run sudo apt update so mirrors match today’s manifests, install with sudo apt install mysql-server, then activate the systemd unit (sudo systemctl start mysql) and latch it onto boot (sudo systemctl enable mysql). You now have binaries, client stubs, and a running daemon without compiling sources.
How do I restart MySQL or check its status with systemctl?
After config edits or package upgrades call sudo systemctl restart mysql, inspect readiness with sudo systemctl status mysql, and only reach for journalctl -u mysql when systemd’s narration beats plain log tails—same muscle memory as restarting other long-lived daemons discussed alongside the nginx Ubuntu snippet.
Why does this walkthrough mention mysql_native_password for root?
Stock MySQL 8 on Ubuntu favors caching_sha2_password because modern connectors understand it natively—the ALTER USER … mysql_native_password stanza survives as a bridging trick for stubborn legacy stacks. Migrate clients forward when you control every dependency.
What does mysql_secure_installation actually change?
The wizard folds five concrete moves: optional password validation, revisiting root’s secret, blasting anonymous binds, forbidding remote superuser hopping, nuking default test schemas, and reloading grants so those safeguards apply immediately—not on the next manual FLUSH PRIVILEGES.
Where are MySQL error logs on Ubuntu?
Expect structured logs under /var/log/mysql/, with error.log exposing startup sequence, InnoDB crashes, authentication failures—sudo tail -f /var/log/mysql/error.log is the live triage pane while you reconcile networking or SELinux-ish surprises elsewhere on the VPS.
Written by Shashikant Dwivedi
Engineer, occasional writer, full-time noticer. Based in Prayagraj, India. New essays land roughly twice a month.
Keep reading
Adjacent essays.

DevOps
Install MongoDB 7.0 on Ubuntu Server: Official APT & systemd Setup
Nov 29, 2024 · 3 min

DevOps
Install Nginx on Ubuntu Server: apt, UFW, systemd, welcome page
Sep 14, 2024 · 5 min

DevOps
Install Redis on Ubuntu Server: Official APT Repo & Remote Access
Sep 1, 2025 · 5 min
The newsletter
New articles in your inbox.
Occasional articles on engineering, tooling, and software development practices. No marketing, no fluff — just the article, when it's ready.
Unsubscribe with one click. Your email never leaves the list.