Using keepalived in a hassos installation

Hello,

Is it possible to install keepalived in a raspberry pi 4 with Home Assistant OS? Right now I am using the Nginx Proxy Manager addon as a point of entry of all my local services (not only hass). I would love to be able to keep it running when hassos is down (for instance when updating). Is it possible to use something like keepalived so i can use a virtual IP to failover to another npm instance running in another computer?

1 Like

I too am looking for server redundancy failover using keepalived using a floating IP, I rely on HA to be 100% operational.

+1 from my side as well. In the past I used Keepalived to fulfill this

Hi!

I found this topic while searching for the same thing. I would like to use keepalived with HA OS. My usecase would he to have a floating VIP with the Adguard addon and other adguard instance(s) in the LAN.
I am doing that today with 3 Raspis and pihole but I would prefer using adguard. For that, it would be great to have the ability to add the HA OS instance ti have it float the VIP there as well.

Unfortunately, I do not know, how to achieve that. From other topics I got the impression, that it might be possible to install keepalived on the core or ssh addon? But then? Is there somebody who can help with that?

Thanks and best regards :slight_smile:

For those still looking for a keepalived HA add-on, here is one I’ve been using personally for the last several months:

hassio-addons/keepalived at master · rsnodgrass/hassio-addons · GitHub

wow, many thanks for this @ryans !! I need to understand first how to properly configure it in my setup but I am going to give it a go.

Thanks again!

I am having some troubles setting up keepalived using the container. Basically, I cannot manage to make it work. I have set up a simple VRRP with virtual IP 192.168.1.9. My config is this one:

global_defs {
    router_id dns-homeassistant  # hostname is used by default
}

vrrp_instance ADGUARD {
    state MASTER
    interface end0
    virtual_router_id 33
    priority 100
    advert_int 2

    authentication {
        auth_type PASS
        auth_pass adguard
    }

    virtual_ipaddress {
        192.168.1.9/24 dev end0
    }
}

The addon seems to start and sets the virtual IP and MASTER state (I have not setup any other keepalived node yet).

Tue Feb  4 09:23:09 2025: (ADGUARD) Entering BACKUP STATE (init)
Tue Feb  4 09:23:09 2025: VRRP sockpool: [ifindex(  2), family(IPv4), proto(112), fd(12,13) multicast, address(224.0.0.18)]
Tue Feb  4 09:23:16 2025: (ADGUARD) Receive advertisement timeout
Tue Feb  4 09:23:16 2025: (ADGUARD) Entering MASTER STATE
Tue Feb  4 09:23:16 2025: (ADGUARD) setting VIPs.
Tue Feb  4 09:23:16 2025: (ADGUARD) Sending/queueing gratuitous ARPs on end0 for 192.168.1.9
Tue Feb  4 09:23:16 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:16 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:16 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:16 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:16 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:21 2025: (ADGUARD) Sending/queueing gratuitous ARPs on end0 for 192.168.1.9
Tue Feb  4 09:23:21 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:21 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:21 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:21 2025: Sending gratuitous ARP on end0 for 192.168.1.9
Tue Feb  4 09:23:21 2025: Sending gratuitous ARP on end0 for 192.168.1.9

After that, I can ping the virtual IP 192.168.1.9 succesfully:

> ping 192.168.1.9
PING 192.168.1.9 (192.168.1.9) 56(84) bytes of data.
64 bytes from 192.168.1.9: icmp_seq=1 ttl=64 time=0.338 ms
64 bytes from 192.168.1.9: icmp_seq=2 ttl=64 time=0.254 ms

However, it does not seem to reach the adguard addon on port 53. If I do:

> dig @192.168.1.9 example.com
;; communications error to 192.168.1.9#53: connection refused

I can reach the adguard addon in the real home assistant IP (in my case 192.168.1.30):

> dig @192.168.1.30 example.com

; <<>> DiG 9.18.28-1~deb12u2-Debian <<>> @192.168.1.30 example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13584
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            251     IN      A       23.215.0.138
example.com.            251     IN      A       96.7.128.198
example.com.            251     IN      A       96.7.128.175
example.com.            251     IN      A       23.192.228.80
example.com.            251     IN      A       23.215.0.136
example.com.            251     IN      A       23.192.228.84

;; Query time: 39 msec
;; SERVER: 192.168.1.30#53(192.168.1.30) (UDP)
;; WHEN: Tue Feb 04 09:27:40 CET 2025
;; MSG SIZE  rcvd: 136

Any ideas what might be happening? Does the adguard addon only respond to queries to the real IP?

OK, I found the problem. You need to re-start the adguard addon after the keepalived addon is started. This is a big problem I think.

If you start keepalived in a BACKUP state, home assistant does not seem to inform the adguard addon that the virtual IP could be assigned to it. Therefore, when keepalived switches to MASTER state, adguard is unreachable.

So this only works if you start keepalived before adguard addon (no idea if this can be done automatically) and that it starts in a MASTER state so the virtual IP assigned to HA before adguard is started.

Any ideas how this can be solved?

Correct, the AdGuard add-on cannot listen on an interface that doesn’t exist (and if a new interface is added to a host, it doesn’t detect that and start listening). Thus on initial install, AdGuard MUST of course be restarted to listen to the new VIP.

However, for future reboots this MAY still be a problem. I can’t see anyway to specify a dependency or order of add-on startup, so I think it might be a little luck of the draw. I have changed the keepalived addon config.yaml so it starts up earlier with startup: services, which I think is after startup: system (HA documentation services was before system).

Anyone know if there is a way in the UI to specify add-on start order?

Another idea (if there is no way to list add-on dependencies) is to create an automation that restarts AdGuard Home after keepalived add-on is running.

automation:
  - alias: "Restart AdGuard after Keepalived Add-on Started"
    id: restart_adguard_after_keepalived
    trigger:
      - platform: state
        entity_id: binary_sensor.keepalived_running
      from: 'off'
      to: 'on'
      for: 00:00:05
    actions:
      - service: hassio.addon_restart
        data:
          addon: "a0d7b954_adguard"

FIRST HOWEVER, you must enable the sensor that determines if an addon is running. Home Assistant doesn’t enable these by default.

Go to Settings → Devices & Services → Supervisor → Entities then search for binary_sensor.keepalived_running, edit the sensor, and click Enable!