Use case · Database

MariaDB on a dedicated server: install, size InnoDB to the RAM, back it up

A MariaDB dedicated server is one physical machine running only MariaDB, so the InnoDB buffer pool can take most of the RAM and every fsync goes straight to drives no other tenant touches. This page covers the install on Ubuntu, sizing innodb_buffer_pool_size and the redo log, network access, backups with mariadb-backup and mariadb-dump, and upgrades between release series.

Configure a database server

What MariaDB asks of the hardware

Memory first, then storage latency, then cores. The InnoDB documentation calls innodb_buffer_pool_size the most important system variable: the pool should hold most of the active data set, and the variable reference says it can be set up to 80% of total memory on a server running mostly InnoDB tables. The buffer pool page also warns against going so large that the machine swaps, which costs more than the bigger pool gains.

Storage matters because of the commit path. With the default innodb_flush_log_at_trx_commit=1, InnoDB writes and flushes the redo log on every transaction, which is what full ACID needs. Every commit therefore waits on the drive, so fsync latency sets the floor under write-heavy work.

SettingWhat it controlsStarting point
innodb_buffer_pool_sizeRAM cache for data and index pages; default 128 MiBUp to 80% of RAM per the docs; 70% in our block below
innodb_log_file_sizeSize of the single redo log file, ib_logfile0Our choice: a quarter of the buffer pool, capped at 16 GB
innodb_flush_log_at_trx_commitWhen commits reach the diskKeep 1; 2 can lose about a second of commits on an OS crash or power loss
bind-addressWhich addresses accept TCP connections127.0.0.1 until another host must connect

The 80% guidance assumes MariaDB has the box to itself. The docs say it does not apply when MariaDB ColumnStore runs on the same server, because ColumnStore reserves 75% of system RAM by default.

Machines that fit a MariaDB workload

The SQL dedicated server page lists three database builds, and each one maps to a different kind of MariaDB deployment. All are single tenant with root, with no hypervisor between the engine and the disks, on Linux images including Ubuntu 26.04, Debian 13 and AlmaLinux 10, with nothing to license.

  • Two NVMe drives in RAID 1 (Xeon E3-1585L v5, 64 GB DDR4): the lowest latency we sell, mirrored in software by the OS. For a working set that fits in 64 GB and commits all day. This is an HPE m710x cartridge, which has its own browser console.
  • Four SSDs in hardware RAID 10 (64 GB or 256 GB builds): striped mirrors on a RAID controller, no parity cost on writes, a failed drive costs no data. The usual choice for a transactional database.
  • RAID 5 or 6: more usable space from the same drives, slower on small writes. Fits reporting and archive schemas that mostly read.

Memory goes to 2 TB on the largest x86 machines and the biggest controller takes 24 drives, so a large schema can stay on one host. Each rack server and blade carries an out-of-band controller (HPE iLO, Dell iDRAC or a Supermicro BMC) with a browser console and virtual media, which is how you recover a box that will not boot after a bad config. For NVMe on more cartridge lines, see the NVMe dedicated servers.

Installing on Ubuntu

Ubuntu ships MariaDB in its own archive, and the MariaDB docs note that those packages enable the unix_socket plugin: root@localhost logs in as the operating system root, with no password to set. The block turns on ufw with SSH only, installs the server and mariadb-backup, and prints the version, the bind address and the data directory. Any step that does not succeed ends it with a STOP message.

# On Ubuntu, as a user with sudo. Firewall first, SSH kept open.
sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw &&
sudo ufw allow OpenSSH && sudo ufw --force enable &&
sudo apt update && sudo apt install -y mariadb-server mariadb-backup &&
systemctl is-active --quiet mariadb &&
sudo mariadb -e 'SELECT VERSION(), @@bind_address, @@datadir' ||
echo "STOP - the install did not complete, read the output above"
  1. Run sudo mariadb-secure-installation. The docs list what it does: remove anonymous accounts, refuse root logins from outside localhost, drop the test database, and optionally set a root password. They add that with unix_socket authentication a root password is usually unnecessary.
  2. Check that @@bind_address printed 127.0.0.1. The docs say many MariaDB packages bind there by default, so only local clients connect.
  3. To track a newer release series than Ubuntu carries, use the MariaDB Package Repository instead: download mariadb_repo_setup from r.mariadb.com, check it with sha256sum -c against the checksum on the docs page, and run it with --mariadb-server-version="mariadb-11.8" to pin a series (without it the script picks the latest GA). Then sudo apt install mariadb-server mariadb-client mariadb-backup. Check first that the script covers your Ubuntu release; the Ubuntu packages are the fallback when it does not.

Sizing the buffer pool and redo log

The block writes a drop-in file named 60-dedicated.cnf. MariaDB reads the files in an include directory in byte order of their names and the value read last wins, so it overrides the packaged 50-server.cnf. It sizes the pool at 70% of the RAM the kernel reports and the redo log at a quarter of that (capped at 16 GB, so the file cannot crowd a small array), restarts the server and prints both. If the file already exists the block refuses; to start again, delete the file, run sudo systemctl restart mariadb, then re-run the block.

