# Templates and Inheritance **Configuration reuse patterns for large-scale ExaBGP deployments** --- ## Table of Contents - [Overview](#overview) - [Why Use Templates](#why-use-templates) - [Template Syntax](#template-syntax) - [Using Templates with inherit](#using-templates-with-inherit) - [Group Configuration](#group-configuration) - [Inheritance Rules](#inheritance-rules) - [Variables and Substitution](#variables-and-substitution) - [DRY Principles](#dry-principles) - [Large-Scale Deployment Patterns](#large-scale-deployment-patterns) - [Advanced Template Patterns](#advanced-template-patterns) - [Real-World Examples](#real-world-examples) - [Best Practices](#best-practices) - [Common Patterns](#common-patterns) - [Troubleshooting](#troubleshooting) - [See Also](#see-also) --- ## Overview **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 --- ## Why Use Templates ### Without Templates (Repetitive) ```ini 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 --- ### With Templates (DRY) ```ini # 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 Syntax ### Basic Template Definition ```ini template { neighbor { } } ``` **Example:** ```ini template { neighbor basic-peer { router-id 10.0.0.1; local-as 65001; family { ipv4 unicast; } capability { route-refresh; } } } ``` --- ### Multiple Templates You can define multiple templates: ```ini 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; } } } ``` --- ## Using Templates with inherit ### Basic Inheritance ```ini 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:** 1. Neighbor inherits all directives from template 2. Neighbor adds/overrides with its own directives 3. Final configuration combines both --- ### Overriding Template Values Child configurations can **override** template settings: ```ini 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.1` uses `hold-time 180` (from template) - `192.168.2.1` uses `hold-time 90` (overridden) --- ### Adding to Template Configuration You can **add** to template configuration: ```ini 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. --- ## Group Configuration **Groups** combine template functionality with neighbor definitions in a single block. ### Basic Group ```ini group internal-peers { # Shared configuration router-id 10.0.0.1; local-address 10.0.0.1; local-as 65001; peer-as 65001; # iBGP family { ipv4 unicast; } capability { route-refresh; } # Neighbor 1 neighbor 10.0.0.2 { description "iBGP Peer 1"; } # Neighbor 2 neighbor 10.0.0.3 { description "iBGP Peer 2"; } # Neighbor 3 neighbor 10.0.0.4 { description "iBGP Peer 3"; } } ``` **Benefits:** - Group configuration inherited by all neighbors - Each neighbor only specifies unique settings - Clear logical grouping --- ### Group with Per-Neighbor Overrides ```ini group edge-routers { router-id 10.0.0.1; local-as 65001; peer-as 65000; # eBGP family { ipv4 unicast; } capability { route-refresh; graceful-restart; } # Neighbor with defaults neighbor 192.168.1.1 { local-address 192.168.1.2; description "Edge Router 1"; } # Neighbor with override neighbor 192.168.2.1 { local-address 192.168.2.2; description "Edge Router 2 (short hold-time)"; hold-time 90; # Override group default } # Neighbor with MD5 neighbor 192.168.3.1 { local-address 192.168.3.2; description "Edge Router 3 (MD5 auth)"; md5-password "secret123"; # Add MD5 } } ``` --- ### Multiple Groups ```ini # iBGP group group ibgp-peers { 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; } neighbor 10.0.0.2 { } neighbor 10.0.0.3 { } } # eBGP group group ebgp-peers { router-id 10.0.0.1; local-as 65001; family { ipv4 unicast; } capability { route-refresh; } neighbor 192.168.1.1 { local-address 192.168.1.2; peer-as 65000; } neighbor 192.168.2.1 { local-address 192.168.2.2; peer-as 65002; } } # FlowSpec group group flowspec-peers { router-id 10.0.0.1; local-as 65001; family { ipv4 flow; } api { processes [ ddos-blocker ]; } neighbor 192.168.10.1 { local-address 192.168.10.2; peer-as 65000; } } ``` --- ## Inheritance Rules ### Rule 1: Template Must Be Defined First **Wrong:** ```ini neighbor 192.168.1.1 { inherit my-template; # ERROR: template not defined yet # ... } template { neighbor my-template { # ... } } ``` **Correct:** ```ini template { neighbor my-template { # ... } } neighbor 192.168.1.1 { inherit my-template; # OK: template defined above # ... } ``` --- ### Rule 2: Only One Template Per Neighbor **Wrong:** ```ini neighbor 192.168.1.1 { inherit template1; inherit template2; # ERROR: can't inherit multiple templates # ... } ``` **Workaround:** Use nested inheritance or merge templates manually. --- ### Rule 3: Child Overrides Take Precedence ```ini 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" } ``` --- ### Rule 4: Family Blocks Are Merged ```ini 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. --- ### Rule 5: API Processes Are Merged ```ini template { neighbor my-template { api { processes [ process1 ]; } } } neighbor 192.168.1.1 { inherit my-template; api { processes [ process2 ]; } # Final: processes [ process1, process2 ] } ``` --- ## Variables and Substitution **ExaBGP does not have native variable substitution**. However, you can achieve this using: 1. Configuration generation scripts 2. Environment variables in processes 3. External templating tools (Jinja2, ERB, etc.) --- ### Method 1: Shell Script Generation ```bash #!/bin/bash # Variables ROUTER_ID="10.0.0.1" LOCAL_AS="65001" PEER_AS="65000" # Generate configuration cat > /etc/exabgp/exabgp.conf <