# Config Sync

> VyOS configuration synchronization - replicate settings between routers, high availability, and automatic config sync in cloud environments

Source: https://opennix.org/en/docs/vyos/services/vyos-config-sync/


Config Sync is a service for automatic configuration synchronization between two VyOS routers.

## Overview

Config Sync provides automatic replication of configuration changes from the primary router to the secondary one.

**Key capabilities:**
- One-way synchronization (primary → secondary)
- Selective synchronization of configuration sections
- Automatic push of changes after commit
- Two synchronization modes: load and set
- Support for all major configuration sections

**Requirements:**
- VyOS REST API configured on the secondary router
- Both routers must be online
- Identical VyOS version on both devices
- Network connectivity between the routers

**Protocol**: HTTPS/HTTP (VyOS REST API)

**Port**: 443 (HTTPS) or a custom value

## How it works

### Architecture

```
┌──────────────────┐                    ┌──────────────────┐
│   Primary VyOS   │                    │  Secondary VyOS  │
│                  │                    │                  │
│  Config Sync     │──── HTTPS API ────>│   REST API       │
│  Client          │                    │   Server         │
│                  │                    │                  │
└──────────────────┘                    └──────────────────┘
     (master)                               (replica)
```

### Synchronization process

1. The administrator makes changes on the primary router
2. A `commit` is executed on the primary
3. Config Sync intercepts the changes
4. The changes are pushed to the secondary via the REST API
5. The secondary applies the configuration
6. The result is logged on the primary

### Synchronization direction

**Important**: Synchronization is one-way:
- Primary → Secondary: Yes
- Secondary → Primary: No

Changes made on the secondary are NOT synchronized back and will be overwritten during the next synchronization from the primary.

## Basic configuration

### Preparing the Secondary router

The first step is to configure the REST API on the secondary router:

#### VyOS 1.4 (Sagitta)

```
configure
set service https api keys id config-sync key 'your-secure-api-key-here'
commit
save
```

#### VyOS 1.5 (Circinus)

```
configure
set service https api keys id config-sync key 'your-secure-api-key-here'
set service https api rest
commit
save
```

**Note**: In VyOS 1.5, the REST API endpoint must be explicitly enabled.

### Configuring the Primary router

Configure Config Sync on the primary router:

```
configure

# Specify the secondary router address
set service config-sync secondary address '192.168.100.2'

# API key (must match the key on the secondary)
set service config-sync secondary key 'your-secure-api-key-here'

# Sections to synchronize
set service config-sync section firewall
set service config-sync section nat
set service config-sync section vpn

commit
save
```

## Configuration parameters

### Secondary router

#### address

IP address or hostname of the secondary router:

```
set service config-sync secondary address '192.168.100.2'
set service config-sync secondary address 'vyos-backup.example.com'
set service config-sync secondary address '2001:db8::2'
```

#### key

API key for authentication:

```
set service config-sync secondary key 'your-secure-api-key-here'
```

**Generating a secure key:**
```bash
openssl rand -base64 32
```

#### port

REST API TCP port (default 443):

```
set service config-sync secondary port 443
set service config-sync secondary port 8443
```

#### timeout

Connection timeout in seconds (default 60):

```
set service config-sync secondary timeout 60
set service config-sync secondary timeout 120
```

Increase this value for slow links or large configurations.

### Section - sections to synchronize

Select the configuration sections to replicate:

```
set service config-sync section <section-name>
```

**Available sections:**

| Section | Description |
|--------|----------|
| `firewall` | Firewall rules, zones, groups |
| `interfaces` | Interface configuration |
| `nat` | NAT rules (source, destination) |
| `nat66` | NAT66 (IPv6-to-IPv6) |
| `pki` | PKI certificates and keys |
| `protocols` | Dynamic routing (BGP, OSPF, RIP) |
| `qos` | Quality of Service policies |
| `service` | Services (DHCP, DNS, SSH, etc.) |
| `system` | System settings (hostname, users, etc.) |
| `vpn` | VPN configuration (IPsec, OpenVPN, L2TP) |
| `vrf` | Virtual Routing and Forwarding |

