-
Notifications
You must be signed in to change notification settings - Fork 459
Large Configuration File
As your ExaBGP deployment grows, configuration files can become complex and difficult to manage. This guide covers best practices for organizing, maintaining, and optimizing large ExaBGP configurations.
- Overview
- Configuration Organization
- Templates and Inheritance
- File Inclusion
- Variable Substitution
- Configuration Generation
- Performance Considerations
- Validation and Testing
- Best Practices
- Troubleshooting
- See Also
Important: ExaBGP does NOT manipulate the routing table (RIB/FIB). Large configurations typically involve many BGP neighbors, multiple address families, and complex API processes for dynamic route control.
- Many neighbors (10+ peers)
- Multiple sites with similar configurations
- Complex route policies across many peers
- Many address families (IPv4, IPv6, FlowSpec, EVPN, etc.)
- Multiple API processes for different services
- Team collaboration requiring modular configuration
Organize configuration files in a logical hierarchy:
/etc/exabgp/
βββ exabgp.conf # Main configuration file
βββ conf.d/ # Neighbor configurations
β βββ core-routers.conf # Core network peers
β βββ edge-routers.conf # Edge network peers
β βββ route-reflectors.conf # Route reflector peers
β βββ external-peers.conf # External BGP peers
βββ processes/ # API process configurations
β βββ healthcheck.conf
β βββ monitoring.conf
β βββ flowspec.conf
βββ scripts/ # API process scripts
β βββ healthcheck.py
β βββ monitor.py
β βββ ddos-mitigation.py
βββ templates/ # Configuration templates
β βββ neighbor-template.conf
β βββ process-template.conf
βββ secrets/ # Passwords and keys
βββ rr1-password.txt
βββ rr2-password.txt
The main file includes modular components:
# /etc/exabgp/exabgp.conf
# Main ExaBGP Configuration
# Global settings
log {
all = true;
destination = /var/log/exabgp/exabgp.log;
level = INFO;
}
# Include process definitions
include /etc/exabgp/processes/*.conf;
# Include neighbor definitions
include /etc/exabgp/conf.d/*.conf;ExaBGP doesn't have native template support, but you can use external tools to generate configurations from templates.
{# /etc/exabgp/templates/neighbor.j2 #}
neighbor {{ neighbor_ip }} {
router-id {{ router_id }};
local-address {{ local_address }};
local-as {{ local_as }};
peer-as {{ peer_as }};
{% if md5_password %}
md5-password "{{ md5_password }}";
{% endif %}
{% if ttl_security %}
ttl-security 255;
{% endif %}
family {
{% for family in address_families %}
{{ family }};
{% endfor %}
}
{% if route_reflector_client %}
route-reflector-client;
{% endif %}
{% if cluster_id %}
cluster-id {{ cluster_id }};
{% endif %}
{% if api_processes %}
api {
processes [ {{ api_processes | join(', ') }} ];
}
{% endif %}
}# /etc/exabgp/data/neighbors.yaml
neighbors:
- neighbor_ip: 192.0.2.1
router_id: 192.0.2.10
local_address: 192.0.2.10
local_as: 65001
peer_as: 65001
md5_password: "strong-password-123"
ttl_security: true
address_families:
- "ipv4 unicast"
- "ipv6 unicast"
route_reflector_client: true
cluster_id: 192.0.2.254
api_processes:
- healthcheck
- monitor
- neighbor_ip: 192.0.2.2
router_id: 192.0.2.10
local_address: 192.0.2.10
local_as: 65001
peer_as: 65001
md5_password: "strong-password-456"
ttl_security: true
address_families:
- "ipv4 unicast"
- "ipv6 unicast"
route_reflector_client: true
cluster_id: 192.0.2.254
api_processes:
- healthcheck
- monitor#!/usr/bin/env python3
# /usr/local/bin/generate-exabgp-config.py
import yaml
from jinja2 import Environment, FileSystemLoader
# Load configuration data
with open('/etc/exabgp/data/neighbors.yaml', 'r') as f:
data = yaml.safe_load(f)
# Setup Jinja2 environment
env = Environment(loader=FileSystemLoader('/etc/exabgp/templates'))
template = env.get_template('neighbor.j2')
# Generate configuration for each neighbor
output = []
for neighbor in data['neighbors']:
output.append(template.render(neighbor))
# Write generated configuration
with open('/etc/exabgp/conf.d/generated-neighbors.conf', 'w') as f:
f.write('\n\n'.join(output))
print("Configuration generated successfully")#!/bin/bash
# /usr/local/bin/update-exabgp-config.sh
# Generate configuration
/usr/local/bin/generate-exabgp-config.py
# Validate configuration
exabgp --test /etc/exabgp/exabgp.conf
# If validation succeeds, reload ExaBGP
if [ $? -eq 0 ]; then
systemctl reload exabgp
echo "Configuration updated and reloaded"
else
echo "Configuration validation failed"
exit 1
fiExaBGP supports including external files:
# /etc/exabgp/exabgp.conf
# Include single file
include /etc/exabgp/processes/healthcheck.conf;
# Include all files in directory
include /etc/exabgp/conf.d/*.conf;
# Include with absolute path
include /etc/exabgp/neighbors/core-routers.conf;# /etc/exabgp/conf.d/core-routers.conf
neighbor 192.0.2.1 {
router-id 192.0.2.10;
local-address 192.0.2.10;
local-as 65001;
peer-as 65001;
family {
ipv4 unicast;
}
}
neighbor 192.0.2.2 {
router-id 192.0.2.10;
local-address 192.0.2.10;
local-as 65001;
peer-as 65001;
family {
ipv4 unicast;
}
}# /etc/exabgp/conf.d/edge-routers.conf
neighbor 192.0.2.11 {
router-id 192.0.2.10;
local-address 192.0.2.10;
local-as 65001;
peer-as 65002;
family {
ipv4 unicast;
ipv4 flow;
}
}# /etc/exabgp/processes/healthcheck.conf
process healthcheck {
run /etc/exabgp/scripts/healthcheck.py;
encoder text;
}# /etc/exabgp/processes/monitoring.conf
process monitor {
run /etc/exabgp/scripts/monitor.py;
encoder json;
neighbor-changes;
receive-routes;
}While ExaBGP doesn't natively support variables, you can use preprocessing tools.
# /etc/exabgp/templates/exabgp.conf.m4
define(`ROUTER_ID', `192.0.2.10')
define(`LOCAL_AS', `65001')
define(`LOCAL_ADDRESS', `192.0.2.10')
neighbor 192.0.2.1 {
router-id ROUTER_ID;
local-address LOCAL_ADDRESS;
local-as LOCAL_AS;
peer-as 65001;
family {
ipv4 unicast;
}
}
neighbor 192.0.2.2 {
router-id ROUTER_ID;
local-address LOCAL_ADDRESS;
local-as LOCAL_AS;
peer-as 65001;
family {
ipv4 unicast;
}
}Generate configuration:
m4 /etc/exabgp/templates/exabgp.conf.m4 > /etc/exabgp/exabgp.conf#!/bin/bash
# /usr/local/bin/generate-config.sh
ROUTER_ID="192.0.2.10"
LOCAL_AS="65001"
cat > /etc/exabgp/exabgp.conf <<EOF
neighbor 192.0.2.1 {
router-id ${ROUTER_ID};
local-address ${ROUTER_ID};
local-as ${LOCAL_AS};
peer-as 65001;
family {
ipv4 unicast;
}
}
EOF#!/usr/bin/env python3
# /usr/local/bin/exabgp-config-generator.py
class ExaBGPConfig:
def __init__(self, router_id, local_as):
self.router_id = router_id
self.local_as = local_as
self.neighbors = []
self.processes = []
def add_neighbor(self, ip, peer_as, families, **kwargs):
neighbor = {
'ip': ip,
'peer_as': peer_as,
'families': families,
**kwargs
}
self.neighbors.append(neighbor)
def add_process(self, name, run, encoder='text', **kwargs):
process = {
'name': name,
'run': run,
'encoder': encoder,
**kwargs
}
self.processes.append(process)
def generate(self):
lines = []
# Log configuration
lines.append("log {")
lines.append(" all = true;")
lines.append(" destination = /var/log/exabgp/exabgp.log;")
lines.append(" level = INFO;")
lines.append("}")
lines.append("")
# Process configurations
for proc in self.processes:
lines.append(f"process {proc['name']} {{")
lines.append(f" run {proc['run']};")
lines.append(f" encoder {proc['encoder']};")
if proc.get('neighbor_changes'):
lines.append(" neighbor-changes;")
if proc.get('receive_routes'):
lines.append(" receive-routes;")
lines.append("}")
lines.append("")
# Neighbor configurations
for neighbor in self.neighbors:
lines.append(f"neighbor {neighbor['ip']} {{")
lines.append(f" router-id {self.router_id};")
lines.append(f" local-address {self.router_id};")
lines.append(f" local-as {self.local_as};")
lines.append(f" peer-as {neighbor['peer_as']};")
lines.append("")
if neighbor.get('md5_password'):
lines.append(f" md5-password \"{neighbor['md5_password']}\";")
if neighbor.get('ttl_security'):
lines.append(" ttl-security 255;")
lines.append(" family {")
for family in neighbor['families']:
lines.append(f" {family};")
lines.append(" }")
lines.append("")
if neighbor.get('route_reflector_client'):
lines.append(" route-reflector-client;")
if neighbor.get('cluster_id'):
lines.append(f" cluster-id {neighbor['cluster_id']};")
if neighbor.get('api_processes'):
lines.append(" api {")
procs = ', '.join(neighbor['api_processes'])
lines.append(f" processes [ {procs} ];")
lines.append(" }")
lines.append("}")
lines.append("")
return '\n'.join(lines)
# Example usage
config = ExaBGPConfig(router_id='192.0.2.10', local_as=65001)
# Add processes
config.add_process('healthcheck', '/etc/exabgp/scripts/healthcheck.py')
config.add_process('monitor', '/etc/exabgp/scripts/monitor.py',
encoder='json', neighbor_changes=True, receive_routes=True)
# Add neighbors
config.add_neighbor('192.0.2.1', 65001, ['ipv4 unicast', 'ipv6 unicast'],
md5_password='strong-password-123',
ttl_security=True,
route_reflector_client=True,
cluster_id='192.0.2.254',
api_processes=['healthcheck', 'monitor'])
config.add_neighbor('192.0.2.2', 65001, ['ipv4 unicast', 'ipv6 unicast'],
md5_password='strong-password-456',
ttl_security=True,
route_reflector_client=True,
cluster_id='192.0.2.254',
api_processes=['healthcheck', 'monitor'])
# Generate and save configuration
with open('/etc/exabgp/exabgp.conf', 'w') as f:
f.write(config.generate())
print("Configuration generated successfully")# /etc/ansible/playbooks/exabgp-config.yml
---
- name: Generate ExaBGP Configuration
hosts: exabgp_servers
become: true
vars:
router_id: "192.0.2.10"
local_as: 65001
neighbors:
- ip: 192.0.2.1
peer_as: 65001
families:
- ipv4 unicast
- ipv6 unicast
route_reflector_client: true
- ip: 192.0.2.2
peer_as: 65001
families:
- ipv4 unicast
- ipv6 unicast
route_reflector_client: true
tasks:
- name: Deploy ExaBGP configuration
template:
src: templates/exabgp.conf.j2
dest: /etc/exabgp/exabgp.conf
owner: exabgp
group: exabgp
mode: '0640'
notify: Reload ExaBGP
- name: Validate configuration
command: exabgp --test /etc/exabgp/exabgp.conf
register: validation
changed_when: false
handlers:
- name: Reload ExaBGP
systemd:
name: exabgp
state: reloadedLarge configurations can take time to load. Optimize:
# SLOW: Many small include files
include /etc/exabgp/neighbors/neighbor-*.conf; # 100+ files
# FASTER: Fewer larger files
include /etc/exabgp/conf.d/*.conf; # 5-10 filesEach neighbor consumes memory. For large deployments:
-
Monitor memory usage:
ps aux | grep exabgp - Use 64-bit Python: Supports larger memory spaces
- Limit concurrent sessions: Start neighbors gradually
Stagger session establishment to avoid overwhelming peers:
#!/usr/bin/env python3
# /etc/exabgp/scripts/staggered-announce.py
import sys
import time
routes = [
"198.51.100.0/24",
"203.0.113.0/24",
# ... 1000+ routes
]
# Announce routes gradually
for i, route in enumerate(routes):
print(f"announce route {route} next-hop self", flush=True)
# Brief delay every 100 routes
if i % 100 == 0:
time.sleep(1)
while True:
time.sleep(60)Always validate before deploying:
# Validate configuration syntax
exabgp --test /etc/exabgp/exabgp.conf
# Check for syntax errors
if [ $? -eq 0 ]; then
echo "Configuration is valid"
else
echo "Configuration has errors"
exit 1
fi#!/bin/bash
# /usr/local/bin/validate-exabgp-config.sh
set -e
CONFIG_FILE="/etc/exabgp/exabgp.conf"
BACKUP_DIR="/etc/exabgp/backups"
# Create backup
mkdir -p "$BACKUP_DIR"
cp "$CONFIG_FILE" "$BACKUP_DIR/exabgp.conf.$(date +%Y%m%d-%H%M%S)"
# Validate syntax
echo "Validating configuration..."
if exabgp --test "$CONFIG_FILE"; then
echo "β Syntax validation passed"
else
echo "β Syntax validation failed"
exit 1
fi
# Check for common issues
echo "Checking for common issues..."
# Check for duplicate neighbor IPs
DUPLICATES=$(grep -h "^neighbor" "$CONFIG_FILE" /etc/exabgp/conf.d/*.conf 2>/dev/null | awk '{print $2}' | sort | uniq -d)
if [ -n "$DUPLICATES" ]; then
echo "β Duplicate neighbor IPs found:"
echo "$DUPLICATES"
exit 1
else
echo "β No duplicate neighbors"
fi
# Check all included files exist
MISSING_FILES=$(grep "^include" "$CONFIG_FILE" | awk '{print $2}' | sed 's/;$//' | while read f; do [ ! -f "$f" ] && echo "$f"; done)
if [ -n "$MISSING_FILES" ]; then
echo "β Missing included files:"
echo "$MISSING_FILES"
exit 1
else
echo "β All included files exist"
fi
echo "β All validation checks passed"Test configuration changes in staging:
#!/bin/bash
# /usr/local/bin/test-exabgp-config.sh
STAGING_CONFIG="/etc/exabgp/staging/exabgp.conf"
PROD_CONFIG="/etc/exabgp/exabgp.conf"
# Validate staging configuration
echo "Testing staging configuration..."
exabgp --test "$STAGING_CONFIG"
if [ $? -eq 0 ]; then
echo "Staging configuration valid"
# Optionally: Run in dry-run mode (if supported)
# exabgp --dry-run "$STAGING_CONFIG"
read -p "Deploy to production? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
cp "$STAGING_CONFIG" "$PROD_CONFIG"
systemctl reload exabgp
echo "Configuration deployed"
fi
else
echo "Staging configuration invalid"
exit 1
fiTrack configuration changes with git:
cd /etc/exabgp
git init
git add exabgp.conf conf.d/ processes/
git commit -m "Initial ExaBGP configuration"
# After changes
git diff
git add -A
git commit -m "Add new BGP peers for datacenter 2"Add comments liberally:
# /etc/exabgp/conf.d/core-routers.conf
# Core Router 1 - Primary route reflector
# Location: DC1, Rack A12
# Contact: [email protected]
neighbor 192.0.2.1 {
router-id 192.0.2.10;
local-address 192.0.2.10;
local-as 65001;
peer-as 65001;
# MD5 auth enabled per security policy SEC-2023-001
md5-password include "/etc/exabgp/secrets/rr1-password.txt";
family {
ipv4 unicast;
}
}# GOOD: Consistent naming
/etc/exabgp/conf.d/01-core-routers.conf
/etc/exabgp/conf.d/02-edge-routers.conf
/etc/exabgp/conf.d/03-route-reflectors.conf
# BAD: Inconsistent naming
/etc/exabgp/core.conf
/etc/exabgp/Edges.cfg
/etc/exabgp/rr_config.txt
# Change management workflow
1. Create branch: git checkout -b add-new-peers
2. Make changes
3. Validate: exabgp --test /etc/exabgp/exabgp.conf
4. Test in staging
5. Peer review: git diff
6. Merge: git merge add-new-peers
7. Deploy to production
8. Monitor for issues#!/bin/bash
# /etc/cron.daily/backup-exabgp-config.sh
BACKUP_DIR="/backup/exabgp/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# Backup configuration
cp -r /etc/exabgp "$BACKUP_DIR/"
# Compress
tar czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"
rm -rf "$BACKUP_DIR"
# Keep only last 30 days
find /backup/exabgp/ -name "*.tar.gz" -mtime +30 -delete
echo "ExaBGP configuration backed up to $BACKUP_DIR.tar.gz"Symptoms: ExaBGP fails to start after configuration change.
Solutions:
- Check syntax:
exabgp --test /etc/exabgp/exabgp.conf- Check file permissions:
ls -la /etc/exabgp/exabgp.conf
# Should be readable by exabgp user- Check included files exist:
grep "^include" /etc/exabgp/exabgp.conf | awk '{print $2}' | sed 's/;$//' | xargs ls -laSymptoms: ExaBGP startup is slow.
Solutions:
- Reduce number of include files:
# Consolidate multiple small files into larger files
cat /etc/exabgp/neighbors/*.conf > /etc/exabgp/conf.d/all-neighbors.conf- Profile startup time:
time exabgp /etc/exabgp/exabgp.confSymptoms: Production config differs from version control.
Solutions:
- Use configuration management (Ansible, Puppet, Chef)
- Regular audits:
# Compare production vs git
diff /etc/exabgp/exabgp.conf /path/to/git/repo/exabgp.conf- Read-only production configs:
chmod 440 /etc/exabgp/exabgp.conf
# Prevents manual edits- Configuration Syntax - Complete configuration reference
- Templates and Inheritance - Configuration reuse patterns
- Process Configuration - Process directive documentation
- Examples Index - Index of 98 configuration examples
- Best Practices - Security hardening
π» Ghost written by Claude (Anthropic AI)
π Home
π Getting Started
π§ API
π‘οΈ Use Cases
π Address Families
βοΈ Configuration
π Operations
π Reference
- Architecture
- BGP State Machine
- Communities (RFC)
- Extended Communities
- BGP Ecosystem
- Capabilities (AFI/SAFI)
- RFC Support
π Migration
π Community
π External
- GitHub Repo β
- Slack β
- Issues β
π» Ghost written by Claude (Anthropic AI)