
Large sites that need High Availability cannot rely on a single database server. Galera Cluster turns MariaDB into a synchronous multi-master system across many nodes: if one dies, the others take over instantly, and data stays identical on every node in real time.
This guide builds a 3-node Galera Cluster on Ubuntu 22.04 — installing MariaDB, editing galera.cnf, bootstrapping the first node, joining the others, and checking cluster health plus failover.
Prerequisites: Three Ubuntu 22.04 VPS instances (Galera requires an odd number — at least 3 — to avoid split-brain), 2 GB+ RAM each, and a fast network between them (ping < 5 ms in the same region).
What is Galera Cluster
Galera is a replication library that turns MariaDB / MySQL into an active-active cluster: every node is writable, and every COMMIT replicates to all nodes before finalizing (synchronous). As a result, data is 100% consistent across nodes with no replication lag like Master-Slave.
Galera vs Master-Slave Replication
| Topic | Galera | Master-Slave |
|---|---|---|
| Replication | Synchronous (sync before commit) | Asynchronous (slight lag) |
| Writes | Any node | Master only |
| Failover | Automatic / instant | Manual slave promotion |
| Data Consistency | 100% identical | Eventually consistent |
| Best for | HA, e-commerce, sticky sessions | Read-heavy, reporting, analytics |
Topology — Preparing 3 Nodes
Assume three VPS instances:
node1— 10.0.0.11 (will bootstrap the cluster)node2— 10.0.0.12node3— 10.0.0.13
Open these ports between nodes: 3306 (clients), 4567 (Galera replication), 4568 (IST), 4444 (SST).
Step 1 — Install MariaDB on Every Node
Run on all 3 nodes:
sudo apt update sudo apt install -y mariadb-server galera-4 sudo systemctl stop mariadb
Confirm the version (should be 10.6+):
mariadb --version
Step 2 — Edit /etc/mysql/mariadb.conf.d/60-galera.cnf on Every Node
Create the file on each node:
sudo nano /etc/mysql/mariadb.conf.d/60-galera.cnf
Paste the following — change wsrep_node_address per node:
[galera] wsrep_on = ON wsrep_provider = /usr/lib/galera/libgalera_smm.so wsrep_cluster_address = gcomm://10.0.0.11,10.0.0.12,10.0.0.13 wsrep_cluster_name = "asiagb_cluster" wsrep_node_address = 10.0.0.11 # change per node wsrep_node_name = "node1" # change per node wsrep_sst_method = rsync binlog_format = row default_storage_engine = InnoDB innodb_autoinc_lock_mode = 2 bind-address = 0.0.0.0
Step 3 — Bootstrap the First Node (node1)
The first node opens the cluster with a special command:
sudo galera_new_cluster
Check status:
sudo mysql -e "SHOW STATUS LIKE 'wsrep_cluster_size';"
You should see wsrep_cluster_size = 1 while only one node is up.
Step 4 — Join node2 and node3
On node2 and node3:
sudo systemctl start mariadb
Back on node1:
sudo mysql -e "SHOW STATUS LIKE 'wsrep_cluster_size';"
It should now be 3, meaning all nodes are in the cluster.
Step 5 — Test Replication
On node1:
sudo mysql -e "CREATE DATABASE galera_test;" sudo mysql -e "CREATE TABLE galera_test.t1 (id INT PRIMARY KEY, name VARCHAR(50));" sudo mysql -e "INSERT INTO galera_test.t1 VALUES (1, 'hello from node1');"
From node2 or node3:
sudo mysql -e "SELECT * FROM galera_test.t1;"
The row should appear immediately — proving the cluster works.
Step 6 — Cluster Health Checks
sudo mysql -e "SHOW STATUS LIKE 'wsrep_%';" | grep -E "cluster_size|cluster_status|connected|ready|local_state"
Watch these values:
wsrep_cluster_size= 3 (active nodes)wsrep_cluster_status= Primary (healthy quorum)wsrep_connected= ONwsrep_ready= ONwsrep_local_state_comment= Synced
Putting HAProxy in Front of the Cluster
Applications should connect through HAProxy rather than targeting a single Galera node directly. This makes failover transparent and distributes write load evenly across all nodes.
Install HAProxy on a separate load-balancer machine (or on any cluster node for testing):
sudo apt install haproxy -y
Add a backend block to /etc/haproxy/haproxy.cfg:
frontend mysql_front
bind *:3306
mode tcp
default_backend mysql_cluster
backend mysql_cluster
mode tcp
balance leastconn
option mysql-check user haproxy_check
server node1 10.0.0.11:3306 check
server node2 10.0.0.12:3306 check
server node3 10.0.0.13:3306 checkCreate the health-check user on node1:
sudo mysql -e "CREATE USER 'haproxy_check'@'%';" sudo mysql -e "FLUSH PRIVILEGES;"
Restart HAProxy and verify:
sudo systemctl restart haproxy sudo systemctl status haproxy
Why leastconn? Galera uses synchronous write locks, so the node with the shortest queue absorbs a new connection better than pure round-robin, which could send traffic to a node already committing a heavy transaction.
Backing Up a Galera Cluster with Mariabackup
Galera is not a backup system — a DROP TABLE executed on any node replicates to all nodes instantly. You still need a dedicated backup strategy. The recommended tool is Mariabackup, which performs a hot backup without stopping the cluster:
sudo apt install mariadb-backup -y
Run the backup on the least-loaded node:
sudo mariabackup --backup \
--target-dir=/var/backup/galera/$(date +%Y%m%d) \
--user=rootPrepare the backup before restoring:
sudo mariabackup --prepare \
--target-dir=/var/backup/galera/20260608| Method | Pros | Cons |
|---|---|---|
| Mariabackup (hot) | No cluster downtime, full InnoDB support | Large file size |
| mysqldump | Readable SQL, easy restore | Slow on large databases |
| VPS Snapshot | Restore entire node quickly | Requires crash-recovery before bootstrap |
Monitoring Galera with Prometheus and mysqld_exporter
Good monitoring lets you detect problems before they escalate. Install mysqld_exporter on every node and configure Prometheus to scrape these key metrics:
mysql_global_status_wsrep_cluster_size— should always equal 3mysql_global_status_wsrep_ready— 1 = ready, 0 = problemmysql_global_status_wsrep_local_recv_queue_avg— sustained values above 2 indicate that node is lagging behindmysql_global_status_wsrep_flow_control_paused— fraction of time the cluster is paused for sync; should stay near 0
Example Prometheus alert rules to add:
- alert: GaleraClusterNodeMissing
expr: mysql_global_status_wsrep_cluster_size < 3
for: 1m
labels:
severity: critical
annotations:
summary: "Galera node count dropped below 3"
- alert: GaleraNodeNotReady
expr: mysql_global_status_wsrep_ready == 0
for: 30s
labels:
severity: critical
annotations:
summary: "Galera node not ready on {{ $labels.instance }}"If Prometheus is not yet in your stack, Netdata installs in one command and includes a built-in Galera plugin:
wget -O /tmp/netdata-kickstart.sh https://get.netdata.cloud/kickstart.sh sh /tmp/netdata-kickstart.sh
Avoid Split-Brain
⚠️ Never run only 2 nodes. Galera needs an odd quorum (3, 5, 7). With 2 nodes, losing one makes the survivor go read-only (quorum lost). Always run at least 3.
If the whole cluster goes down, bootstrap only on the node with the highest seqno:
sudo cat /var/lib/mysql/grastate.dat
Post-setup Checklist
- Always use an odd number of nodes — never 2 or 4
- Open firewall only for 3306, 4444, 4567, 4568 between nodes
- Keep inter-node latency low (< 5 ms) — not suitable for cross-region
- Front the cluster with HAProxy / ProxySQL — don't let apps target a single node
- Still take regular backups — a cluster is not a backup (DROP TABLE replicates instantly!)
- Monitor
wsrep_cluster_sizeandwsrep_local_state_commentwith Netdata or Prometheus
Need Multiple VPS for a Galera Cluster?
AsiaGB VPS from 500 THB/month with SSD. Spin up multiple instances in the same datacenter with sub-millisecond intra-DC latency — ideal for clusters.
View VPS Plans