f=/etc/mysql/mariadb.conf.d/60-dedicated.cnf
if [ -e "$f" ]; then
  echo "STOP - $f already exists, edit it instead of re-running"
elif ! grep -q 'mariadb.conf.d' /etc/mysql/mariadb.cnf; then
  echo "STOP - this config layout is not the Ubuntu one, see mariadbd --help --verbose"
else
  kb=$(awk '/^MemTotal/{print $(NF-1)}' /proc/meminfo) && [ -n "$kb" ] &&
  bp=$(( kb * 7 / 10 / 1024 )) && lf=$(( bp / 4 > 16384 ? 16384 : bp / 4 )) &&
  printf '[mysqld]\ninnodb_buffer_pool_size = %sM\ninnodb_log_file_size = %sM\n' "$bp" "$lf" |
    sudo tee "$f" >/dev/null &&
  sudo systemctl restart mariadb &&
  sudo mariadb -e 'SELECT @@innodb_buffer_pool_size DIV 1048576 AS pool_mb,
    @@innodb_log_file_size DIV 1048576 AS redo_mb' ||
  echo "STOP - see sudo journalctl -u mariadb -n 50"
fi

The ratios are ours, not MariaDB figures: 70% stays under the documented 80% ceiling and leaves room for the OS and connections. On the redo log, the docs say a larger log defers page writes and reduces write amplification, and can be several times the buffer pool on write-heavy loads. The cost is paid in crash recovery: when the redo left to apply is more than about a third of the buffer pool, InnoDB falls back to slower multi-batch recovery. A log a quarter of the pool or smaller stays under that mark.

Then measure. Once the server is warm, the docs suggest comparing Innodb_buffer_pool_reads with Innodb_buffer_pool_read_requests over a minute: if reads grow by under 1% of requests, the pool is big enough. A rising Innodb_buffer_pool_wait_free means the pool is too small, or that flushing is not keeping up. From MariaDB 10.9 the redo log can also be resized live with SET GLOBAL innodb_log_file_size; keep the file in step so the size survives a restart, and never delete ib_logfile0.

Accounts and remote access

Give every application its own account and database. Open the client with sudo MYSQL_HISTFILE=/dev/null mariadb, then run CREATE DATABASE app; then CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password'; and GRANT ALL ON app.* TO 'app'@'localhost';. That way the password reaches neither the shell history nor the client's own history file, /root/.mysql_history.

When the application runs on another machine, three things change together. Set bind-address in the drop-in file to this server's address (from 10.11 it also takes a comma-separated list), create the account for the app host only (for example 'app'@'203.0.113.10', never '%'), and open the port to that host alone with sudo ufw allow from 203.0.113.10 to any port 3306 proto tcp. The remote-access guide also recommends TLS for those connections. Never open 3306 to the whole internet.

Backups that restore

Two copies, two jobs. mariadb-backup takes a physical, online copy of InnoDB, Aria and MyISAM tables; only InnoDB is copied fully hot. Those files are not consistent until --prepare runs on them, which the docs require before any restore. mariadb-dump with --single-transaction writes SQL that is consistent for InnoDB tables only; MyISAM or MEMORY tables can still change during the dump. Copy the archives off this machine as well, for example by pulling them from another host with rsync -a, with no --delete.

# File /root/mariadb-backup.sh, run as root with: bash /root/mariadb-backup.sh
set -euo pipefail
umask 077
d=/var/backups/mariadb
s=$(date +%F-%H%M%S)
mkdir -p -m 700 "$d"
# physical copy, then the prepare step that makes it consistent
mariadb-backup --backup --user=root --target-dir="$d/phys-$s"
mariadb-backup --prepare --target-dir="$d/phys-$s"
tar -czf "$d/phys-$s.tar.gz" -C "$d" "phys-$s"
tar -tzf "$d/phys-$s.tar.gz" >/dev/null
rm -rf "$d/phys-$s"
# logical copy, portable across versions and machines
mariadb-dump --user=root --single-transaction --quick --routines --events \
  --all-databases | gzip > "$d/dump-$s.sql.gz"
gzip -t "$d/dump-$s.sql.gz"
# prune only after both copies above were written and tested
find "$d" -name 'phys-*.tar.gz' -mtime +7 -delete
find "$d" -name 'dump-*.sql.gz' -mtime +7 -delete
echo "backup OK $s"

