To install MariaDB on Ubuntu 24.04 for production, you need to make more decisions than apt install mariadb-server suggests. The package source determines the release family and upgrade path. The authentication model determines whether local administration depends on a password or the operating system account. Network binding and grants determine whether an application can connect without turning the database into a public service. Storage, backups, observability, and a tested restart determine whether the installation remains recoverable after launch.
This guide builds a single-node MariaDB server on Ubuntu 24.04 LTS, explains the choice between Ubuntu packages and the MariaDB upstream repository, and establishes a conservative production baseline. It also covers the installation failures that tend to appear later: Access denied, remote connection failures, configuration files that appear to have no effect, package conflicts, startup loops, and memory or disk pressure.
The commands assume a dedicated Ubuntu server and an account with sudo. Read each command before running it. Package installation, firewall changes, database grants, and service restarts change system state; schedule them appropriately on an existing host.
Choose the MariaDB release before installing anything
Ubuntu 24.04 and MariaDB do not have one universal “latest” package. There are two common sources:
| Package source | Typical reason to choose it | Operational consequence |
|---|---|---|
| Ubuntu 24.04 repositories | Conservative distribution integration and Ubuntu security maintenance | Uses the MariaDB family packaged by Ubuntu, currently based on 10.11 LTS |
| MariaDB upstream repository | A specific newer MariaDB LTS or feature set | You own repository selection, pinning, compatibility testing, and major-version planning |
MariaDB 12.3 was announced as an LTS release in 2026. That does not automatically make it the correct in-place replacement for every 10.11 workload. Applications, connectors, backup tools, proxies, monitoring integrations, SQL modes, authentication plugins, and replication topologies must be tested against the selected family.
Before changing repositories, inspect the machine:
lsb_release -a
uname -m
apt-cache policy mariadb-server mariadb-client
grep -R --no-filename -hE '^[^#].*(mariadb|mysql)'
/etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null
dpkg -l | grep -E 'mariadb|mysql' || true
Do not add an upstream repository to a server that already contains MySQL or MariaDB until you understand package replacement and data compatibility. Mixing Ubuntu and upstream packages with the same names can create dependency conflicts or an unplanned major upgrade.
For a new general-purpose Ubuntu server, the distribution package is a defensible baseline. Use upstream packages when a documented application requirement, support policy, or tested feature justifies the added lifecycle work.
Prepare the Ubuntu host
Update package metadata and install current Ubuntu security updates in a maintenance window:
sudo apt update
apt list --upgradable
sudo apt upgrade
An upgrade can install a new kernel or restart services. On a remote production system, keep a working SSH session, confirm the console or recovery path, and review the proposed packages before accepting.
Check time, storage, memory, and hostname:
hostnamectl
timedatectl status
free -h
df -hT
df -ih
lsblk -f
Database correctness depends on a stable clock. Filesystem capacity checks must include inodes because a filesystem can reject new files while still reporting free bytes. Record the mount that will contain /var/lib/mysql; database growth, binary logs, temporary files, backups, and system logs must not compete for the last available space without alerts.
Set the required timezone at the operating system level if it is wrong:
sudo timedatectl set-timezone UTC
timedatectl status
UTC is usually simplest for servers. Applications can convert timestamps for users. If organizational policy requires another timezone, use it consistently and document how MariaDB, the application, and backups interpret timestamps.
Method 1: install the Ubuntu-supported MariaDB package
Inspect the candidate version immediately before installation:
apt-cache policy mariadb-server mariadb-client
apt-cache show mariadb-server | sed -n '1,80p'
Install the server and client:
sudo apt install mariadb-server mariadb-client
Ubuntu normally starts and enables the service during installation. Verify instead of assuming:
systemctl is-enabled mariadb
systemctl status mariadb --no-pager
sudo journalctl -u mariadb -n 100 --no-pager
sudo mariadb -e "SELECT VERSION(), @@version_comment, NOW();"
The last command uses the local Unix socket through sudo. On current Debian-style installations, the MariaDB root@localhost account commonly authenticates with the unix_socket plugin. This is deliberate: operating-system root access authorizes local database administration without storing another root password.
Do not conclude that MariaDB is insecure because sudo mariadb does not ask for a database password. The security boundary is the privileged Linux account. A remote process or unprivileged local user cannot impersonate operating-system root merely by knowing the database username.
Method 2: install a selected upstream LTS release
Use this route only after deciding which LTS family the application supports. The MariaDB repository setup utility can configure the upstream package source, but its default may point to a rolling repository. Production automation should select a release explicitly rather than inheriting a changing default.
Download the setup script over HTTPS, inspect it, and verify the instructions against the current official repository documentation:
curl -fsSLo /tmp/mariadb_repo_setup
https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
less /tmp/mariadb_repo_setup
The exact supported option names and version identifiers can change. Display the script help on the target date:
sudo bash /tmp/mariadb_repo_setup --help
Then configure the explicitly approved LTS family using the option documented by that help output. Do not copy a version argument from an old article without checking that the repository still publishes it for Ubuntu 24.04.
After repository configuration:
sudo apt update
apt-cache policy mariadb-server mariadb-client mariadb-backup
The candidate must come from the intended repository and release family. If it does not, stop. Do not force package versions until repository priority and dependency selection are understood.
Install the approved packages:
sudo apt install mariadb-server mariadb-client mariadb-backup
Record the package origin and versions for the runbook:
apt-cache policy mariadb-server mariadb-client mariadb-backup
dpkg-query -W -f='${Package}t${Version}n'
mariadb-server mariadb-client mariadb-backup
Pinning a release family can prevent accidental movement, but a permanent hold also prevents security maintenance. Prefer a managed repository definition and change-control process over forgetting a package on hold.
Understand where MariaDB reads configuration
MariaDB option files can include other directories, and later values can override earlier ones. Discover the active defaults:
mariadbd --help --verbose 2>/dev/null |
sed -n '/Default options are read from/,/Variables and options/p' | head -n 30
sudo find /etc/mysql -maxdepth 3 -type f -print
sudo grep -R --line-number -E
'^s*(bind-address|port|datadir|socket|max_connections|innodb_buffer_pool_size)'
/etc/mysql 2>/dev/null
On Ubuntu, create a small, clearly named override in the included server configuration directory instead of editing package-owned defaults. For example:
sudoedit /etc/mysql/mariadb.conf.d/60-production.cnf
A conservative local-only baseline might contain:
[mariadb]
bind-address = 127.0.0.1
skip-name-resolve = 1
Do not paste performance numbers such as a large buffer pool from another server. Defaults are safer than unmeasured tuning. skip-name-resolve also changes grant behavior: accounts must use IP addresses or localhost, not DNS hostnames. Review existing grants before enabling it.
Validate the effective options before restart:
my_print_defaults mariadb mariadbd server mysqld
sudo mariadbd --validate-config
Not every packaged version supports every validation flag. If --validate-config is unavailable, rely on documented syntax, my_print_defaults, a staged host, and immediate journal inspection after a controlled restart.
Restart and verify:
sudo systemctl restart mariadb
systemctl status mariadb --no-pager
sudo journalctl -u mariadb --since "5 minutes ago" --no-pager
sudo mariadb -e "SHOW VARIABLES WHERE Variable_name IN ('bind_address','skip_name_resolve','port','datadir');"
sudo ss -lntp | grep ':3306'
If a setting did not change, the usual cause is the wrong option group, wrong include directory, or a later file overriding it. Adding the same variable to several files makes future diagnosis harder.
Run the security review without breaking socket authentication
MariaDB provides mariadb-secure-installation to remove anonymous users, remove remote root accounts, delete the test database, and review root authentication:
sudo mariadb-secure-installation
From MariaDB 10.4 onward, Unix socket authentication is commonly the default for local root. There is usually no need to replace it with a root password. Keep socket authentication unless a tested administrative workflow requires something else.
Inspect accounts and plugins directly:
sudo mariadb -e "SELECT User, Host, plugin FROM mysql.user ORDER BY User, Host;"
sudo mariadb -e "SHOW GRANTS FOR 'root'@'localhost';"
Avoid routine administration through an application account. Create named administrative access appropriate to your environment, preferably using local socket authentication for Linux operators or a secret-managed password over TLS for remote automation.
Create an application database and least-privilege user
Generate the password with an approved password manager or secret-management system. Do not embed it in shell history, source control, images, or tickets.
Connect locally:
sudo mariadb
Create a UTF-8 database and application account:
CREATE DATABASE appdb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost'
IDENTIFIED BY 'REPLACE_WITH_SECRET';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX
ON appdb.* TO 'appuser'@'localhost';
SHOW GRANTS FOR 'appuser'@'localhost';
The required privileges depend on the application and migration process. Many runtime services should not receive DROP, ALTER, or CREATE; a separate deployment identity can run migrations. Do not use GRANT ALL ON *.* for convenience.
Test using a prompt so the password is not exposed in the process list:
mariadb --user=appuser --password --database=appdb
-e "SELECT CURRENT_USER(), DATABASE(), NOW();"
For a local application, prefer the Unix socket when supported. It avoids opening a TCP listener and removes network firewall complexity.
Configure remote access only when required
Remote access needs three independent controls:
- MariaDB must listen on the intended interface.
- A matching
'user'@'host'account must exist. - The network firewall must allow only approved clients.
Do not set bind-address = 0.0.0.0 and open port 3306 to the internet. Bind to a private management or application address:
[mariadb]
bind-address = 10.20.30.10
MariaDB 10.11 and later can support comma-separated bind addresses, but verify behavior on the installed version. After validation and restart:
sudo ss -lntp | grep ':3306'
sudo mariadb -e "SHOW VARIABLES LIKE 'bind_address';"
Create a user limited to a specific client address or controlled subnet:
CREATE USER 'appuser'@'10.20.30.25'
IDENTIFIED BY 'REPLACE_WITH_SECRET';
GRANT SELECT, INSERT, UPDATE, DELETE
ON appdb.* TO 'appuser'@'10.20.30.25';
Allow only that source with UFW:
sudo ufw allow from 10.20.30.25 to 10.20.30.10 port 3306 proto tcp
sudo ufw status numbered
Before enabling UFW remotely, confirm SSH rules and recovery access. Database traffic across an untrusted or shared network also requires TLS; IP filtering does not encrypt credentials or data.
Test from the application host:
nc -vz -w 3 10.20.30.10 3306
mariadb --host=10.20.30.10 --user=appuser --password
--database=appdb -e "SELECT CURRENT_USER(), @@hostname;"
Interpret failures precisely. Timeout usually indicates routing or filtering. Connection refused indicates no listener on that address and port. Access denied proves that TCP reached MariaDB but authentication or the user-host match failed.
Establish a backup before loading production data
A database is not production-ready until restoration has been tested. For a small initial database, create a logical backup:
sudo install -d -m 0700 /var/backups/mariadb
sudo mariadb-dump --all-databases
--single-transaction --routines --events --triggers
| gzip > /var/backups/mariadb/all-$(date +%F-%H%M%S).sql.gz
--single-transaction provides a consistent snapshot for transactional InnoDB tables without a global read lock, but it is not a universal consistency guarantee for nontransactional tables or concurrent schema changes. Backups stored only on the database server do not protect against host loss, filesystem corruption, or compromised credentials. Copy them to protected storage with retention and integrity monitoring.
Validate gzip and inspect the dump header:
gzip -t /var/backups/mariadb/all-*.sql.gz
zgrep -m1 -E '^-- MariaDB dump|^-- MySQL dump'
/var/backups/mariadb/all-*.sql.gz
The real test is a restore into an isolated instance, followed by application-level validation. Never test a full restore over the production database.
For large datasets and faster recovery targets, install mariadb-backup, design physical backups, and pair them with binary logs for point-in-time recovery. Those are separate operational procedures, not flags to add casually to a logical dump.
Create a monitoring baseline
Start with service health, capacity, connection pressure, workload, and backup age. Useful local checks include:
systemctl is-active mariadb
sudo mariadb-admin ping
sudo mariadb -e "SHOW GLOBAL STATUS WHERE Variable_name IN (
'Uptime','Threads_connected','Threads_running','Max_used_connections',
'Questions','Slow_queries','Aborted_connects'
);"
sudo mariadb -e "SHOW VARIABLES WHERE Variable_name IN (
'max_connections','innodb_buffer_pool_size','slow_query_log'
);"
sudo du -sh /var/lib/mysql
df -hT /var/lib/mysql
df -ih /var/lib/mysql
Do not alert on a generic percentage without context. Compare Max_used_connections with max_connections, track growth over time, and identify whether high concurrency is expected or caused by leaks. Monitor filesystem free space and inodes separately. Alert before the database reaches a state where it cannot extend data files, write logs, or create temporary files.
Avoid configuring an aggressive liveness probe that restarts MariaDB during a short I/O stall. A process restart does not repair overloaded storage or a blocked transaction; it converts a performance incident into an outage and may trigger crash recovery.
Common installation and startup failures
Access denied for user 'root'@'localhost'
On modern Ubuntu packages, try the Unix socket path:
sudo mariadb --protocol=socket
Inspect the authentication plugin after connecting. Do not immediately start MariaDB with --skip-grant-tables; that disables privilege checks and requires an isolated recovery procedure.
MariaDB listens only on localhost
Ubuntu commonly defaults bind_address to 127.0.0.1. This is secure for local applications. If remote access is required, change it deliberately, verify the effective variable, add a specific user-host account, and apply a source-limited firewall rule.
A configuration change has no effect
Find duplicate definitions and include order:
sudo grep -R --line-number -E '^s*VARIABLE_NAMEs*=' /etc/mysql
my_print_defaults mariadb mariadbd server mysqld
Replace VARIABLE_NAME with the actual option. Confirm whether it is dynamic or requires restart. Query the effective server variable rather than trusting the edited file.
The service fails after restart
Do not repeatedly restart it. Capture the first error:
systemctl status mariadb --no-pager
sudo journalctl -u mariadb --since "15 minutes ago" --no-pager
sudo tail -n 100 /var/log/mysql/error.log 2>/dev/null
sudo df -hT
sudo df -ih
sudo ss -lntp | grep ':3306' || true
Common causes include invalid options, a port already in use, incorrect ownership, a full filesystem, unavailable mounts, insufficient memory, and an incompatible package transition. Fix the verified cause. Do not delete InnoDB files or initialize the data directory over existing data.
Package dependencies conflict
Inspect sources and package policy:
apt-cache policy mariadb-server mariadb-client mariadb-common
apt-mark showhold
grep -R --line-number -E 'mariadb|mysql'
/etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null
Do not solve conflicts with dpkg --force-* on a production database. Align the repository family and package versions, back up data, and test the supported transition.
Production verification checklist
Before declaring the installation complete, verify all of the following:
- The chosen release family and repository origin are documented.
- MariaDB starts after a controlled reboot.
- The error journal contains no repeating startup or storage errors.
root@localhostauthentication is understood and tested.- Anonymous users, unintended remote root accounts, and the test database are absent.
- Application users are restricted by database, privileges, and host.
- Port 3306 is either local-only or limited to approved private sources.
- TLS is required for connections across untrusted networks.
- The application can connect and perform only its intended operations.
- Database, binary log, temporary-file, and log growth have monitored capacity.
- A backup exists outside the host and has been restored in isolation.
- Package updates and major upgrades have separate tested procedures.
- The operations team knows where configuration, logs, data, backups, and credentials live.
Reboot verification catches dependencies that a simple restart does not:
sudo systemctl reboot
This disconnects users and stops the server. Run it only in an approved window with console access. After reconnecting:
systemctl status mariadb --no-pager
sudo mariadb-admin ping
sudo journalctl -u mariadb -b --no-pager
FAQ
Which MariaDB version should I install on Ubuntu 24.04?
Use the Ubuntu-packaged 10.11 family when distribution integration and conservative maintenance meet your needs. Choose a newer upstream LTS such as 12.3 only after application, connector, backup, and upgrade testing.
Should I set a password for the MariaDB root account?
Not automatically. Modern Debian and Ubuntu installations commonly use unix_socket authentication for root@localhost, which ties database administration to operating-system root. Preserve it unless a documented workflow requires another method.
Is mariadb-secure-installation still useful?
Yes, particularly for reviewing anonymous users, remote root accounts, and the test database. However, some older prompts and tutorials predate socket authentication, so understand each change before accepting it.
Why can my application not connect remotely?
Check the listener address, firewall, route, and exact MariaDB 'user'@'host' account. A timeout, refused connection, and authentication denial identify different layers and should not receive the same fix.
Should MariaDB listen on 0.0.0.0?
Usually no. Bind to the specific private interface required by applications and enforce source-limited firewall rules. Never expose port 3306 directly to the public internet.
How large should innodb_buffer_pool_size be?
There is no safe universal percentage. Measure the dataset, workload, operating-system memory, connection buffers, and co-located services. Establish monitoring before changing the default.
Is a successful mariadb-dump enough to prove backups work?
No. Validate the archive, transfer it off-host, restore it into an isolated server, and test schema, row counts, users, routines, events, and application behavior.
Can I upgrade directly between major MariaDB releases?
The supported path depends on the source and target families. Read the official upgrade documentation and release notes, test on a restored copy, back up all data, and run the required post-upgrade checks.
Conclusion
The safest way to install MariaDB on Ubuntu 24.04 is to choose the release lifecycle first, verify package origin, retain a clear local authentication model, expose only the network path the application needs, and prove backup and restart behavior before production data arrives. Installation is complete only when the service is recoverable and observable, not merely when a client returns SELECT 1.
Start with Ubuntu's packaged MariaDB when it satisfies the application. Use an upstream LTS only through an explicitly managed repository and tested upgrade policy. Keep socket authentication for local root unless there is a reason to change it, grant applications the minimum privileges they require, and treat remote access, TLS, backups, capacity, and monitoring as parts of the initial deployment rather than future cleanup.
Suggested Internal Links
- MariaDB 12.3 LTS vs 11.8 and 10.11: Version Guide —
/mariadb-lts-version-guide/ - Secure a New MariaDB Server from the First Login —
/secure-mariadb-server/ - Configure MariaDB Remote Access Without Exposing It —
/configure-mariadb-remote-access/ - Back Up MariaDB with mariadb-dump and Safe Restore Tests —
/mariadb-dump-backup-restore/ - Build a MariaDB Production Maintenance Runbook —
/mariadb-maintenance-runbook/
Suggested External Sources
- MariaDB Server installation guide — https://mariadb.com/docs/server/mariadb-quickstart-guides/installing-mariadb-server-guide
- Installing MariaDB DEB packages — https://mariadb.com/docs/server/server-management/install-and-upgrade-mariadb/installing-mariadb/binary-packages/installing-mariadb-deb-files
- MariaDB repository setup and usage — https://mariadb.com/docs/server/server-management/install-and-upgrade-mariadb/installing-mariadb/binary-packages/mariadb-package-repository-setup-and-usage
mariadb-secure-installationreference — https://mariadb.com/docs/server/clients-and-utilities/deployment-tools/mariadb-secure-installation- Unix socket authentication — https://mariadb.com/docs/server/reference/plugins/authentication-plugins/authentication-plugin-unix-socket
- MariaDB server system variables — https://mariadb.com/docs/server/server-management/variables-and-modes/server-system-variables
- MariaDB Foundation release policy — https://mariadb.org/about/