# HAproxy with Keepalived not behaving as expected

**URL:** <https://discourse.haproxy.org/t/haproxy-with-keepalived-not-behaving-as-expected/9657>\
**Category:** Help!\
**Created:** [March 23, 2024, 1:25pm UTC](https://discourse.haproxy.org/t/haproxy-with-keepalived-not-behaving-as-expected/9657 "2024-03-23T13:25:08Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![th3pl4gu3](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.haproxy.org/th3pl4gu3/32/2191_2.png) [@th3pl4gu3](https://discourse.haproxy.org/u/th3pl4gu3)\
**Post date:** [March 23, 2024, 1:25pm UTC](https://discourse.haproxy.org/t/haproxy-with-keepalived-not-behaving-as-expected/9657/1 "2024-03-23T13:25:08Z")

</div>

I have two servers in a public subnet with both public and private IPs. I want to configure `HAproxy` with `keepalived` and make `server1` act as the `master` and `server2` as `backup`.

If `server1` goes down, I want `server2` to takeover.

Let’s classify it as follows:

```auto
server1: private_ip1 & public_ip1
server2: private_ip2 & public_ip2

virtual_public_ip

```

I have a flask app on both servers with the following code:

`app.py`

```
from flask import *
import socket

app = Flask( __name__ )

@app.route("/")
def index():
    hostname = socket.gethostname()
    ip = socket.gethostbyname(hostname)
    return f"<h1>Hello from computer {hostname} with ip {ip}</h1>"

if __name__ == " __main__":
    app.run(debug=False)

```

The code will basically display the hostname of the server and its IP address.

Below is the config file for HAproxy and Keepalived for each servers.

`server1 HAproxy`

```
global
    log 127.0.0.1 local2

    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

    # utilize system-wide crypto-policies
    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option http-server-close
    option forwardfor except 127.0.0.0/8
    option redispatch
    retries 3
    timeout http-request 10s
    timeout queue 1m
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 10s
    timeout check 10s
    maxconn 3000

frontend main
    bind *:80
    default_backend app_servers

backend app_servers
    balance roundrobin
    server haproxy-01 public_ip1:5000 check
    server haproxy-02 public_ip2:5000 backup

```

`server1 keepalived`

```
global_defs {
	enable_script_security
	script_user th3pl4gu3
}

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 101
    virtual_ipaddress {
        virtual_public_ip
    }
    track_script {
        chk_haproxy
    }
}

```

`server2 HAproxy`

```
global
    log 127.0.0.1 local2

    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

    # utilize system-wide crypto-policies
    ssl-default-bind-ciphers PROFILE=SYSTEM
    ssl-default-server-ciphers PROFILE=SYSTEM

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option http-server-close
    option forwardfor except 127.0.0.0/8
    option redispatch
    retries 3
    timeout http-request 10s
    timeout queue 1m
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 10s
    timeout check 10s
    maxconn 3000

frontend main
bind *:80
    default_backend app_servers

backend app_servers
    balance roundrobin
    server haproxy-01 public_ip1:5000 backup
    server haproxy-02 public_ip2:5000 check

```

`server2 keepalived`

```
global_defs {
    enable_script_security
    script_user th3pl4gu3
}

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    virtual_ipaddress {
        virtual_public_ip
    }
    track_script {
        chk_haproxy
    }
}

```

If i go on my browser and enter `http://public_ip1:5000` in the URL, i can see the hostname for server1 and the `virtual_public_ip`.

If i go on my browser and enter `http://public_ip2:5000` in the URL, i can see the hostname for server2 and still the `virtual_public_ip`.

But if i try to access the app. using the virtual IP itself, it doesn’t work `http://virtual_public_ip`.

What am i doing wrong ?

---

<div class="post-metadata">

**Author:** ![jasejk](https://avatars.discourse-cdn.com/v4/letter/j/e8c25b/32.png) [@jasejk](https://discourse.haproxy.org/u/jasejk)\
**Post date:** [March 23, 2024, 7:52pm UTC](https://discourse.haproxy.org/t/haproxy-with-keepalived-not-behaving-as-expected/9657/2 "2024-03-23T19:52:54Z")

</div>

this works for me on an Exchange cluster for keepalived

```auto
Server1
vrrp_script check_haproxy {
  script "killall -0 haproxy"
  interval 2
  weight 2
}

vrrp_instance VI_1 {
  interface ens192
  state MASTER
  virtual_router_id 10
  priority 101
  virtual_ipaddress {
    VIP ipv4
  }
  virtual_ipaddress_excluded {

   VIP ipv6

  }
  track_script {
    check_haproxy
  }
  smtp_alert
}

Server2
vrrp_script check_haproxy {
  script "killall -0 haproxy"
  interval 2
  weight 2
}

vrrp_instance VI_1 {
  interface ens192
  state MASTER
  virtual_router_id 10
  priority 100
  virtual_ipaddress {
    VIP ipv4
  }
  virtual_ipaddress_excluded {

   VIP ipv6

  }
  track_script {
    check_haproxy
  }
  smtp_alert
}

```
