← All articles
Cell tower against a cloudy sky

IPVS and Keepalived for High Availability in Your Homelab

Networking 2026-02-15 · 7 min read keepalived ipvs high-availability vrrp load-balancing networking failover
By HomeLab Starter Editorial TeamHome lab enthusiasts covering hardware setup, networking, and self-hosted services for home and small office environments.

Running a single instance of any service means one thing: when it goes down, so does everything that depends on it. In a homelab, that might mean your DNS stops resolving, your reverse proxy goes offline, or your NAS becomes unreachable. Keepalived and IPVS solve this by giving you automatic failover and load balancing using tools that are already in the Linux kernel.

Photo by Xuancong Meng on Unsplash

Keepalived implements VRRP (Virtual Router Redundancy Protocol), which lets two or more machines share a single virtual IP address. One machine is the master and actively holds the IP. If it goes down, a backup takes over within seconds. IPVS (IP Virtual Server) is a kernel-level Layer 4 load balancer that distributes connections across multiple backend servers. Together, they give you production-grade high availability without any external dependencies.

keepalived logo

Why Keepalived Over Other HA Solutions

Before diving in, it's worth understanding where Keepalived sits relative to other HA tools you might have heard of:

Feature Keepalived + IPVS HAProxy Corosync + Pacemaker MetalLB (K8s)
Layer L3/L4 (kernel) L4/L7 (userspace) Any (framework) L2/L3 (K8s only)
Failover mechanism VRRP External (needs Keepalived) Quorum-based ARP/BGP
Load balancing Yes (IPVS) Yes (built-in) Via managed resources Yes
Config complexity Low Medium High Medium
Resource overhead Minimal Low Moderate Moderate
Best for VIP failover + L4 LB HTTP routing + L7 LB Complex cluster resources Kubernetes services

Keepalived shines when you need a virtual IP that moves between hosts and kernel-level load balancing. It uses almost no resources — the daemon is tiny and IPVS runs in kernel space. For a homelab, this means you can add HA to a Raspberry Pi without worrying about overhead.

Installing Keepalived

On Debian/Ubuntu:

sudo apt update
sudo apt install -y keepalived ipvsadm

On Fedora/RHEL:

sudo dnf install -y keepalived ipvsadm

The ipvsadm package provides the command-line tool for inspecting and managing IPVS rules. Keepalived manages IPVS automatically through its configuration, but ipvsadm is invaluable for debugging.

Enable IP forwarding, which is required for IPVS to route traffic:

echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-ipvs.conf
echo 'net.ipv4.ip_nonlocal_bind = 1' | sudo tee -a /etc/sysctl.d/99-ipvs.conf
sudo sysctl --system

The ip_nonlocal_bind setting allows services to bind to the virtual IP even when the local machine isn't the current VRRP master — important for services that start before failover occurs.

Understanding VRRP

VRRP works by having a group of routers (or servers) share a virtual IP. One is elected the master based on priority, and it periodically sends VRRP advertisements to the group. If the backup nodes stop hearing advertisements, the highest-priority backup promotes itself to master and takes over the virtual IP.

Key concepts:

Like what you're reading? Subscribe to HomeLab Starter — free weekly guides in your inbox.

Basic VRRP Failover Configuration

Let's set up a virtual IP shared between two servers. This is the foundation for everything else.

Network layout:

Server 1 (Master) — /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass homelabHA
    }

    virtual_ipaddress {
        192.168.1.100/24
    }
}

Server 2 (Backup) — /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 90
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass homelabHA
    }

    virtual_ipaddress {
        192.168.1.100/24
    }
}

Start keepalived on both:

sudo systemctl enable --now keepalived

Verify the virtual IP is on Server 1:

ip addr show eth0

You should see 192.168.1.100/24 listed as a secondary address. Now stop keepalived on Server 1 and watch Server 2 pick up the IP within about 3 seconds.

Adding Health Checks with VRRP Scripts

A virtual IP that only fails over when the whole machine goes down isn't enough. You want it to fail over when the service goes down too. Keepalived supports health check scripts that adjust the priority dynamically.

vrrp_script check_nginx {
    script "/usr/bin/curl -sf http://localhost:80/ > /dev/null"
    interval 2
    weight -20
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass homelabHA
    }

    virtual_ipaddress {
        192.168.1.100/24
    }

    track_script {
        check_nginx
    }
}

When the check_nginx script fails 3 times in a row (fall 3), Keepalived subtracts 20 from the priority. If Server 1's priority drops from 100 to 80, Server 2 at priority 90 becomes the new master. When the script passes twice (rise 2), the priority is restored and Server 1 preempts back to master.

Common health check patterns:

# Check if a process is running
/usr/bin/pgrep -x nginx

# Check an HTTP endpoint
/usr/bin/curl -sf http://localhost:8080/health

# Check a TCP port
/usr/bin/nc -z localhost 5432