**Examples:**

Synchronize all network services:
```
set service config-sync section firewall
set service config-sync section nat
set service config-sync section interfaces
set service config-sync section vpn
```

Routing and services only:
```
set service config-sync section protocols
set service config-sync section service
```

### Mode - synchronization mode

#### load (default)

Replaces the section configuration on the secondary:

```
set service config-sync mode load
```

**Behavior:**
- Removes the existing section configuration on the secondary
- Loads the new configuration from the primary
- Recommended for full synchronization

**Example:**
```
# Primary has:
firewall rule 10, 20, 30

# Secondary will have exactly the same:
firewall rule 10, 20, 30

# Any other rules on the secondary will be removed
```

#### set

Adds/updates the configuration on the secondary:

```
set service config-sync mode set
```

**Behavior:**
- Does not remove the existing configuration
- Adds new parameters
- Updates existing parameters
- May lead to configuration mismatch

**Example:**
```
# Primary has:
firewall rule 10, 20

# Secondary has:
firewall rule 30, 40

# After synchronization the secondary will have:
firewall rule 10, 20, 30, 40
```

**Recommendation**: Use `load` to guarantee identical configurations.

## Configuration examples

### Basic HA router

Primary router:
```
configure

# Secondary router
set service config-sync secondary address '192.168.100.2'
set service config-sync secondary key 'MySecureKey123!@#'

# Synchronize critical sections
set service config-sync section firewall
set service config-sync section nat
set service config-sync section system

# Full-replacement mode
set service config-sync mode load

commit
save
```

Secondary router:
```
configure

# Enable REST API
set service https api keys id config-sync key 'MySecureKey123!@#'
set service https api rest

commit
save
```

### HA VPN gateway

Primary:
```
configure

# Secondary router
set service config-sync secondary address '10.0.0.2'
set service config-sync secondary key 'VpnGatewaySync2024'
set service config-sync secondary timeout 120

# VPN and related sections
set service config-sync section vpn
set service config-sync section firewall
set service config-sync section nat
set service config-sync section pki

# Replacement mode
set service config-sync mode load

commit
save
```

### Synchronizing OSPF configuration

Primary:
```
configure

# Secondary router
set service config-sync secondary address '192.168.1.2'
set service config-sync secondary key 'OspfSyncKey'

# Routing protocols and system only
set service config-sync section protocols
set service config-sync section system

commit
save
```

### Multi-site with VRF

Primary:
```
configure

# Secondary router
set service config-sync secondary address '10.10.10.2'
set service config-sync secondary key 'VrfMultiSite2024'

# VRF, routing, and services
set service config-sync section vrf
set service config-sync section protocols
set service config-sync section interfaces
set service config-sync section service

commit
save
```

### Full synchronization of all sections

Primary:
```
configure

set service config-sync secondary address '192.168.100.2'
set service config-sync secondary key 'FullSyncKey2024'

# All supported sections
set service config-sync section firewall
set service config-sync section interfaces
set service config-sync section nat
set service config-sync section nat66
set service config-sync section pki
set service config-sync section protocols
set service config-sync section qos
set service config-sync section service
set service config-sync section system
set service config-sync section vpn
set service config-sync section vrf

set service config-sync mode load

commit
save
```

## Examples for cloud providers

### Yandex Cloud HA configuration

**Topology:**
- Primary VyOS: 192.168.10.10 (internal IP)
- Secondary VyOS: 192.168.10.20 (internal IP)
- Both VMs in the same Yandex Cloud subnet
- Security Group allows HTTPS between the VMs

**Secondary router** (192.168.10.20):
```
configure

# REST API setup
set service https api keys id yc-config-sync key 'YC-Secure-Key-2024-Random-String'
set service https api rest

# Allow HTTPS from the internal network
set service https listen-address 192.168.10.20

# HTTPS certificate (self-signed for internal use)
set service https certificates system-generated-certificate

commit
save
```

