Evernode instances merged into mariadb galera cluster with maria-backup sync
Posted: Sun Apr 05, 2026 11:10 pm

https://i.imgur.com/mdEdsN4.png
Docker Demo (ssh on userport, username: evernode password: default)
evermariagalera/evermariagalera:latest
using up all ports as tcp ports, mesh, user, gptcp1 and gptcp2
Minimum recommended size of cluster: 3 (cuz if one of them dies there's still a majority telling us which data is correct)
dbport is gptcp1
Initial Clustered Maria DB Galera with maria-backup sync project. This code is with SSH, next step is to make a nice frontend.
This is using env.vars to source $GPTCP1 and $GPTCP2, you need to adjust them manually if you use a node without env.vars
config file: /etc/mysql/conf.d/galera.cnf
Dockerfile
Code: Select all
FROM everweb/test:latest
ENV DEBIAN_FRONTEND=noninteractive \
TZ=UTC
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl gnupg ca-certificates software-properties-common && \
curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | bash -s -- --mariadb-server-version="mariadb-11.4" && \
apt-get update && \
apt-get install -y --no-install-recommends \
mariadb-server \
mariadb-client \
mariadb-backup \
galera-4 \
rsync \
openssh-server \
openssl sudo nano&& \
apt-get purge -y gnupg software-properties-common && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
RUN mkdir -p /var/lib/mysql /var/run/mysqld /var/run/sshd /etc/mysql/conf.d && \
chown -R mysql:mysql /var/lib/mysql /var/run/mysqld && \
chmod 755 /var/run/mysqld
RUN echo "Port 22" >> /etc/ssh/sshd_config && \
echo "PermitRootLogin no" >> /etc/ssh/sshd_config && \
echo "ListenAddress 0.0.0.0" >> /etc/ssh/sshd_config
RUN useradd -m -s /bin/bash evernode && \
echo "evernode:default" | chpasswd && \
usermod -aG sudo evernode && \
echo "evernode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
COPY galera.cnf /etc/mysql/conf.d/galera.cnf
COPY start.sh /start.sh
RUN chmod +x /start.sh
# Volume
VOLUME /var/lib/mysql
ENTRYPOINT ["/start.sh"]
Code: Select all
[mysqld]
# mysql port shared with wsrep_sst_method = mysqldump/mariabackup
port = 3306 # peer port
bind-address = 0.0.0.0 # Listen on all interfaces (or set to your private IP for security)
# ==================== Galera Settings ====================
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_cluster_name = galeracluster
#you only need a few servers added to this list.
wsrep_cluster_address = gcomm://1.1.1.1
# SST Method
wsrep_sst_method = mariabackup
wsrep_sst_auth = "sst_user:__RANDOMPWD__"
wsrep_sst_receive_address = __PUBLICIP__:3306
# Node identification — change per node
wsrep_node_name = node1
wsrep_node_address = __PUBLICIP__
wsrep_provider_options = "gcache.size=4G;gmcast.listen_addr=tcp://0.0.0.0:4567;ist.recv_addr=__PUBLICIP__:4568;ist.recv_bind=0.0.0.0:4568;gmcast.peer_timeout=PT20S;evs.keepalive_period=PT5S;evs.suspect_timeout=PT60S;evs.inactive_timeout=PT2M;evs.inactive_check_period=PT10S;evs.install_timeout=PT2M;evs.send_window=1024;evs.user_send_window=512"
binlog_format = ROW
default_storage_engine = InnoDB
innodb_autoinc_lock_mode = 2
innodb_flush_log_at_trx_commit = 0
innodb_doublewrite = 1
Code: Select all
#!/bin/bash
set -e
echo "=== Container starting ==="
# Generate SSH keys if missing
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
echo "Generating SSH keys..."
ssh-keygen -A
fi
CFG_FILE="/contract/cfg/hp.cfg"
SSHD_CONFIG="/etc/ssh/sshd_config"
# Extract userport
userport=$(awk '
$0 ~ /"user"/ { user_block=1 }
user_block && $0 ~ /"port"/ {
gsub(/[ ,]/, "", $2);
gsub(/[^0-9]/, "", $2);
print $2;
exit
}
' "$CFG_FILE")
if [[ -z "$userport" ]]; then
echo "Could not extract user port from $CFG_FILE"
exit 1
fi
echo "Using SSH port: $userport"
# Add port if missing
if ! grep -q "^Port $userport" "$SSHD_CONFIG"; then
echo "Adding Port $userport"
echo "Port $userport" >> "$SSHD_CONFIG"
fi
# Extract meshport
meshport=$(awk '
$0 ~ /"mesh"/ { mesh_block=1 }
mesh_block && $0 ~ /"port"/ {
gsub(/[ ,]/, "", $2);
gsub(/[^0-9]/, "", $2);
print $2;
exit
}
' "$CFG_FILE")
if [[ -z "$meshport" ]]; then
echo "Could not extract user port from $CFG_FILE"
exit 1
fi
# List of reliable IPv4-only IP resolvers
RESOLVERS=(
"https://ipv4.icanhazip.com"
"https://api.ipify.org"
"https://ifconfig.me/ip"
"https://ipecho.net/plain"
"https://checkip.amazonaws.com"
"https://ipinfo.io/ip"
"https://myexternalip.com/raw"
"https://ident.me"
"https://whatismyip.akamai.com"
)
publicip=""
for resolver in "${RESOLVERS[@]}"; do
ip=$(curl -s --max-time 5 --connect-timeout 3 -4 "$resolver" 2>/dev/null | tr -d ' \n\r\t')
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
IFS='.' read -r a b c d <<< "$ip"
if (( a <= 255 && b <= 255 && c <= 255 && d <= 255 )); then
publicip="$ip"
break
fi
fi
done
if [[ -n "$publicip" ]]; then
echo "Public IPv4: $publicip"
else
echo "Error: Could not retrieve public IPv4 address from any resolver."
fi
sed -i "s/4567/$meshport/g" /etc/mysql/conf.d/galera.cnf
sed -i "s/__PUBLICIP__/$publicip/g" /etc/mysql/conf.d/galera.cnf
generate_password() {
tr -dc 'A-Za-z0-9!_¤.?' < /dev/urandom | head -c 10
}
randompassword=$(generate_password)
sed -i "s/__RANDOMPWD__/$randompassword/g" /etc/mysql/conf.d/galera.cnf
sed -i "s/node1/$(hostname)/g" /etc/mysql/conf.d/galera.cnf
sleep 15 #env.vars need time
if [ -f /contract/env.vars ]; then
source /contract/env.vars
sed -i "s/4568/$EXTERNAL_GPTCP2_PORT/g" /etc/mysql/conf.d/galera.cnf
sed -i "s/3306/$EXTERNAL_GPTCP1_PORT/g" /etc/mysql/conf.d/galera.cnf
#sed -i "s/4444/$EXTERNAL_GPTCP2_PORT/g" /etc/mysql/conf.d/galera.cnf
#sed -i "s/node1/$HOSTNAME/g" /etc/mysql/conf.d/galera.cnf
fi
if [ ! -f /contract/env.vars ]; then
echo "Starting SSH..."
/usr/sbin/sshd &
fi
ROOT_USER="root"
ROOT_PASS=""
SST_USER="sst_user"
echo "=== Starting MariaDB ==="
sudo -u mysql mariadbd --wsrep-new-cluster &
MARIADB_PID=$!
echo "MariaDB started with PID ${MARIADB_PID}"
echo "Waiting for MariaDB to become ready..."
until mariadb --socket=/run/mysqld/mysqld.sock -e "SELECT 1" >/dev/null 2>&1; do
sleep 2
echo "Waiting for MariaDB..."
done
echo "MariaDB is ready!"
echo "Creating SST user and granting privileges..."
sudo -u mysql mariadb -e "
CREATE USER IF NOT EXISTS '${SST_USER}'@'%' IDENTIFIED BY '${randompassword}';
GRANT ALL PRIVILEGES ON *.* TO '${SST_USER}'@'%';
FLUSH PRIVILEGES;"
echo "SST user created successfully."
echo "Stopping MariaDB"
if sudo -u mysql mariadbd shutdown; then
echo "MariaDB stopped cleanly via mysqladmin."
else
echo "mysqladmin shutdown failed, killing process..."
kill ${MARIADB_PID} 2>/dev/null || true
sleep 2
kill -9 ${MARIADB_PID} 2>/dev/null || true
fi
echo "Done."
sed -i "s/1.1.1.1/$publicip:$meshport/g" /etc/mysql/conf.d/galera.cnf
sudo sed -i 's/.*bind-address\s*=\s*127.0.0.1.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
if [ -f /contract/env.vars ]; then
# Start SSH FIRST (important)
echo "Starting SSH..."
/usr/sbin/sshd &
fi
# All you need to do to sync this up is to boot up instances, then add their ips to eachothers
# wscom list in /etc/mysql/conf.d/galera.cnf, then pick one to use --wsrep-new-cluster command and the rest just no command.
# A full cluster outage occurs when all nodes shut down or when Quorum is lost completely,
# leaving no Primary Component. In this scenario, you must manually intervene to safely restart the cluster.
# file /var/lib/mysql/grastate.dat (sudo nano) contains bootstrap boolean switch, the one with 1 on it has a healthy db (asfaik)
# Highest seqno is latest version, uuid matters too (so its not blank).
# If your seqnumber is -1 you need to do sudo -u mysql mariadbd --wsrep-recover and then restart
# cluster sudo -u mysql mariadbd --wsrep-new-cluster &
#run first node with sudo -u mysql mariadbd --wsrep-new-cluster &
#run second nodes with sudo -u mysql mariadbd
# Create WordPress database and user change localhost to % or a specific ip if u need public access.
# sudo mariadb -e "CREATE DATABASE IF NOT EXISTS wordpress;"
# sudo mariadb -e "CREATE USER IF NOT EXISTS 'wordpress'@'%' IDENTIFIED BY 'wordpress_password';"
# sudo mariadb -e "GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%';"
# sudo mariadb -e "FLUSH PRIVILEGES;"
#Check cluster status
# sudo mariadb -e "SHOW STATUS LIKE 'wsrep_cluster_size';"
# sudo mariadb -e "SHOW STATUS LIKE 'wsrep_cluster_status';"
# sudo mariadb -e "SHOW STATUS LIKE 'wsrep_ready';"
#Create sst user
# CREATE USER 'sst_user'@'%' IDENTIFIED BY 'YourVeryStrongSSTPassword123!';
# GRANT ALL PRIVILEGES ON *.* TO 'sst_user'@'%';
# FLUSH PRIVILEGES;
# Change PWD (doesn't seem to be needed)
# sudo -u mysql mariadbd &
# sudo mariadb --socket=/var/run/mysqld/mysqld.sock -e "ALTER USER 'sst_user'@'%' IDENTIFIED BY 'NewPWD'; FLUSH PRIVILEGES;"
# kill pid.
tail -f /dev/null