As of this implementation, remote peer configurations are stored in a synchronized collection (_system_remote_peers) that is automatically replicated across all nodes in the cluster through EntglDB's built-in sync infrastructure.
When using the BullyLeaderElectionService:
- Any LAN node can be elected as the Cloud Gateway (leader)
- Only the elected leader connects to remote cloud nodes
- All nodes automatically have the same remote peer configurations through sync
- Leader election is always effective because all nodes know about all remote peers
- Remote peer configurations are stored as documents in a special collection:
_system_remote_peers - This collection is synchronized automatically through EntglDB's normal sync process
- When you add/remove/modify a remote peer on any node, it syncs to all other nodes
- All nodes maintain consistent remote peer configurations without manual intervention
Since configurations sync automatically, you only need to add remote peers on one node:
// Add on any node in the cluster
var database = new PeerDatabase(store, configProvider);
var peerManagement = new PeerManagementService(database, logger);
await peerManagement.AddCloudPeerAsync(
"cloud-node-1",
"remote.entgldb.com:9000",
new OAuth2Configuration {
Authority = "https://identity.example.com",
ClientId = "lan-cluster-client",
ClientSecret = "secret",
Scopes = new[] { "entgldb:sync" }
}
);
// Configuration automatically syncs to all other nodes in clusterQuery remote peers on any node - they should all return the same list:
var peers = await peerManagement.GetAllRemotePeersAsync();
foreach (var peer in peers)
{
Console.WriteLine($"{peer.NodeId}: {peer.Address} (Type: {peer.Type}, Enabled: {peer.IsEnabled})");
}You can still use configuration files for initial setup on cluster creation:
appsettings.json (optional, for first-time cluster setup):
{
"EntglDb": {
"InitialRemotePeers": [
{
"nodeId": "cloud-node-1",
"address": "remote.entgldb.com:9000",
"type": "CloudRemote",
"oAuth2": {
"authority": "https://identity.example.com",
"clientId": "lan-cluster-client",
"clientSecret": "${SECRET_FROM_ENV}",
"scopes": ["entgldb:sync"]
}
}
]
}
}Startup code (apply once on any node):
var initialPeers = configuration.GetSection("EntglDb:InitialRemotePeers")
.Get<List<RemotePeerConfig>>();
if (initialPeers != null && initialPeers.Any())
{
var peerManagement = new PeerManagementService(database, logger);
foreach (var remotePeer in initialPeers)
{
// Check if already exists to avoid duplicates
var existing = await peerManagement.GetAllRemotePeersAsync();
if (!existing.Any(p => p.NodeId == remotePeer.NodeId))
{
await peerManagement.AddCloudPeerAsync(
remotePeer.NodeId,
remotePeer.Address,
remotePeer.OAuth2
);
}
}
}You can manage remote peers dynamically without restarting nodes:
// Add a new remote peer (syncs to all nodes)
await peerManagement.AddCloudPeerAsync("cloud-2", "cloud2.example.com:9000", oauth2Config);
// Disable a peer temporarily (syncs to all nodes)
await peerManagement.DisablePeerAsync("cloud-1");
// Re-enable later (syncs to all nodes)
await peerManagement.EnablePeerAsync("cloud-1");
// Remove a peer permanently (syncs to all nodes)
await peerManagement.RemoveRemotePeerAsync("cloud-2");All changes are automatically synchronized across the cluster within seconds (depending on sync interval).
Scenario: You have a running 3-node LAN cluster and want to add cloud connectivity
Solution: Connect to any node and add the cloud peer
# SSH to any node
ssh node-1
# Add cloud peer via API or code
dotnet run -- add-cloud-peer \
--node-id cloud-1 \
--address cloud.example.com:9000 \
--authority https://identity.example.com \
--client-id client-idThe configuration automatically syncs to all 3 nodes.
Scenario: Cloud node is under maintenance, disable temporarily
Solution: Disable on any node
await peerManagement.DisablePeerAsync("cloud-1");
// Syncs to all nodes, leader stops connectingRe-enable when maintenance is done:
await peerManagement.EnablePeerAsync("cloud-1");
// Syncs to all nodes, leader resumes connectingScenario: Migrating to a new cloud provider
Solution:
// Add new cloud node (old one still active)
await peerManagement.AddCloudPeerAsync("cloud-new", "newcloud.com:9000", newOAuth2);
// Disable old cloud node
await peerManagement.DisablePeerAsync("cloud-old");
// After verification, remove old cloud node
await peerManagement.RemoveRemotePeerAsync("cloud-old");All changes sync automatically to all nodes.
- Zero Configuration Drift: All nodes always have identical remote peer lists
- Dynamic Updates: Add/remove/modify peers without restarting any node
- Consistent Leader Election: Leader always knows about all remote peers
- Simplified Operations: Manage from any node, changes propagate automatically
- High Availability: No single point of failure for configuration management
Remote peers are stored in: _system_remote_peers
Uses EntglDB's built-in document synchronization:
- Documents are oplog entries with HLC timestamps
- Conflict resolution uses last-write-wins by default
- Synchronization happens every 2 seconds (default sync interval)
Each remote peer is a document with NodeId as primary key:
{
"NodeId": "cloud-node-1",
"Address": "remote.entgldb.com:9000",
"Type": 2,
"OAuth2Json": "{\"authority\":\"https://...\", ...}",
"IsEnabled": true
}Current Status: Automatic synchronization implemented
Recommended: Simply add remote peers on any node - they sync automatically
No Manual Consistency Required: Configuration synchronization is automatic and real-time