Save it with chmod 700, create the log directory first (sudo install -d -m 700 /var/log/mariadb-backup), and put this line in the root crontab: 15 3 * * * umask 077; bash /root/mariadb-backup.sh > /var/log/mariadb-backup/last.log 2>&1. With set -e, any step that does not succeed ends the run before the prune, so old archives are never deleted on a bad night. A run that stops part-way can leave an unpacked phys- folder in /var/backups/mariadb that nothing prunes; read the log, then delete it. Each run needs free space of roughly the data size, on top of a week of archives.

  1. Restore as root (sudo -i), in one shell, with the same MariaDB version that took the backup; the docs say the mariadb-backup version must be compatible with the server version. These paths assume @@datadir printed /var/lib/mysql/; use yours if it differs. Pick the archive and test it: f=/var/backups/mariadb/phys-2026-10-30-031500.tar.gz; tar -tzf "$f" >/dev/null && echo ok. Continue only when it prints ok.
  2. Unpack it to a fresh directory: mkdir -m 700 /var/restore && tar -xzf "$f" -C /var/restore. The mkdir refuses if /var/restore is left over from an earlier run; remove it first.
  3. Stop the server and set the live data aside, keeping its permissions: systemctl stop mariadb && [ ! -e /var/lib/mysql.previous ] && mv /var/lib/mysql /var/lib/mysql.previous && install -d -o mysql -g mysql -m "$(stat -c %a /var/lib/mysql.previous)" /var/lib/mysql && echo ok. If an old /var/lib/mysql.previous blocks it, move that elsewhere first.
  4. Copy the prepared backup in, reset owners and start: mariadb-backup --copy-back --target-dir="/var/restore/$(basename "$f" .tar.gz)" && chown -R mysql:mysql /var/lib/mysql && systemctl start mariadb.
  5. Check the application. To roll back, keeping the restored copy aside rather than deleting it: `systemctl stop mariadb && [ -d /var/lib/mysql.previous ] && mv /var/lib/mysql "/var/lib/mysql.rejected-$(date +%F-%H%M%S)" && mv /var/lib/mysql.previous /var/lib/mysql && systemctl start mariadb || echo "STOP - a step did not complete; look at /var/lib/mysql, /var/lib/mysql.previous and the mysql.rejected copies before retrying". When the restore is confirmed, delete /var/lib/mysql.previous and /var/restore`.

Upgrades and release series

Minor releases arrive with apt upgrade. The mariadb-upgrade page says Debian and Ubuntu packages run mariadb-upgrade for you after a package upgrade, once the new server has started; on other setups you run sudo mariadb-upgrade yourself. For a major move, the docs publish one guide per hop (10.11 to 11.4, 11.4 to 11.8, 11.8 to 12.3): take a backup with the old version of mariadb-backup, point the repository at the new series, stop, remove the old server package, install the new one, drop removed options from your config, start, then run mariadb-upgrade.

LTS seriesGACommunity binaries until
10.1116 Feb 202316 Feb 2028
11.429 May 202429 May 2029
11.84 Jun 20254 Jun 2028
12.328 May 202612 Jun 2029

Dates from the MariaDB Foundation maintenance policy, which also says 10.6 reached its community end on 6 July 2026. Releases up to 11.4 got 5 years of binaries; later LTS series get 3, plus 2 years of critical and security fixes in source releases.

Licence, and where this setup stops

MariaDB Server is licensed under GPL version 2, and the Foundation states it will stay that way. Our general reading, not legal advice: the licensing FAQ says the GPL affects only code you distribute, so running MariaDB for your own applications, including ones that serve customers over the network, carries no source obligation. GPLv2 has no network clause. If you distribute copies of MariaDB, modified or not, for example inside an appliance, you must pass on the corresponding source under GPLv2. The C, Java and ODBC client libraries are LGPL 2.1 or later.

One machine is one failure domain: RAID protects against a dead drive, not a dead board or a dropped table. For failover, run a replica on a second server (mariadb-backup can seed one). If PostgreSQL is the better engine for your app, the same reasoning is laid out for PostgreSQL on its own machine; for a cache in front of MariaDB, see Redis on a dedicated server.

Questions

How much RAM should a MariaDB machine have?

Enough for the data your queries touch every day, plus the OS and connections. The MariaDB docs put the buffer pool at up to 80% of memory on an InnoDB-only server, so by our arithmetic a 64 GB machine gives InnoDB roughly 45 to 51 GB.

Ubuntu packages or the MariaDB repository?

Ubuntu packages are the simplest and receive security updates through apt. The MariaDB Package Repository lets you choose and pin a release series such as 11.8 with --mariadb-server-version. Either way, Debian and Ubuntu packages run mariadb-upgrade after a package upgrade.

Is mariadb-dump enough as a backup?

For small databases it can be, and its SQL output moves between versions and machines. It is consistent only for InnoDB tables with --single-transaction, and restoring a large dump is slow. mariadb-backup copies the files hot and restores by copying them back after the prepare step; keeping both covers more cases.

Where are the servers, and how fast is one online?

New York, Miami, San Francisco, Amsterdam and Bucharest, on our own network, AS19624; each build lists its cities. Ready servers go live about 30 minutes once payment is approved; a machine configured to order takes 4 to 24 hours.

Give MariaDB the whole machine

Pick the array, size the memory to the working set, and install MariaDB with root on Linux.

Configure a database server

Related on Server Room

Other use cases