**Primary router** (192.168.10.10):
```
configure

# Connection to the secondary
set service config-sync secondary address '192.168.10.20'
set service config-sync secondary key 'YC-Secure-Key-2024-Random-String'
set service config-sync secondary port 443
set service config-sync secondary timeout 90

# Sections to synchronize
set service config-sync section firewall
set service config-sync section nat
set service config-sync section interfaces
set service config-sync section system

# Full-replacement mode
set service config-sync mode load

commit
save
```

**Note for Yandex Cloud:**
- Use internal IP addresses for synchronization
- Configure Security Groups to allow HTTPS (TCP 443)
- Consider using a Network Load Balancer for failover

### VK Cloud (Mail.ru Cloud) HA configuration

**Topology:**
- Primary VyOS: 10.0.10.10 (private IP)
- Secondary VyOS: 10.0.10.20 (private IP)
- Floating IP for failover
- Security Group with an HTTPS rule

**Secondary router** (10.0.10.20):
```
configure

# REST API configuration
set service https api keys id vkcloud-sync key 'VKCloud-HA-Key-SecureRandom123'
set service https api rest

# Listen on the private interface
set service https listen-address 10.0.10.20

# Self-signed certificate
set service https certificates system-generated-certificate

commit
save
```

**Primary router** (10.0.10.10):
```
configure

# Secondary endpoint
set service config-sync secondary address '10.0.10.20'
set service config-sync secondary key 'VKCloud-HA-Key-SecureRandom123'
set service config-sync secondary port 443
set service config-sync secondary timeout 120

# Critical sections
set service config-sync section firewall
set service config-sync section nat
set service config-sync section vpn
set service config-sync section service

set service config-sync mode load

commit
save
```

**Security Group setup in VK Cloud:**
```
# Allow HTTPS between the HA pair
Direction: Ingress
Protocol: TCP
Port: 443
Source: 10.0.10.10/32
```

### AWS HA across different AZs

**Topology:**
- Primary: us-east-1a (10.0.1.10)
- Secondary: us-east-1b (10.0.2.20)
- Different Availability Zones for fault tolerance

**Secondary** (10.0.2.20):
```
configure

set service https api keys id aws-ha key 'AWS-HA-Sync-Key-Random'
set service https api rest
set service https listen-address 10.0.2.20
set service https certificates system-generated-certificate

commit
save
```

**Primary** (10.0.1.10):
```
configure

set service config-sync secondary address '10.0.2.20'
set service config-sync secondary key 'AWS-HA-Sync-Key-Random'
set service config-sync secondary timeout 150

# Full synchronization for DR
set service config-sync section firewall
set service config-sync section nat
set service config-sync section interfaces
set service config-sync section protocols
set service config-sync section service
set service config-sync section system
set service config-sync section vpn

set service config-sync mode load

commit
save
```

### Azure HA with an Availability Set

**Topology:**
- Primary: 172.16.1.10 (zone 1)
- Secondary: 172.16.1.20 (zone 2)
- Azure Load Balancer for failover

**Secondary** (172.16.1.20):
```
configure

set service https api keys id azure-ha key 'Azure-ConfigSync-2024-SecureKey'
set service https api rest
set service https listen-address 172.16.1.20

commit
save
```

**Primary** (172.16.1.10):
```
configure

set service config-sync secondary address '172.16.1.20'
set service config-sync secondary key 'Azure-ConfigSync-2024-SecureKey'
set service config-sync secondary port 443

set service config-sync section firewall
set service config-sync section nat
set service config-sync section vpn
set service config-sync section protocols

set service config-sync mode load

commit
save
```

## Operational commands

### Viewing the configuration

Show the current Config Sync configuration:

```
show service config-sync
```

Output:
```
 config-sync {
     mode load
     secondary {
         address 192.168.100.2
         key ****************
         port 443
         timeout 60
     }
     section firewall
     section nat
     section vpn
 }
```

### Manual synchronization

Config Sync triggers automatically after a `commit`. To run it manually:

```
reset config-sync
```

This re-synchronizes all configured sections.

### Checking the status

Check the last synchronization:

```
show log | match config-sync
```

Successful synchronization:
```
Oct 15 10:30:15 vyos-primary config-sync[1234]: Successfully synced section 'firewall' to 192.168.100.2
Oct 15 10:30:16 vyos-primary config-sync[1234]: Successfully synced section 'nat' to 192.168.100.2
```

