-
Notifications
You must be signed in to change notification settings - Fork 467
Templates and Inheritance
Configuration reuse patterns for large-scale ExaBGP deployments
- Overview
- Why Use Templates
- Template Syntax
- Using Templates with inherit
- Grouping Neighbors
- Inheritance Rules
- Variables and Substitution
- DRY Principles
- Large-Scale Deployment Patterns
- Advanced Template Patterns
- Real-World Examples
- Best Practices
- Common Patterns
- Troubleshooting
- See Also
Templates and inheritance allow you to define configuration once and reuse it across multiple neighbors, reducing duplication and maintenance burden.
Key concepts:
- Template: A named configuration block that can be inherited
-
Inheritance: A neighbor inherits settings from a template using
inherit - Group: A collection of neighbors with shared configuration
- Override: Child configurations can override template settings
Benefits:
- DRY: Don't Repeat Yourself - define once, reuse everywhere
- Consistency: Ensure all neighbors use same settings
- Maintainability: Update one template, affect all inheritors
- Scalability: Manage hundreds of neighbors efficiently
neighbor 192.168.1.1 {
router-id 10.0.0.1;
local-address 192.168.1.2;
local-as 65001;
peer-as 65000;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
neighbor 192.168.2.1 {
router-id 10.0.0.1;
local-address 192.168.2.2;
local-as 65001;
peer-as 65000;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
neighbor 192.168.3.1 {
router-id 10.0.0.1;
local-address 192.168.3.2;
local-as 65001;
peer-as 65000;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}Problems:
- 30+ lines for 3 neighbors
- Changing capabilities requires editing 3 places
- Error-prone (typos, inconsistencies)
- Doesn't scale to 100+ neighbors
# Define template once
template {
neighbor ebgp-peer {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
}
# Use template (just 5 lines per neighbor)
neighbor 192.168.1.1 {
inherit ebgp-peer;
local-address 192.168.1.2;
peer-as 65000;
}
neighbor 192.168.2.1 {
inherit ebgp-peer;
local-address 192.168.2.2;
peer-as 65000;
}
neighbor 192.168.3.1 {
inherit ebgp-peer;
local-address 192.168.3.2;
peer-as 65000;
}Benefits:
- 18 lines total (vs 30+)
- Change capabilities once, affects all neighbors
- Consistent configuration guaranteed
- Easy to add 100 more neighbors
template {
neighbor <template-name> {
<directives>
}
}Example:
template {
neighbor basic-peer {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
}
capability {
route-refresh;
}
}
}You can define multiple templates:
template {
# Template for eBGP peers
neighbor ebgp-peer {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
# Template for iBGP peers
neighbor ibgp-peer {
router-id 10.0.0.1;
local-as 65001;
peer-as 65001; # iBGP
family {
ipv4 unicast;
ipv6 unicast;
ipv4 mpls-vpn;
}
capability {
route-refresh;
graceful-restart 120;
}
}
# Template for FlowSpec
neighbor flowspec-peer {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 flow;
}
}
}template {
neighbor common-settings {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
}
}
}
neighbor 192.168.1.1 {
inherit common-settings;
local-address 192.168.1.2;
peer-as 65000;
}What happens:
- Neighbor inherits all directives from template
- Neighbor adds/overrides with its own directives
- Final configuration combines both
Child configurations can override template settings:
template {
neighbor default-peer {
router-id 10.0.0.1;
local-as 65001;
hold-time 180; # Default hold-time
family {
ipv4 unicast;
}
}
}
neighbor 192.168.1.1 {
inherit default-peer;
local-address 192.168.1.2;
peer-as 65000;
}
neighbor 192.168.2.1 {
inherit default-peer;
local-address 192.168.2.2;
peer-as 65000;
hold-time 90; # Override: use shorter hold-time
}Result:
-
192.168.1.1useshold-time 180(from template) -
192.168.2.1useshold-time 90(overridden)
You can add to template configuration:
template {
neighbor basic-peer {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
}
capability {
route-refresh;
}
}
}
neighbor 192.168.1.1 {
inherit basic-peer;
local-address 192.168.1.2;
peer-as 65000;
# Add additional family
family {
ipv4 unicast;
ipv6 unicast; # Added
}
# Add MD5 authentication
md5-password "secret123";
}Important: Family blocks are merged, not replaced. Other directives are replaced when overridden.
ExaBGP 3.4 had a group block. It no longer exists: a template plus inherit does the same job,
and the same template can be shared by any number of neighbors.
template {
neighbor internal-peers {
local-address 10.0.0.1;
local-as 65001;
peer-as 65001; # iBGP
family {
ipv4 unicast;
}
capability {
route-refresh;
}
}
}
neighbor 10.0.0.2 {
inherit internal-peers;
router-id 10.0.0.1;
description "iBGP Peer 1";
}
neighbor 10.0.0.3 {
inherit internal-peers;
router-id 10.0.0.1;
description "iBGP Peer 2";
}
neighbor 10.0.0.4 {
inherit internal-peers;
router-id 10.0.0.1;
description "iBGP Peer 3";
}Benefits:
- The template is inherited by every neighbor which asks for it
- Each neighbor only carries what makes it different
- Clear logical grouping
template {
neighbor edge-routers {
local-as 65001;
peer-as 65000; # eBGP
family {
ipv4 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
}
# Neighbor with the template defaults
neighbor 192.168.1.1 {
inherit edge-routers;
router-id 10.0.0.1;
local-address 192.168.1.2;
description "Edge Router 1";
}
# Neighbor overriding one directive
neighbor 192.168.2.1 {
inherit edge-routers;
router-id 10.0.0.1;
local-address 192.168.2.2;
description "Edge Router 2 (short hold-time)";
hold-time 90; # overrides the template
}
# Neighbor adding one directive
neighbor 192.168.3.1 {
inherit edge-routers;
router-id 10.0.0.1;
local-address 192.168.3.2;
description "Edge Router 3 (MD5 auth)";
md5-password "secret123";
}process ddos-blocker {
run /etc/exabgp/ddos-blocker.py;
encoder json;
}
template {
neighbor ibgp-peers {
local-address 10.0.0.1;
local-as 65001;
peer-as 65001;
outgoing-ttl 5;
family {
ipv4 unicast;
ipv6 unicast;
}
}
neighbor ebgp-peers {
local-as 65001;
family {
ipv4 unicast;
}
capability {
route-refresh;
}
}
neighbor flowspec-peers {
local-as 65001;
family {
ipv4 flow;
}
api {
processes [ ddos-blocker ];
}
}
}
neighbor 10.0.0.2 {
inherit ibgp-peers;
router-id 10.0.0.1;
}
neighbor 10.0.0.3 {
inherit ibgp-peers;
router-id 10.0.0.1;
}
neighbor 192.168.1.1 {
inherit ebgp-peers;
router-id 10.0.0.1;
local-address 192.168.1.2;
peer-as 65000;
}
neighbor 192.168.2.1 {
inherit ebgp-peers;
router-id 10.0.0.1;
local-address 192.168.2.2;
peer-as 65002;
}
neighbor 192.168.10.1 {
inherit flowspec-peers;
router-id 10.0.0.1;
local-address 192.168.10.2;
peer-as 65000;
}Wrong:
neighbor 192.168.1.1 {
inherit my-template; # ERROR: template not defined yet
# ...
}
template {
neighbor my-template {
# ...
}
}Correct:
template {
neighbor my-template {
# ...
}
}
neighbor 192.168.1.1 {
inherit my-template; # OK: template defined above
# ...
}Wrong:
neighbor 192.168.1.1 {
inherit template1;
inherit template2; # ERROR: can't inherit multiple templates
# ...
}Workaround: Use nested inheritance or merge templates manually.
template {
neighbor my-template {
hold-time 180;
md5-password "default";
}
}
neighbor 192.168.1.1 {
inherit my-template;
hold-time 90; # Overrides template
md5-password "custom"; # Overrides template
# Final: hold-time=90, md5-password="custom"
}template {
neighbor my-template {
family {
ipv4 unicast;
}
}
}
neighbor 192.168.1.1 {
inherit my-template;
family {
ipv6 unicast; # Merged with template
}
# Final: ipv4 unicast + ipv6 unicast
}Note: This is an exception to Rule 3. Most blocks are replaced, but family is merged.
template {
neighbor my-template {
api {
processes [ process1 ];
}
}
}
neighbor 192.168.1.1 {
inherit my-template;
api {
processes [ process2 ];
}
# Final: processes [ process1, process2 ]
}ExaBGP does not have native variable substitution. However, you can achieve this using:
- Configuration generation scripts
- Environment variables in processes
- External templating tools (Jinja2, ERB, etc.)
#!/bin/bash
# Variables
ROUTER_ID="10.0.0.1"
LOCAL_AS="65001"
PEER_AS="65000"
# Generate configuration
cat > /etc/exabgp/exabgp.conf <<EOF
template {
neighbor ebgp-peer {
router-id ${ROUTER_ID};
local-as ${LOCAL_AS};
peer-as ${PEER_AS};
family {
ipv4 unicast;
}
}
}
neighbor 192.168.1.1 {
inherit ebgp-peer;
local-address 192.168.1.2;
}
neighbor 192.168.2.1 {
inherit ebgp-peer;
local-address 192.168.2.2;
}
EOFTemplate file (exabgp.conf.j2):
template {
neighbor ebgp-peer {
router-id {{ router_id }};
local-as {{ local_as }};
peer-as {{ peer_as }};
family {
ipv4 unicast;
}
}
}
{% for neighbor in neighbors %}
neighbor {{ neighbor.ip }} {
inherit ebgp-peer;
local-address {{ neighbor.local_address }};
description "{{ neighbor.description }}";
}
{% endfor %}Render script (generate_config.py):
from jinja2 import Template
config = {
'router_id': '10.0.0.1',
'local_as': 65001,
'peer_as': 65000,
'neighbors': [
{'ip': '192.168.1.1', 'local_address': '192.168.1.2', 'description': 'Router 1'},
{'ip': '192.168.2.1', 'local_address': '192.168.2.2', 'description': 'Router 2'},
{'ip': '192.168.3.1', 'local_address': '192.168.3.2', 'description': 'Router 3'},
]
}
with open('exabgp.conf.j2') as f:
template = Template(f.read())
with open('/etc/exabgp/exabgp.conf', 'w') as f:
f.write(template.render(config))Environment variables can be used inside processes, not in configuration file:
process healthcheck {
run /etc/exabgp/api/healthcheck.py;
encoder text;
env {
SERVICE_IP = "100.10.0.100";
SERVICE_PORT = "80";
ANNOUNCE_PREFIX = "100.10.0.0/24";
}
}Process script (healthcheck.py):
import os
service_ip = os.environ['SERVICE_IP']
service_port = os.environ['SERVICE_PORT']
announce_prefix = os.environ['ANNOUNCE_PREFIX']
# Use variables in logic
if check_health(service_ip, service_port):
print(f"announce route {announce_prefix} next-hop self")
else:
print(f"withdraw route {announce_prefix}")DRY: Don't Repeat Yourself
Before:
neighbor 192.168.1.1 { router-id 10.0.0.1; local-as 65001; family { ipv4 unicast; } }
neighbor 192.168.2.1 { router-id 10.0.0.1; local-as 65001; family { ipv4 unicast; } }
neighbor 192.168.3.1 { router-id 10.0.0.1; local-as 65001; family { ipv4 unicast; } }After:
template {
neighbor common { router-id 10.0.0.1; local-as 65001; family { ipv4 unicast; } }
}
neighbor 192.168.1.1 { inherit common; local-address 192.168.1.2; peer-as 65000; }
neighbor 192.168.2.1 { inherit common; local-address 192.168.2.2; peer-as 65000; }
neighbor 192.168.3.1 { inherit common; local-address 192.168.3.2; peer-as 65000; }Create specialized templates from base templates (via config generation):
Base template:
template {
neighbor base-peer {
router-id 10.0.0.1;
local-as 65001;
capability {
route-refresh;
}
}
}Specialized templates (add features):
template {
neighbor base-peer { /* ... */ }
neighbor ebgp-peer {
router-id 10.0.0.1;
local-as 65001;
capability {
route-refresh;
graceful-restart; # Added for eBGP
}
family {
ipv4 unicast;
ipv6 unicast;
}
}
neighbor ibgp-peer {
router-id 10.0.0.1;
local-as 65001;
peer-as 65001; # iBGP
capability {
route-refresh;
}
family {
ipv4 unicast;
ipv6 unicast;
ipv4 mpls-vpn; # Added for iBGP
}
}
}Bad: Duplicate values across config
neighbor 192.168.1.1 { local-as 65001; /* ... */ }
neighbor 192.168.2.1 { local-as 65001; /* ... */ }
neighbor 192.168.3.1 { local-as 65001; /* ... */ }
# If AS number changes, must update 3 placesGood: Define once in template
template {
neighbor common { local-as 65001; /* ... */ }
}
neighbor 192.168.1.1 { inherit common; /* ... */ }
neighbor 192.168.2.1 { inherit common; /* ... */ }
neighbor 192.168.3.1 { inherit common; /* ... */ }
# AS number change: update 1 place# Template for all peers
template {
neighbor global-peer {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
}
# US region
neighbor 192.168.1.1 { inherit global-peer; local-address 192.168.1.2; peer-as 65100; description "US-East-1"; }
neighbor 192.168.1.3 { inherit global-peer; local-address 192.168.1.2; peer-as 65101; description "US-East-2"; }
neighbor 192.168.2.1 { inherit global-peer; local-address 192.168.2.2; peer-as 65102; description "US-West-1"; }
# ... 50 more US peers
# EU region
neighbor 192.168.10.1 { inherit global-peer; local-address 192.168.10.2; peer-as 65200; description "EU-West-1"; }
neighbor 192.168.10.3 { inherit global-peer; local-address 192.168.10.2; peer-as 65201; description "EU-West-2"; }
# ... 50 more EU peersNote: there is no group block, every neighbor names the template it inherits. To avoid repeating
the line 50 times, generate the configuration (see the pattern at the end of this page).
# Base template
template {
neighbor base-config {
router-id 10.0.0.1;
local-as 65001;
capability { route-refresh; }
}
}
# Unicast template
template {
neighbor unicast-peer {
router-id 10.0.0.1;
local-as 65001;
family { ipv4 unicast; ipv6 unicast; }
capability { route-refresh; graceful-restart; }
}
}
# FlowSpec template
template {
neighbor flowspec-peer {
router-id 10.0.0.1;
local-as 65001;
family { ipv4 flow; }
}
}
# VPN template
template {
neighbor vpn-peer {
router-id 10.0.0.1;
local-as 65001;
family { ipv4 mpls-vpn; l2vpn evpn; }
capability { extended-message; }
}
}
# Use appropriate template per service
neighbor 192.168.1.1 { inherit unicast-peer; local-address 192.168.1.2; peer-as 65000; }
neighbor 192.168.2.1 { inherit flowspec-peer; local-address 192.168.2.2; peer-as 65000; }
neighbor 192.168.3.1 { inherit vpn-peer; local-address 192.168.3.2; peer-as 65000; }Python script to generate config for 1000 peers:
#!/usr/bin/env python3
# Configuration data
config = {
'router_id': '10.0.0.1',
'local_as': 65001,
'peers': []
}
# Generate 1000 peers
for i in range(1, 1001):
config['peers'].append({
'ip': f'192.168.{i//256}.{i%256}',
'local_address': '10.0.0.1',
'peer_as': 65000 + (i % 10),
'description': f'Peer-{i}'
})
# Write configuration
with open('/etc/exabgp/exabgp.conf', 'w') as f:
# Template
f.write("""
template {
neighbor base-peer {
router-id %s;
local-as %s;
family {
ipv4 unicast;
}
capability {
route-refresh;
}
}
}
""" % (config['router_id'], config['local_as']))
# Neighbors
for peer in config['peers']:
f.write("""
neighbor %s {
inherit base-peer;
local-address %s;
peer-as %s;
description "%s";
}
""" % (peer['ip'], peer['local_address'], peer['peer_as'], peer['description']))
print(f"Generated config with {len(config['peers'])} neighbors")# Define processes
process healthcheck {
run /etc/exabgp/api/healthcheck.py;
encoder text;
}
process receive-routes {
run /etc/exabgp/api/receive.py;
encoder json;
receive { parsed; updates; }
}
# Template with API
template {
neighbor api-enabled {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
}
api {
processes [ healthcheck, receive-routes ];
}
}
}
# Use template
neighbor 192.168.1.1 {
inherit api-enabled;
local-address 192.168.1.2;
peer-as 65000;
}# High-security template
template {
neighbor secure-peer {
router-id 10.0.0.1;
local-as 65001;
md5-password "ChangeThisPassword!";
incoming-ttl 255;
hold-time 90;
family {
ipv4 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
}
# Use for sensitive peers
neighbor 203.0.113.1 {
inherit secure-peer;
local-address 192.0.2.1;
peer-as 13335; # Cloudflare
description "Critical Transit Provider";
md5-password "ActualSecurePassword123!"; # Override default
}template {
neighbor ibgp-rr-client {
router-id 10.0.0.1;
local-address 10.0.0.1; # Loopback
local-as 65001;
peer-as 65001; # iBGP
outgoing-ttl 5;
family {
ipv4 unicast;
ipv6 unicast;
ipv4 mpls-vpn;
}
capability {
route-refresh;
graceful-restart 120;
}
}
}
# Route reflector clients
neighbor 10.0.0.2 { inherit ibgp-rr-client; description "RR Client 1"; }
neighbor 10.0.0.3 { inherit ibgp-rr-client; description "RR Client 2"; }
neighbor 10.0.0.4 { inherit ibgp-rr-client; description "RR Client 3"; }process announce-anycast {
run /etc/exabgp/api/announce_anycast.py;
encoder text;
}
template {
neighbor upstream-provider {
router-id 192.0.2.1;
local-as 65001;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
api {
processes [ announce-anycast ];
}
}
}
# 10 upstream providers
neighbor 203.0.113.1 { inherit upstream-provider; local-address 203.0.113.2; peer-as 174; description "Cogent"; }
neighbor 203.0.113.5 { inherit upstream-provider; local-address 203.0.113.6; peer-as 1299; description "Telia"; }
neighbor 203.0.113.9 { inherit upstream-provider; local-address 203.0.113.10; peer-as 3356; description "Level3"; }
# ... 7 more providersConfig generation for 100 leafs:
#!/usr/bin/env python3
# Template
template = """
template {{
neighbor leaf-switch {{
router-id 10.0.0.1;
local-address 10.0.0.1;
local-as 65000;
family {{
l2vpn evpn;
}}
capability {{
extended-message;
}}
}}
}}
"""
# Generate 100 leaf neighbors
with open('/etc/exabgp/exabgp.conf', 'w') as f:
f.write(template)
for rack in range(1, 11): # 10 racks
for leaf in range(1, 11): # 10 leafs per rack
leaf_id = (rack - 1) * 10 + leaf
leaf_ip = f"10.{rack}.{leaf}.1"
f.write(f"""
neighbor {leaf_ip} {{
inherit leaf-switch;
peer-as 65{leaf_id:03d};
description "Rack{rack:02d}-Leaf{leaf:02d}";
}}
""")process ddos-blocker {
run /etc/exabgp/api/ddos_blocker.py;
encoder text;
}
template {
neighbor scrubbing-center {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 flow;
}
api {
processes [ ddos-blocker ];
}
}
}
# Regional scrubbing centers (US)
neighbor 192.168.1.1 { inherit scrubbing-center; local-address 192.168.1.2; peer-as 65000; description "US-East-1 Scrubber"; }
neighbor 192.168.2.1 { inherit scrubbing-center; local-address 192.168.2.2; peer-as 65000; description "US-West-1 Scrubber"; }
# ... more US
# Regional scrubbing centers (EU)
neighbor 192.168.10.1 { inherit scrubbing-center; local-address 192.168.10.2; peer-as 65000; description "EU-West-1 Scrubber"; }
neighbor 192.168.11.1 { inherit scrubbing-center; local-address 192.168.11.2; peer-as 65000; description "EU-Central-1 Scrubber"; }
# ... more EUBad:
template { neighbor t1 { /* ... */ } }
template { neighbor t2 { /* ... */ } }Good:
template { neighbor ebgp-unicast-peer { /* ... */ } }
template { neighbor ibgp-vpn-peer { /* ... */ } }
template { neighbor flowspec-ddos-peer { /* ... */ } }# Template: eBGP peers for internet transit
# Used by: All upstream providers
# Families: IPv4/IPv6 unicast
# Features: Graceful restart, route refresh
template {
neighbor ebgp-transit {
router-id 10.0.0.1;
local-as 65001;
family {
ipv4 unicast;
ipv6 unicast;
}
capability {
route-refresh;
graceful-restart;
}
}
}Bad: Overly complex template
template {
neighbor complex-template {
# 50+ lines of configuration
# ...
}
}Good: Break into focused templates
template {
neighbor base-peer { /* Core settings */ }
neighbor ebgp-peer { /* eBGP specifics */ }
neighbor ibgp-peer { /* iBGP specifics */ }
}ExaBGP doesn't support template inheritance directly. For complex scenarios, generate config:
# config_generator.py
class TemplateRegistry:
def __init__(self):
self.templates = {}
def register(self, name, config):
self.templates[name] = config
def generate(self, template_name, overrides):
base = self.templates[template_name].copy()
base.update(overrides)
return base
# Use it
registry = TemplateRegistry()
registry.register('base', {'router_id': '10.0.0.1', 'local_as': 65001})
registry.register('ebgp', {**registry.templates['base'], 'peer_as': 65000})
# Generate neighbor
neighbor = registry.generate('ebgp', {'local_address': '192.168.1.2'})# Store templates in version control
/etc/exabgp/
├── exabgp.conf # Main config (generated)
├── templates/
│ ├── base.conf # Base template
│ ├── ebgp.conf # eBGP template
│ ├── ibgp.conf # iBGP template
│ └── flowspec.conf # FlowSpec template
├── peers/
│ ├── transit.yaml # Transit peer data
│ └── customers.yaml # Customer peer data
└── generate_config.py # Config generator# eBGP template
template {
neighbor ebgp-peer {
router-id 10.0.0.1;
local-as 65001;
family { ipv4 unicast; ipv6 unicast; }
capability { route-refresh; graceful-restart; }
}
}
# iBGP template
template {
neighbor ibgp-peer {
router-id 10.0.0.1;
local-address 10.0.0.1;
local-as 65001;
peer-as 65001;
outgoing-ttl 5;
family { ipv4 unicast; ipv6 unicast; ipv4 mpls-vpn; }
capability { route-refresh; graceful-restart 120; }
}
}
# eBGP neighbors
neighbor 203.0.113.1 { inherit ebgp-peer; local-address 203.0.113.2; peer-as 174; }
# iBGP neighbors
neighbor 10.0.0.2 { inherit ibgp-peer; }
neighbor 10.0.0.3 { inherit ibgp-peer; }# Old template (existing neighbors)
template {
neighbor legacy-peer {
hold-time 180;
capability { route-refresh; }
}
}
# New template (improved settings)
template {
neighbor modern-peer {
hold-time 90; # Faster failure detection
capability { route-refresh; graceful-restart; } # Added GR
}
}
# Migrate neighbors gradually
neighbor 192.168.1.1 { inherit legacy-peer; /* ... */ }
neighbor 192.168.2.1 { inherit modern-peer; /* ... */ } # Migrated
neighbor 192.168.3.1 { inherit legacy-peer; /* ... */ }Error:
Configuration error: template 'my-template' not found
Cause: Template not defined before use.
Fix:
# Define template BEFORE use
template {
neighbor my-template { /* ... */ }
}
# Then use it
neighbor 192.168.1.1 {
inherit my-template;
# ...
}Scenario:
template {
neighbor my-template {
hold-time 180;
}
}
neighbor 192.168.1.1 {
inherit my-template;
hold-time 90;
}Question: Why is hold-time 90, not 180?
Answer: Child configurations override template values. This is expected behavior.
Scenario:
template {
neighbor my-template {
family { ipv4 unicast; }
}
}
neighbor 192.168.1.1 {
inherit my-template;
# Expecting both ipv4 and ipv6, but only have ipv4
}Fix: Explicitly declare both families:
neighbor 192.168.1.1 {
inherit my-template;
family {
ipv4 unicast; # From template (merged)
ipv6 unicast; # Added
}
}The group block of ExaBGP 3.4 no longer exists. Each neighbor inherits a template instead, and a
configuration generator covers the cases where that becomes repetitive.
Instead of:
# Not a section: the parser rejects this
group my-group {
inherit my-template;
# ...
}Use:
# Python config generator
for peer in group_members:
print(f"""
neighbor {peer.ip} {{
inherit my-template;
local-address {peer.local_address};
peer-as {peer.peer_as};
}}
""")- Neighbor Configuration - Complete neighbor reference
- Configuration Syntax - Configuration file format
- Directives Reference - A-Z directive listing
- Large Configuration File - Managing large configs
- First BGP Session - Basic setup
Ready to scale? Start with Quick Start Guide →
Getting Started
Configuration
- Configuration Syntax
- Neighbor Configuration
- Directives A-Z
- Templates
- Environment Variables
- Process Configuration
API
- API Overview
- Text API Reference
- JSON API Reference
- API Commands
- Writing API Programs
- Error Handling
- Production Best Practices
Address Families
- Overview
- IPv4 Unicast
- IPv6 Unicast
- FlowSpec
- EVPN
- L3VPN
- BGP-LS
- VPLS
- SRv6 / MUP
- Multicast
- RT Constraint
Features
Use Cases
Tools
Operations
Reference
- Architecture
- Design
- Attribute Reference
- Command Reference
- BGP State Machine
- Capabilities
- Communities
- Examples Index
- Glossary
- RFC Support
Integration
Migration
Community
External