A MariaDB Galera cluster keeps three database nodes in sync, so any node can accept writes and the cluster keeps running when one node goes down. This guide covers a full MariaDB Galera cluster setup on three Linux VPSs: install the packages, write the wsrep configuration, bootstrap the first node, then join the others and check that every node is Synced.
You will work on all three servers. The examples use 203.0.113.10 (node1), 203.0.113.11 (node2) and 203.0.113.12 (node3). Replace them with your own VPS IPs.
Before you start
- Three Linux VPSs running Ubuntu 22.04/24.04, Debian 12, or AlmaLinux/Rocky 8–9.
- Root, or a user with
sudo. - The IP addresses of all three nodes written down, and shell access to each.
- Working time sync. Galera rejects nodes whose clocks drift, so confirm
chronyorsystemd-timesyncdis active on every node. - Ports 3306 (SQL), 4567 (cluster communication), 4568 (IST) and 4444 (SST) open between the nodes only.
Tip: If your VPSs share a private network, use those addresses for wsrep_cluster_address and keep the public IPs for your applications. Mixing public and private addresses inside one cluster causes connection failures.
Warning: Galera applies cluster writes on every node. Back up anything already stored on these servers, because joining a node runs a State Snapshot Transfer (SST) that overwrites its existing data directory.
Install MariaDB and the Galera provider
Run this on all three nodes.
On Ubuntu and Debian:
sudo apt update
sudo apt install -y mariadb-server galera-4 rsyncOn AlmaLinux and Rocky Linux:
sudo dnf install -y mariadb-server mariadb-server-galera rsyncThen stop MariaDB so it does not start with a default configuration before you edit the cluster settings:
sudo systemctl stop mariadbFind the Galera provider library, since the path differs between distributions:
ls /usr/lib/galera/libgalera_smm.so /usr/lib64/galera-4/libgalera_smm.so 2>/dev/nullNote the path that exists — you need it in the next step. If neither exists, install the provider package for your distribution and check the MariaDB Galera documentation for your release.
Write the wsrep configuration
On Ubuntu and Debian, create /etc/mysql/mariadb.conf.d/60-galera.cnf. On AlmaLinux and Rocky, create /etc/my.cnf.d/60-galera.cnf. The contents are the same:
[mysqld]
default_storage_engine = InnoDB
innodb_autoinc_lock_mode = 2
innodb_flush_log_at_trx_commit = 0
bind-address = 0.0.0.0
[galera]
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_cluster_name = app_galera
wsrep_cluster_address = gcomm://203.0.113.10,203.0.113.11,203.0.113.12
wsrep_node_name = node1
wsrep_node_address = 203.0.113.10
wsrep_sst_method = rsyncCopy this file to all three nodes and change exactly two lines on node2 and node3:
wsrep_node_name—node2, thennode3.wsrep_node_address— the node's own IP.
Keep wsrep_cluster_address identical on every node; it lists every member so any node can find the cluster after a restart. If your provider library sits in /usr/lib64/galera-4/, change wsrep_provider to that path.
Open the firewall ports
With firewalld:
sudo firewall-cmd --permanent --add-port=3306/tcp --add-port=4567/tcp --add-port=4568/tcp --add-port=4444/tcp
sudo firewall-cmd --reloadWith ufw, allow the cluster ranges from the other node IPs instead of opening them to the world:
sudo ufw allow from 203.0.113.10 to any port 4567 proto tcp
sudo ufw allow from 203.0.113.11 to any port 4567 proto tcp
sudo ufw allow from 203.0.113.12 to any port 4567 proto tcpRepeat for ports 4568 and 4444, and open 3306 only to the application servers that need it.
On AlmaLinux and Rocky, SELinux may block MariaDB from listening on the Galera ports:
sudo semanage port -a -t mysqld_port_t -p tcp 4567
sudo semanage port -a -t mysqld_port_t -p tcp 4568
sudo semanage port -a -t mysqld_port_t -p tcp 4444Bootstrap the first node
The first node has to start alone to create the cluster. On node1 only:
sudo galera_new_clusterIf that command is missing on your distribution, start it this way instead:
sudo systemctl set-environment MYSQLD_OPTS="--wsrep-new-cluster"
sudo systemctl start mariadbConfirm node1 is running as a one-node Primary cluster:
sudo mariadb -e "SHOW STATUS LIKE 'wsrep_cluster_size';"You should see wsrep_cluster_size at 1. If it shows 0, read the error log at /var/log/mysql/error.log (Debian/Ubuntu) or /var/log/mariadb/mariadb.log (RHEL family) before continuing.
Warning: Run the bootstrap command on one node only, and never on a node that is already part of a running cluster. Starting two separate Primaries on the same data set splits the cluster and can leave you with conflicting writes that must be merged by hand.
Join the remaining nodes
On node2 and node3, start MariaDB normally — do not bootstrap:
sudo systemctl start mariadbEach node connects to the cluster, requests an SST from an existing member and then reports Synced. The first join copies the whole data set, so it can take a while on a large database. Watch progress with:
sudo mariadb -e "SHOW STATUS LIKE 'wsrep_local_state_comment';"Joining, Initialized or Joining, State transfer in progress means the transfer is still running. Synced means the node is live and serving.
Finally, remove the environment override if you set it during bootstrap:
sudo systemctl unset-environment MYSQLD_OPTSCheck it works: Galera cluster status
On any node, look at the full status set:
sudo mariadb -e "SHOW STATUS WHERE Variable_name IN ('wsrep_cluster_size','wsrep_cluster_status','wsrep_connected','wsrep_ready','wsrep_local_state_comment','wsrep_incoming_addresses');"What you want to see on a healthy three-node cluster:
wsrep_cluster_size=3wsrep_cluster_status=Primarywsrep_connected=ONwsrep_ready=ONwsrep_local_state_comment=Syncedon every nodewsrep_incoming_addresseslists all three IPs
Now prove that writes replicate. On node1:
sudo mariadb -e "CREATE DATABASE clustertest;"
sudo mariadb -e "CREATE TABLE clustertest.t (id INT PRIMARY KEY, note VARCHAR(50)) ENGINE=InnoDB;"
sudo mariadb -e "INSERT INTO clustertest.t VALUES (1,'from node1');"On node2 and node3:
sudo mariadb -e "SELECT * FROM clustertest.t;"All three must return the same row. Remove the test data when you are done:
sudo mariadb -e "DROP DATABASE clustertest;"Troubleshooting
- MariaDB will not start, log says
Failed to open gcommor cannot open the provider. Thewsrep_providerpath is wrong for your distribution. Runlson the usual paths and correct the line in60-galera.cnf. - A joining node sits at
Joiningfor a long time, then fails. Check free disk space, that port 4444 and 4568 are reachable from the donor, and thatrsyncis installed on both ends. The error log names the failing stage. wsrep_cluster_sizeis 1 on a node that should have joined. The node started as its own Primary, usually because it was bootstrapped twice or lost contact with the others. Stop it, confirm the firewall andwsrep_cluster_address, then start it again without the bootstrap flag.- Error 1045 during SST. You switched
wsrep_sst_methodtomariabackupwithout matchingwsrep_sst_authon all nodes. Make the credentials identical everywhere, or go back torsync. - Tables look inconsistent after a restart. Galera only replicates InnoDB. Convert leftover MyISAM tables with
ALTER TABLE name ENGINE=InnoDB;and check the error log for warnings about non-transactional writes.
Next steps
- Install and secure MariaDB, and allow remote access safely before you point applications at the cluster.
- Install MariaDB on AlmaLinux and Rocky Linux if you built the cluster on the RHEL family.
- Tune MySQL and MariaDB memory settings for a small VPS so three nodes are not fighting for RAM.
- Troubleshoot MySQL replication lag and broken replicas for the checks that also apply to Galera flow control issues.