Synchronization error:
```
Oct 15 10:30:15 vyos-primary config-sync[1234]: Failed to sync to 192.168.100.2: Connection timeout
```

### Monitoring the logs

Real-time monitoring:

```
monitor log | match config-sync
```

Or via the system journal:
```
show log tail 50 | match config-sync
```

## Troubleshooting

### Synchronization is not working

**Symptoms**: Changes on the primary do not appear on the secondary.

**Check 1 - REST API on the secondary:**
```
show service https
```

It must be running and have an API key.

**Check 2 - Network connectivity:**
```
ping 192.168.100.2
```

**Check 3 - HTTPS availability:**
```bash
curl -k https://192.168.100.2/
```

It should return a response from the VyOS API.

**Check 4 - Inspect the logs:**
```
show log | match config-sync
```

**Solution:**
```
# On the secondary, verify the API
show service https api

# Restart the HTTPS service if needed
restart https

# On the primary, check the configuration
show service config-sync

# Try a manual synchronization
reset config-sync
```

### Authentication error

**Symptoms**: `Authentication failed` in the logs.

**Cause**: The API keys do not match.

**Solution:**

On the secondary:
```
show service https api keys
```

On the primary:
```
show service config-sync secondary key
```

Update the key on the primary if they differ:
```
set service config-sync secondary key 'correct-key-from-secondary'
commit
```

### Timeout errors

**Symptoms**: `Connection timeout` in the logs.

**Causes:**
- Slow network
- Large configuration
- Overloaded secondary

**Solution:**

Increase the timeout:
```
set service config-sync secondary timeout 180
commit
```

Check the load on the secondary:
```
# On the secondary
show system cpu
show system memory
```

### Partial synchronization

**Symptoms**: Some sections synchronize, others do not.

**Check:**
```
show log | match "config-sync.*Failed"
```

**Possible causes:**
- VyOS version incompatibility
- Syntax errors in the configuration
- Insufficient API key permissions

**Solution:**

Check the versions:
```
# On both routers
show version
```

Validate the configuration:
```
show configuration commands | grep <section>
```

### Secondary router offline

**Symptoms**: `Connection refused` or `No route to host`.

**Check:**
```
ping 192.168.100.2
show log | match config-sync
```

**Behavior**: Config Sync will keep retrying on the next commit.

**Solution:**
- Restore network connectivity
- Check the firewall between the routers
- After recovery, run `reset config-sync`

### Configuration conflicts

**Symptoms**: After synchronization, the secondary has errors or unexpected behavior.

**Cause**: The `set` mode can create conflicts.

**Solution:**

Switch to `load` mode:
```
set service config-sync mode load
commit
```

Manually clear the section configuration on the secondary if needed:
```
# On the secondary
delete firewall
commit

# Config Sync will load a fresh configuration on the next commit on the primary
```

### VyOS version mismatch

**Symptoms**: Synchronization works, but the secondary shows errors.

**Check:**
```
# On both routers
show version | grep Version
```

**Solution**: Upgrade both routers to the same VyOS version.

## Security

### Protecting the API key

**Generating a strong key:**
```bash
openssl rand -base64 32
```

Example output:
```
3Km8WxT7qN9vB2hL5pY6sF1dC4eR8tU3jH7gN2mK9xP=
```

**Do not use weak keys:**
- Dictionary words
- Simple patterns (123456, password)
- Short keys (< 20 characters)

### Firewall rules

Restrict REST API access to the primary router only:

**On the secondary router:**
```
# Allow HTTPS only from the primary
set firewall ipv4 input filter rule 100 action accept
set firewall ipv4 input filter rule 100 destination port 443
set firewall ipv4 input filter rule 100 protocol tcp
set firewall ipv4 input filter rule 100 source address 192.168.100.1

# Deny all other HTTPS connections
set firewall ipv4 input filter rule 110 action drop
set firewall ipv4 input filter rule 110 destination port 443
set firewall ipv4 input filter rule 110 protocol tcp

commit
```

