Files
mustafa.ulukaya 7dfd31832a feat(vip): store the keepalived.conf an agent finds on a node
Ingest side of adopting an existing VIP. A node reports the keepalived.conf it
found and does NOT own to a new endpoint, and the finding is kept in a new
vip_discoveries table (one row per agent, since the file is per-node).

Reporting is read-only on the node. The heartbeat cannot carry this: it has the
VIP address and a best-effort MASTER/BACKUP, while rendering a node's config
needs eleven fields, so the file itself has to be read and parsed server-side -
parsing keepalived's block syntax in bash is not something to attempt on a
production load balancer.

Secrets are split at ingest. The reported content may contain the VRRP
auth_pass, so the password is Fernet-encrypted into its own column through the
same key path as vip_instances, and the stored copy of the file has it masked.
Nothing readable through the API, the UI preview or a database dump carries it
in cleartext, and the parse result is never logged. A file that does not parse
records its error rather than failing the agent's poll loop, and a report of
"the file is gone" clears the row so the UI stops offering a stale candidate.

The keepalived-config delivery gains allow_takeover and
takeover_expected_hash. The agent refuses to overwrite a keepalived.conf
without our ownership marker, which is the guard that protects a
hand-maintained setup - and is exactly the guard adoption has to pass. Rather
than weaken it, an adopted VIP authorises exactly ONE takeover of exactly the
file that was analysed by pinning its md5, so a config edited between adoption
and Apply is still refused instead of being silently overwritten.

SCHEMA_VERSION 10 -> 11 for the new table and two additive columns. Nothing
existing is altered, but the bump re-seeds the four built-in roles, which the
upgrade notes call out.
2026-08-11 01:35:59 +03:00
..
2025-10-27 12:14:03 +03:00