# Check if a file exists (maintenance mode)
/usr/bin/test ! -f /tmp/keepalived-maintenance

Load Balancing with IPVS

VRRP gives you failover. IPVS gives you load balancing. Keepalived manages both in a single configuration.

IPVS runs in the Linux kernel and supports three forwarding modes:

For a homelab on a single subnet, DR mode is the best choice — it's fast and puts minimal load on the balancer.

IPVS Configuration Example

Here's a full configuration that provides a highly available, load-balanced web service:

vrrp_instance VI_WEB {
    state MASTER
    interface eth0
    virtual_router_id 52
    priority 100
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass webHA123
    }

    virtual_ipaddress {
        192.168.1.200/24
    }
}

virtual_server 192.168.1.200 80 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    persistence_timeout 300
    protocol TCP

    real_server 192.168.1.21 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            connect_port 80
        }
    }

    real_server 192.168.1.22 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            connect_port 80
        }
    }

    real_server 192.168.1.23 80 {
        weight 1
        HTTP_GET {
            url {
                path /health
                status_code 200
            }
            connect_timeout 3
            retry 3
        }
    }
}

IPVS scheduling algorithms:

Algorithm Code Best for
Round Robin rr Equal servers, stateless services
Weighted Round Robin wrr Mixed hardware (give faster servers more traffic)
Least Connections lc Long-lived connections, varying request durations
Weighted Least Connections wlc Mixed hardware with long-lived connections
Source Hashing sh Sticky sessions without cookies

For most homelab use cases, rr (round robin) or wlc (weighted least connections) work well.

Direct Routing Setup on Real Servers

When using DR mode, each real server needs to be configured to accept traffic for the virtual IP without responding to ARP requests for it. This prevents ARP conflicts — only the load balancer should answer ARP for the VIP.

On each real server:

# Add the VIP to the loopback interface
sudo ip addr add 192.168.1.200/32 dev lo

# Suppress ARP responses for the VIP
echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 | sudo tee /proc/sys/net/ipv4/conf/all/arp_announce

Make these persistent by adding to /etc/sysctl.d/99-ipvs-dr.conf:

net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

Practical Homelab HA Scenarios

HA DNS (Pi-hole / AdGuard Home)

Run two Pi-hole instances with Keepalived sharing a VIP. Point your DHCP server at the VIP instead of individual Pi-hole IPs:

vrrp_script check_pihole {
    script "/usr/bin/dig +short @127.0.0.1 google.com > /dev/null 2>&1"
    interval 5
    weight -30
    fall 3
    rise 2
}

vrrp_instance VI_DNS {
    state MASTER
    interface eth0
    virtual_router_id 53
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass dnsHA
    }
    virtual_ipaddress {
        192.168.1.53/24
    }
    track_script {
        check_pihole
    }
}

HA Reverse Proxy

If you run Nginx or Caddy as your reverse proxy, putting Keepalived in front of two instances ensures your entire web stack stays up even if one proxy server fails.

HA Database (PostgreSQL)

Combine Keepalived with PostgreSQL streaming replication. The health check script verifies the local PostgreSQL is in read-write mode (primary), and if it fails, the VIP moves to the standby server. You'll need a promotion script in the notify_master hook to promote the standby automatically.

Monitoring IPVS

Use ipvsadm to inspect the current state:

# Show all virtual services and real servers
sudo ipvsadm -Ln

# Show connection statistics
sudo ipvsadm -Ln --stats

# Show rate information
sudo ipvsadm -Ln --rate

Keepalived also logs to syslog. Watch for failover events:

journalctl -u keepalived -f

You'll see messages like Entering MASTER STATE and Entering BACKUP STATE during transitions.

Troubleshooting

VIP not appearing: Check that virtual_router_id matches on all nodes and that no other VRRP instance on your network uses the same VRID. Also verify your firewall allows VRRP traffic (protocol 112).

Split brain (both nodes claim master): This usually means VRRP advertisements aren't reaching the backup. Check that multicast (or unicast, if configured) traffic isn't blocked. Switches with IGMP snooping can sometimes drop VRRP multicast.

IPVS not distributing traffic: Verify with ipvsadm -Ln that real servers show up and have non-zero connection counts. For DR mode, confirm the ARP settings on real servers and that the VIP is on loopback.

Firewall rules: Allow VRRP and the load-balanced ports:

# Allow VRRP (protocol 112)
sudo firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent

# Allow the service port
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload

Next Steps

Once you have basic VRRP and IPVS running, consider adding notification scripts (notify_master, notify_backup, notify_fault) to trigger alerts through ntfy or Gotify when failovers happen. You can also combine Keepalived with HAProxy — use Keepalived for VIP failover and HAProxy for L7 routing, giving you the best of both worlds. For more complex setups with three or more nodes, look into unicast VRRP configuration to avoid multicast issues on certain network switches.

Get free weekly tips in your inbox. Subscribe to HomeLab Starter