### HTTPS certificates

**Self-signed certificates (internal networks):**
```
set service https certificates system-generated-certificate
commit
```

**Custom certificates:**
```
# First, import the certificate via PKI
set pki certificate vyos-cert certificate 'MII...'
set pki certificate vyos-cert private key 'MII...'

# Use it in HTTPS
set service https certificates certificate vyos-cert
commit
```

### Restricting the listen-address

Listen only on the internal interface:

```
set service https listen-address 192.168.100.2
set service https listen-address 10.0.0.2
commit
```

**Do not use:**
```
# Dangerous - listens on all interfaces
set service https listen-address 0.0.0.0
```

### Audit logging

Enable logging of all API operations:

```
set system syslog global facility all level info
set system syslog host 192.168.1.100 facility all level info
commit
```

## Best practices

### Planning

1. **Choose the right sections**: Synchronize only what must be identical
2. **Test on staging**: Verify Config Sync in a test environment before production
3. **Document the architecture**: Clearly indicate which router is primary and which is secondary

### Configuration

4. **Use load mode**: Guarantees identical configurations
5. **Do not synchronize interfaces blindly**: Interfaces may have different IP addresses
6. **Generate strong API keys**: At least 32 characters of random data
7. **Set an adequate timeout**: Account for configuration size and network speed

### Operations

8. **Monitor the logs**: Regularly check synchronization success
9. **Test failover**: Periodically verify that the secondary is operational
10. **Make backups**: Config Sync does not replace a backup
11. **Version control**: Keep configuration history in git

### Security

12. **Restrict the firewall**: Only the primary should have access to the secondary's API
13. **Use internal networks**: Do not synchronize over the public internet without a VPN
14. **Rotate keys regularly**: Rotate API keys every 90 days
15. **Log all operations**: Centralized logging for an audit trail

### Fault tolerance

16. **Test failover scenarios**: Primary goes down, switch over to the secondary
17. **Document recovery procedures**: How to bring the primary back into service
18. **Synchronization after recovery**: How to restore sync after downtime
19. **Monitor both routers**: Alerting on synchronization problems

## Limitations

1. **One-way synchronization**: Primary → secondary only
2. **Requires an online secondary**: Both routers must be reachable
3. **Identical VyOS version**: Version incompatibility can cause errors
4. **No conflict resolution**: Changes on the secondary are overwritten
5. **Single secondary**: Cannot synchronize with multiple secondaries simultaneously
6. **Synchronous operations**: The commit is blocked until synchronization completes

## Alternative approaches

### For multiple replication

If you need to synchronize more than 2 routers:

1. **Configuration Management**: Ansible, SaltStack, Puppet
2. **Git-based**: Store configurations in git, apply via CI/CD
3. **Scripted sync**: Custom scripts using the VyOS API

### For bidirectional sync

Config Sync does not support two-way synchronization. Options:

1. **Two Config Sync instances**: Configure mutual synchronization (beware of loops!)
2. **External orchestration**: Ansible with centralized state
3. **Manual coordination**: Choose one router as the source of truth

## Integration with HA

Config Sync works great with VyOS HA (VRRP):

**Primary** (VRRP Master):
```
configure

# VRRP
set high-availability vrrp group LAN vrid 10
set high-availability vrrp group LAN interface eth1
set high-availability vrrp group LAN address 192.168.1.1/24

# Config Sync
set service config-sync secondary address '192.168.100.2'
set service config-sync secondary key 'HA-Sync-Key'
set service config-sync section firewall
set service config-sync section nat
set service config-sync section service

commit
save
```

**Secondary** (VRRP Backup):
```
configure

# VRRP (same settings)
set high-availability vrrp group LAN vrid 10
set high-availability vrrp group LAN interface eth1
set high-availability vrrp group LAN address 192.168.1.1/24

# REST API for Config Sync
set service https api keys id config-sync key 'HA-Sync-Key'
set service https api rest

commit
save
```

**Result**:
- VRRP provides IP failover
- Config Sync guarantees an identical configuration
- If the primary goes down, the secondary is ready to take over

