Why your database wants a machine of its own
A database feels slow for two reasons: the data it needs is not in memory, so it reads from disk, or every save waits for the disk to confirm the write. MariaDB's InnoDB engine keeps hot data in its buffer pool, and in its default setup it pushes its redo log to disk on every commit, which is what keeps committed data safe through a crash.
On a shared host, both of those depend on what other people are doing. On a machine you rent whole, they depend on you. The drive is yours alone, with no other customer's virtual disks on it, and you can give the buffer pool as much RAM as the box has to spare.
Choosing the server: memory first, then drives
Start from how much of your data the app reads every day, because that is what you want in memory. Then pick drives for how hard it writes. Our NVMe dedicated servers are HPE Moonshot cartridges: a complete server each, with NVMe drives that reach the processor over PCIe.
| Cartridge line | Cores | Memory | Where |
|---|---|---|---|
| Intel Xeon E3-1585L v5 | 4 | 32 to 64 GB | All five cities |
| Intel Xeon D-1548 / D-1587 | 8 / 16 | 32 to 128 GB | All five cities |
| Intel Xeon E-2286M | 8 | 32 to 64 GB | Bucharest only |
Every line takes one NVMe drive, sized between 240 GB and 3.84 TB, or two of the same size in software RAID 1, so a dead drive costs you a swap rather than your data. The service agreement has a failed drive replaced within four hours of your call or chat. There is no hardware RAID controller on these cartridges, though. If your data has outgrown 128 GB of memory, or you want RAID 10 on a real controller, look at the enterprise blade and rack servers: hardware RAID with up to 24 bays, memory up to 2 TB, and a browser console on every one. Their drives are SATA or SAS behind the controller, not NVMe, so you trade some latency for more drives and RAID 10.
Take a racked server as it stands and it is yours about 30 minutes once your order has been approved. A build you configure takes 4 to 24 hours when we hold the parts, and longer when one has to be bought in. All five cities are on the locations page.
Up and running in an evening
This block switches the firewall on with only SSH allowed, installs MariaDB and its backup tool from Ubuntu's own packages, then shows you the version, the address it listens on and where it keeps its data. If any step goes wrong it stops and says so.
# Ubuntu, logged in as your own sudo user
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() AS version, @@bind_address AS listens_on, @@datadir AS data' ||
echo "STOP - something above went wrong, fix it before going further"
- Run
sudo mariadb-secure-installationand answer its questions. According to the MariaDB docs it removes the anonymous accounts and thetestdatabase and stops root from logging in from other machines. - You will notice it does not insist on a root password. On Ubuntu,
root@localhostsigns in through theunix_socketplugin, which trusts the system's root user, and the docs say a password is usually not needed with it. Usesudo mariadbto get in. - Look at the
listens_onvalue. If it reads 127.0.0.1, only programs on this server can connect, and MariaDB notes that lots of packaged builds start out on that address. Leave it that way until another machine needs access. - Want a newer series than Ubuntu carries? MariaDB publishes a repository script,
mariadb_repo_setup. Check its sha256 checksum against the one listed in the docs before you run it, and hold it to one series, for example--mariadb-server-version="mariadb-11.4". It has to support your Ubuntu release; if it does not, stay with Ubuntu's packages.
Hand InnoDB the memory you are paying for
Out of the box MariaDB gives the buffer pool just 128 MiB, which wastes a dedicated machine. MariaDB's system variable reference allows the pool as much as 80 percent of the machine's memory when InnoDB holds most of your tables. The block below sets it to 70% of your RAM and the redo log to a quarter of that, at most 16 GB. Those two ratios are our own cautious picks, not MariaDB numbers: they leave headroom for the system and for connections.
conf=/etc/mysql/mariadb.conf.d/70-memory.cnf
if [ -e "$conf" ]; then
echo "STOP - $conf is already there; change it by hand"
elif ! grep -q 'mariadb.conf.d' /etc/mysql/mariadb.cnf; then
echo "STOP - not the usual Ubuntu layout; mariadbd --help --verbose lists the files read"
else
total_kb=$(awk '/^MemTotal/{print $(NF-1)}' /proc/meminfo) && [ -n "$total_kb" ] &&
pool=$(( total_kb * 7 / 10 / 1024 )) &&
redo=$(( pool / 4 > 16384 ? 16384 : pool / 4 )) &&
printf '[mysqld]\ninnodb_buffer_pool_size = %sM\ninnodb_log_file_size = %sM\n' "$pool" "$redo" |
sudo tee "$conf" >/dev/null &&
sudo systemctl restart mariadb &&
sudo mariadb -e 'SHOW GLOBAL VARIABLES WHERE Variable_name IN
("innodb_buffer_pool_size", "innodb_log_file_size")' ||
echo "STOP - read sudo journalctl -u mariadb -n 50"
fi
It writes a small file, 70-memory.cnf, next to Ubuntu's own 50-server.cnf. MariaDB reads those files in name order and the last value wins, so yours applies. An existing file is left alone; to redo it, delete the file, restart MariaDB, and run the block again.
Why not a giant redo log? The InnoDB docs explain that a bigger one saves disk writes on busy tables, but makes recovery after a crash slower once the log still waiting to be applied grows past roughly one third of the pool's size. Keeping it at a quarter avoids that. After a day of real traffic, check SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%'; twice, a minute apart. The docs say that if disk reads grew by less than 1% of read requests, the pool is large enough.
Let your app in, keep everyone else out
Make one account per application, limited to its own database. Start the client with sudo env MYSQL_HISTFILE=/dev/null mariadb and run CREATE DATABASE shop;, then CREATE USER 'shop'@'localhost' IDENTIFIED BY 'choose-a-strong-password'; and GRANT ALL ON shop.* TO 'shop'@'localhost';. Typed there rather than on the shell command line, the password stays out of your shell history, and pointing MYSQL_HISTFILE at /dev/null keeps the client from saving it in /root/.mysql_history too.
If your website runs on a different server, do three things. Add bind-address to 70-memory.cnf with this server's address and restart. Create the account for that one web server, such as 'shop'@'198.51.100.7', rather than for any host. Then let only that machine through the firewall: sudo ufw allow proto tcp from 198.51.100.7 to any port 3306. MariaDB's remote-access guide also suggests encrypting those connections with TLS. Port 3306 should never be open to everyone.
Backups you have actually tested
This script keeps two kinds of copy. mariadb-backup copies InnoDB, Aria and MyISAM tables while the server keeps running (InnoDB hot, with only brief locks; the docs call it nearly non-blocking), and its --prepare step turns them into a consistent data directory; the docs say a copy that has not been prepared must not be restored. mariadb-dump writes plain SQL, which is consistent with --single-transaction for InnoDB tables, though not for MyISAM or MEMORY tables. With set -e any error ends the run, so old copies are only deleted after both new ones exist and pass a check. An interrupted run can leave an unpacked files- folder behind in /var/backups/mariadb, which the clean-up line never touches: check the log, then remove it by hand. Keep free space of about your data size for each run, plus the week of archives.
# Save as /root/backup-mariadb.sh and run it as root: bash /root/backup-mariadb.sh
set -euo pipefail
umask 077
dir=/var/backups/mariadb
stamp=$(date +%F-%H%M%S)
mkdir -p -m 700 "$dir"
# 1. hot physical copy of the data files, made consistent by --prepare
mariadb-backup --backup --user=root --target-dir="$dir/files-$stamp"
mariadb-backup --prepare --target-dir="$dir/files-$stamp"
tar -czf "$dir/files-$stamp.tar.gz" -C "$dir" "files-$stamp"
tar -tzf "$dir/files-$stamp.tar.gz" >/dev/null
rm -rf "$dir/files-$stamp"
# 2. SQL dump, handy for moving one database or changing versions
mariadb-dump --user=root --all-databases --single-transaction --quick \
--routines --events | gzip > "$dir/sql-$stamp.sql.gz"
gzip -t "$dir/sql-$stamp.sql.gz"
# 3. only now, with both new copies checked, drop anything older than 7 days
find "$dir" \( -name 'files-*.tar.gz' -o -name 'sql-*.sql.gz' \) -mtime +7 -delete
echo "backup OK $stamp"
Make it private with sudo chmod 700 /root/backup-mariadb.sh, make its log folder with sudo mkdir -m 700 /var/log/backup-mariadb, then open sudo crontab -e and add 30 2 * * * umask 077; bash /root/backup-mariadb.sh > /var/log/backup-mariadb/run.log 2>&1 on a line of its own. A copy kept on the same machine will not survive losing that machine, so pull the archives to somewhere else every day, for example with rsync -a from another host, and never with --delete.
Restoring takes a few commands typed as root. Run sudo -i once and do every step in that same session, because the steps share variables. Use the MariaDB version that made the copy, since the docs require a compatible mariadb-backup.
- Name the archive and your data directory, then check the archive:
pick=/var/backups/mariadb/files-2026-10-30-023000.tar.gz; dd=/var/lib/mysql; tar -tzf "$pick" >/dev/null && echo good. Setddto whatever the install block printed asdata, without the trailing slash it shows; then rundd=${dd%/}to be sure. Do not go further unless it says good. - Unpack it into a new folder:
mkdir -m 700 /root/mariadb-restore && tar -xzf "$pick" -C /root/mariadb-restore. Themkdirrefuses if that folder is left from an earlier try; delete it and repeat. - Stop MariaDB and park the current data, keeping it intact: `systemctl stop mariadb && [ ! -e "$dd.before-restore" ] && mv "$dd" "$dd.before-restore" && mkdir "$dd" && chown --reference="$dd.before-restore" "$dd" && chmod --reference="$dd.before-restore" "$dd" && echo good
. If an older.before-restore` folder stops it, move that one aside and repeat. - Copy the prepared files in, give them back to MariaDB and start it:
mariadb-backup --target-dir="/root/mariadb-restore/$(basename "$pick" .tar.gz)" --copy-back && chown -R --reference="$dd.before-restore" "$dd" && systemctl start mariadb. - Test your app. To undo, `systemctl stop mariadb && [ -d "$dd.before-restore" ] && mv "$dd" "/root/mariadb-restore/rejected-$(date +%s)" && mv "$dd.before-restore" "$dd" && systemctl start mariadb || echo "STOP - something above did not finish; check what is in $dd and whether $dd.before-restore still exists before trying again"
brings the parked data back. When all is well, remove the.before-restorefolder and/root/mariadb-restore`.
Staying on a supported version
Pick a long-term (LTS) series and plan the next move before it expires. The MariaDB Foundation lists community binaries for 10.11 until 16 February 2028, 11.8 until 4 June 2028, 11.4 until 29 May 2029 and 12.3 until 12 June 2029; support for 10.6 ended on 6 July 2026. LTS series after 11.4 get three years of binaries and then two more years of critical fixes in source form.
Small updates come with sudo apt upgrade, and on Ubuntu the server packages take care of mariadb-upgrade themselves once the new version starts. For a jump between series, MariaDB writes a separate guide for every step, from 10.11 up through 11.4 and 11.8 to 12.3. Each follows one outline: back up with the mariadb-backup you have now, point the repository at the next series, stop MariaDB, uninstall the old server and put the new one in, clear out settings that version no longer accepts, start it, and run sudo mariadb-upgrade wherever that is not done for you.
The licence, and when to choose something else
MariaDB Server comes under the GNU GPL v2, and the Foundation has said it will remain free and open source under that licence. This is how we read it, as general guidance and not legal advice. MariaDB's licensing FAQ says the GPL only concerns code you distribute, and that using it inside your organisation, or connecting to a service that runs it, is free. Running it behind your own website or app therefore asks nothing of you, and GPLv2 has no clause for software offered over a network. Hand copies of MariaDB to someone else, changed or unchanged, as part of a product you ship, and you must offer them the source code under GPLv2 too. The client libraries for C, Java and ODBC use the LGPL, version 2.1 or later.
One server is still one server: RAID 1 saves you from a dead drive, not from a mistaken DROP TABLE or a failed board, which is why the backups above matter. If you need a second machine standing by, MariaDB replication can run on it, and mariadb-backup can seed the copy. Comparing engines? Read how we set up PostgreSQL on a dedicated server, and if pages load slowly because of repeated queries, a cache like Redis on its own server may help more than a bigger database box.
Questions people ask
- How big a server does a MariaDB database need?
- Aim for memory that holds the data your app reads every day, plus room for the system. MariaDB lets the buffer pool take as much as 80 percent of memory on a box that runs mostly InnoDB. Our NVMe cartridges go to 128 GB of memory; past that, the enterprise lines go to 2 TB.
- Do I need hardware RAID for MariaDB?
- Not necessarily. Two NVMe drives in software RAID 1 keep a copy of every write on both drives, and a failed one is swapped without losing data. Choose hardware RAID 10 on an enterprise server when you need more drives or more space than two NVMe drives give; those servers use SATA or SAS drives behind the controller rather than NVMe.
- Should MariaDB be reachable from the internet?
- No. Keep it on 127.0.0.1 when the app runs on the same machine. When it does not, listen on the server's address, tie the account to your web server's address, and allow just that address through ufw on port 3306.
- Which backup tool should I use, mariadb-backup or mariadb-dump?
- Both, for different jobs. mariadb-backup is fast to take and restore for the whole server, but must be prepared first and restored with a compatible version. mariadb-dump gives you SQL you can load into another version or another machine.