HA Sync
HA Sync pairs two Aegis instances for automatic failover. One instance runs as primary (serving traffic via a virtual IP), the other runs as a replicated secondary (standby). If the primary fails, the secondary promotes itself, claims the virtual IP, and begins serving traffic — typically within 3 seconds. When the failed node recovers, it rejoins as secondary and syncs from the new primary. This is a premium feature requiring an Aegis Unleashed license. Linux only.How It Works
- Two separate Aegis installations on two separate machines
- Each has its own binary, its own SQLite database, its own config
- They peer over gRPC, authenticated with a pre-shared key
- The primary holds a virtual IP and serves all client traffic
- Config changes replicate from primary to secondary in real-time
- If the primary’s heartbeat stops, the secondary promotes and claims the VIP
Deployment Model
Each Aegis node is an independent installation. There is no forking, no shared process, and no shared database file.
Replication works at the application level: when the primary writes to its local SQLite, it publishes the change as a typed event over the gRPC stream. The secondary receives it and writes to its own local SQLite. Two completely independent databases, zero locking conflicts.
Clients connect to the virtual IP (e.g.,
10.0.0.100), which exists on exactly one machine’s network interface at any time. The admin UI is always accessible on each node’s real IP — it’s not behind the VIP.
Virtual IP Management
Aegis creates, holds, and releases the VIP itself using the Linux netlink API. No external tools (keepalived, etc.) are needed.Lifecycle
- User configures VIP address and interface in Settings → Sync
- On primary promotion, Aegis calls
netlink.AddrAddto add the VIP to the interface - Aegis sends a gratuitous ARP so network switches learn the new MAC
- The kernel routes packets addressed to the VIP to the proxy listeners
- On failover, the new primary adds the VIP to its own interface and sends ARP
- The old primary (if recovered) removes the VIP
VIP Verification
After claiming the VIP, the primary verifies it’s working:- Checks the address exists on the interface via netlink
- Binds a temporary TCP listener on the VIP to confirm kernel routing
- The secondary periodically dials the VIP to confirm reachability
Pairing and Configuration
Configuration is done in each node’s own admin UI at Settings → Sync.Setup Steps
- Open Node A at
https://10.0.0.1:9443→ Settings → Sync - Click Generate Pre-Shared Key — copy the PSK
- Open Node B at
https://10.0.0.2:9443→ Settings → Sync - Paste the PSK, enter Node A’s sync address (
10.0.0.1:9444) - Back on Node A, enter Node B’s sync address (
10.0.0.2:9444) - Configure the interface and VIP on both nodes
- Click Enable Sync on both
Settings
Role Negotiation
On startup
State transitions
Replication
What gets replicated
Every config mutation on the primary is sent to the secondary as a typed event. Each entity type has its own handler — no generic blob application.What does NOT replicate
Full sync
When a secondary joins or falls too far behind (>10,000 events or >1 hour), a full sync runs:- Primary serializes all config tables as JSON
- Streams to secondary in batches (500 rows per chunk)
- Secondary replaces its local data and triggers a Reload
- Switches to live replication stream
Live replication
During normal operation, events stream in real-time:- Primary writes to its local SQLite
- Store publishes a typed replication event
- Event streams to secondary over gRPC
- Secondary’s applier dispatches to the correct typed handler
- Handler writes to secondary’s local SQLite
- Batched Reload every 1 second (not per-event)
Failover
Detection
The secondary monitors heartbeats from the primary. If no heartbeat arrives within the failover timeout (default 3 seconds):- Secondary claims the VIP via netlink
- Sends gratuitous ARP
- Begins serving traffic
- Starts accepting replication connections (becomes the source)
- Triggers a full Reload
Recovery
When the failed node comes back:- Connects to peer, discovers it’s already primary
- Releases VIP if held (defensive)
- Requests full sync from the new primary
- Joins as secondary
Split-brain protection
If a network partition heals and both nodes think they’re primary:- They reconnect and discover both claim primary
- Compare replication sequence numbers — higher wins
- If equal, compare uptime — longer wins
- Loser releases VIP, demotes, and does a full sync
Secondary Behavior
The secondary is read-only for config mutations:- All GET endpoints work — monitoring, viewing traffic, checking sync status
- Config mutations return 409 — “This node is a secondary replica. Make changes on the primary.”
- The admin UI shows a banner — “Secondary — config changes are read-only”
- Traffic is not served — the secondary doesn’t hold the VIP, so client traffic never reaches it

