1. http-ipv4-keepalive-and-restart#
This bash script will check if the web server is responding correctly via IPv4, and return an error if not. The keepalived process will use the output to switch to the backup instance(s) if there's an issue.
#!/bin/bash
# http-ipv4-keepalive-and-restart
# © 2025 by Sami Ait Ali Oulahcen
# Licensed under CC BY-SA 4.0
#
# If nginx returns HTTP code 200, return 0
sh -c '[ $(curl -4 --connect-timeout 3 -o /dev/null -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]' && echo 0
# Else restart nginx and return error code
if [ $? -ne 0 ]; then
systemctl restart nginx
exit 1
fi
# keepalived will use this to switch to other instances
2. http-ipv6-keepalive-and-restart#
This bash script will check if the web server is responding correctly via IPv6, and return an error if not. The keepalived process will use the output to switch to the backup instance(s) if there's an issue.
#!/bin/bash
# http-ipv6-keepalive-and-restart
# © 2025 by Sami Ait Ali Oulahcen
# Licensed under CC BY-SA 4.0
#
# If nginx returns HTTP code 200, return 0
sh -c '[ $(curl -6 --connect-timeout 3 -o /dev/null -I -L -s -w "%{http_code}" http://localhost) -eq 200 ]' && echo 0
# Else restart nginx and return error code
if [ $? -ne 0 ]; then
systemctl restart nginx
exit 1
fi
# keepalived will use the error output to switch to other instances
3. Install and configure keepalived#
Install keepalived
dnf install keepalived
Let's configure keepalived. This is the master node's config:
/etc/keepalived/keepalived.confvrrp_script web-check-status-ipv4 {
script "/usr/local/bin/web-check-status-ipv4.sh"
interval 3
timeout 5
rise 27
fall 2
user nginx
}
vrrp_script web-check-status-ipv6 {
script "/usr/local/bin/web-check-status-ipv6.sh"
interval 3
timeout 5
rise 27
fall 2
user nginx
}
vrrp_instance web1-ipv4 {
state MASTER
interface ens18
virtual_router_id 10
priority 30
unicast_src_ip 192.203.0.15
unicast_peer {
192.203.0.115
}
authentication {
auth_type PASS
auth_pass uvy23141276gfba5asc421baspz
}
virtual_ipaddress {
192.203.0.20
}
virtual_ipaddress_excluded {
2001:db8:dd::20
}
track_script {
web-check-status-ipv4
}
}
vrrp_instance web1-ipv6 {
state MASTER
interface ens18
virtual_router_id 10
priority 30
unicast_src_ip 2001:db8:dd::15
unicast_peer {
2001:db8:dd::115
}
authentication {
auth_type PASS
auth_pass uvy23141276gfba5asc421baspz
}
virtual_ipaddress {
2001:db8:dd::20
}
track_script {
web-check-status-ipv6
}
}
The scripts /usr/local/bin/web-check-status-ipv{4,6}.sh are the ones from chapter 1 and 2. I've configured keepalived to fall after 2 failed attempts fall 2 and to rise after 27 successful attempts rise 27 for more stability. You can customise to your liking.
And this is the backup node's config:
/etc/keepalived/keepalived.confvrrp_script web-check-status-ipv4 {
script "/usr/local/bin/web-check-status-ipv4.sh"
interval 3
timeout 5
rise 27
fall 2
user nginx
}
vrrp_script web-check-status-ipv6 {
script "/usr/local/bin/web-check-status-ipv6.sh"
interval 3
timeout 5
rise 27
fall 2
user nginx
}
vrrp_instance web1-ipv4 {
state BACKUP
interface ens18
virtual_router_id 10
priority 20
unicast_src_ip 192.203.0.115
unicast_peer {
192.203.0.15
}
authentication {
auth_type PASS
auth_pass uvy23141276gfba5asc421baspz
}
virtual_ipaddress {
192.203.0.20
}
virtual_ipaddress_excluded {
2001:db8:dd::20
}
track_script {
web-check-status-ipv4
}
}
vrrp_instance web1-ipv6 {
state BACKUP
interface ens18
virtual_router_id 10
priority 20
unicast_src_ip 2001:db8:dd::115
unicast_peer {
2001:db8:dd::15
}
authentication {
auth_type PASS
auth_pass uvy23141276gfba5asc421baspz
}
virtual_ipaddress {
2001:db8:dd::20
}
track_script {
web-check-status-ipv6
}
}
4. Configure rsyncd to sync websites contents#
Install the rsync daemon
dnf install rsync-daemon
Then modify the configuration file /etc/rsyncd.conf with the path to your websites
/etc/rsyncd.confuse chroot = false
[www]
uid = nobody
gid = nobody
path = /var/www
list = yes
read only = true
Allow rsyncd through the firewall, and SElinux
setsebool -P rsync_export_all_ro 1
firewall-cmd --permanent --add-service=rsynd
firewall-cmd --reload
And finally start the service
systemctl enable --now rsyncd
On the backup server, you can run something like this via cron to sync periodically:
rsync -a --delete rsync://web00.uni.ma/www/ /var/www