## Monitoring

### Prometheus metrics

If you use the VyOS Prometheus exporter:

```yaml
# Metrics to monitor
- vyos_config_sync_last_success_timestamp
- vyos_config_sync_failures_total
- vyos_config_sync_duration_seconds
```

### Zabbix monitoring

A script to check synchronization:

```bash
#!/bin/bash
# check_config_sync.sh

LAST_SYNC=$(grep "Successfully synced" /var/log/messages | tail -1)
SYNC_TIME=$(echo "$LAST_SYNC" | awk '{print $1, $2, $3}')

# Check that synchronization happened within the last hour
if [ -z "$SYNC_TIME" ]; then
    echo "CRITICAL: No config sync found"
    exit 2
fi

# Return OK
echo "OK: Last sync at $SYNC_TIME"
exit 0
```

### Syslog

Send Config Sync logs to a centralized syslog:

```
set system syslog host 192.168.1.100 facility all level info
set system syslog host 192.168.1.100 port 514
commit
```

## Scenario examples

### Initial setup of a new HA pair

**Step 1 - Configure the secondary:**
```
configure
set service https api keys id ha-sync key 'GeneratedSecureKey123'
set service https api rest
set service https listen-address 192.168.100.2
commit
save
```

**Step 2 - Configure the primary:**
```
configure
set service config-sync secondary address '192.168.100.2'
set service config-sync secondary key 'GeneratedSecureKey123'
set service config-sync section firewall
set service config-sync section nat
set service config-sync section vpn
commit
save
```

**Step 3 - Verify:**
```
show log | match config-sync
```

**Step 4 - Test a change:**
```
configure
set firewall ipv4 input filter rule 999 action accept
set firewall ipv4 input filter rule 999 description "Test sync"
commit
```

**Step 5 - Check on the secondary:**
```
show firewall ipv4 input filter rule 999
```

### Recovery after a failure

**Scenario**: The primary was offline and changes were made on the secondary.

**Step 1 - Determine the source of truth:**
- If the secondary configuration is correct, make it the new primary
- If the primary configuration is correct, re-synchronize

**Step 2 - Switching roles (secondary → primary):**

On the old secondary (now the primary):
```
configure
set service config-sync secondary address '192.168.100.1'
set service config-sync secondary key 'HA-Sync-Key'
set service config-sync section firewall
# ... remaining sections
commit
```

On the old primary (now the secondary):
```
configure
delete service config-sync
set service https api keys id ha-sync key 'HA-Sync-Key'
set service https api rest
commit
```

**Step 3 - Force synchronization:**
```
reset config-sync
```

### Planned maintenance

**Before maintenance:**
```
# Back up both routers
show configuration commands | cat > /config/backup-$(date +%Y%m%d).conf

# Verify that the secondary is synchronized
show log | match config-sync | tail -20
```

**During maintenance:**
```
# Temporarily disable Config Sync if you are changing the primary
set service config-sync secondary disable
commit

# Perform the maintenance
# ...

# Re-enable it
delete service config-sync secondary disable
commit

# Re-synchronize
reset config-sync
```

## Troubleshooting Checklist

When you run into problems, go through this list:

- [ ] REST API is running on the secondary (`show service https`)
- [ ] API keys match on the primary and secondary
- [ ] Network connectivity (ping, traceroute)
- [ ] HTTPS port is reachable (curl, telnet)
- [ ] Firewall is not blocking HTTPS between the routers
- [ ] VyOS versions match on both devices
- [ ] Sections to synchronize are specified correctly
- [ ] Timeout is sufficient for the configuration size
- [ ] Logs show no synchronization errors
- [ ] The secondary router is not overloaded (CPU, memory)
- [ ] The configuration on the primary is valid (`commit check`)

## Next steps

- [High Availability (VRRP)](/docs/vyos/ha/) - configuring VRRP for IP failover
- [HTTPS API](/docs/vyos/services/vyos-https/) - detailed REST API setup
- [System Login](/docs/vyos/system/vyos-login/) - managing users and API keys
- [Monitoring](/docs/vyos/services/) - monitoring Config Sync operations

