Skip to content

Configuration Templates

Configuration templates enable you to create reusable, parameterized network configurations that can be applied across multiple networks with different variable values. This approach promotes consistency, reduces duplication, and simplifies management of similar network deployments.

The terraform meraki module supports a template system that allows you to:

  • Define reusable templates with placeholder variables
  • Apply templates to networks with specific variable values
  • Combine multiple templates for comprehensive configurations
  • Maintain consistency across similar network deployments
  • Network level templates are supported

Templates are defined in the meraki.template.networks section of your YAML configurations.

Templates are defined in the meraki.template section of your YAML configurations. Here’s an example:

meraki:
template:
networks:
# Security appliance template
- name: appliance_baseline
appliance:
settings:
client_tracking_method: "MAC address"
deployment_mode: routed
dynamic_dns:
prefix: "${site_prefix}"
enabled: true
# Wireless configuration template
- name: corporate_wireless
wireless:
ssids:
- number: 0
name: "${corporate_ssid}"
enabled: true
auth_mode: "8021x-radius"
encryption_mode: "wpa2-eap"
radius_servers:
- host: "${radius_server_ip}"
port: 1812
secret: "${radius_secret}"
- number: 1
name: "${guest_ssid}"
enabled: true
auth_mode: "open"
splash_page: "Click-through splash page"

Networks reference templates and provide variable values:

meraki:
domains:
- name: "EMEA"
networks:
- name: "Branch-Office-01"
templates: [appliance_baseline, corporate_wireless]
variables:
site_prefix: "branch-01"
corporate_ssid: "Corp-WiFi"
guest_ssid: "Guest-WiFi"
radius_server_ip: "10.0.1.100"
radius_secret: "radiusSecret123"

Templates support variable substitution using ${variable_name} syntax:

# Network template with multiple variable types
- name: appliance_baseline
appliance:
settings:
dynamic_dns:
prefix: "${site_prefix}"
enabled: true
vlans:
- id: 10
name: "Data"
subnet: "${data_subnet}"
appliance_ip: "${data_gateway}"
dhcp:
dhcp_enabled: true
dhcp_start: "${data_dhcp_start}"
dhcp_end: "${data_dhcp_end}"
# Network implementation
- name: "Branch-London"
templates: [appliance_baseline]
variables:
site_prefix: "london-branch"
data_subnet: "10.100.10.0/24"
data_gateway: "10.100.10.1"
data_dhcp_start: "10.100.10.50"
data_dhcp_end: "10.100.10.200"

Real-World Example: Multi-Site Retail Chain

Section titled “Real-World Example: Multi-Site Retail Chain”
meraki:
template:
networks:
# Store appliance baseline
- name: store_appliance_baseline
appliance:
settings:
client_tracking_method: "MAC address"
deployment_mode: routed
dynamic_dns:
prefix: "${store_code}"
enabled: true
vlans_settings:
vlans: true
vlans:
- id: 10
name: "Store Operations"
subnet: "${store_subnet}"
appliance_ip: "${store_gateway}"
dhcp:
dhcp_enabled: true
dhcp_start: "${store_dhcp_start}"
dhcp_end: "${store_dhcp_end}"
- id: 20
name: "POS Systems"
subnet: "${pos_subnet}"
appliance_ip: "${pos_gateway}"
dhcp:
dhcp_enabled: true
dhcp_start: "${pos_dhcp_start}"
dhcp_end: "${pos_dhcp_end}"
# Store wireless configuration
- name: store_wireless
wireless:
ssids:
- number: 0
name: "${store_staff_ssid}"
enabled: true
auth_mode: "8021x-radius"
encryption_mode: "wpa2-eap"
vlan_id: 10
radius_servers:
- host: "${radius_server}"
port: 1812
secret: "${radius_secret}"
- number: 1
name: "${customer_wifi_ssid}"
enabled: true
auth_mode: "open"
vlan_id: 30
splash_page: "Click-through splash page"
meraki:
domains:
- name: "EMEA"
organizations:
- name: "Retail-Chain-EMEA"
networks:
- name: "Store-London-Oxford-Street"
templates: [store_appliance_baseline, store_wireless]
variables:
store_code: "LON-OXF-01"
store_subnet: "10.100.10.0/24"
store_gateway: "10.100.10.1"
store_dhcp_start: "10.100.10.50"
store_dhcp_end: "10.100.10.100"
pos_subnet: "10.100.20.0/24"
pos_gateway: "10.100.20.1"
pos_dhcp_start: "10.100.20.10"
pos_dhcp_end: "10.100.20.50"
store_staff_ssid: "RetailStaff-London"
customer_wifi_ssid: "FreeWiFi-London"
radius_server: "10.0.1.100"
radius_secret: "LondonRadius123"
- name: "Store-Manchester-Arndale"
templates: [store_appliance_baseline, store_wireless]
variables:
store_code: "MAN-ARN-01"
store_subnet: "10.101.10.0/24"
store_gateway: "10.101.10.1"
store_dhcp_start: "10.101.10.50"
store_dhcp_end: "10.101.10.100"
pos_subnet: "10.101.20.0/24"
pos_gateway: "10.101.20.1"
pos_dhcp_start: "10.101.20.10"
pos_dhcp_end: "10.101.20.50"
store_staff_ssid: "RetailStaff-Manchester"
customer_wifi_ssid: "FreeWiFi-Manchester"
radius_server: "10.0.1.101"
radius_secret: "ManchesterRadius456"

Combine multiple templates for comprehensive configurations:

meraki:
domains:
- name: "Global"
organizations:
- name: "Enterprise-Corp"
networks:
- name: "Enterprise-Branch-NYC"
templates: [
appliance_baseline, # Basic appliance settings
store_wireless, # Wireless configuration
corporate_wireless, # Additional SSID configs
monitoring_setup # SNMP and syslog
]
variables:
store_code: "NYC-01"
site_prefix: "nyc-branch-01"
corporate_ssid: "Corp-NYC"
guest_ssid: "Guest-NYC"
radius_server: "10.0.1.100"
# ... additional variables for all templates

Use boolean variables for optional features:

meraki:
template:
networks:
# Template with conditional security features
- name: security_optional_features
appliance:
security:
intrusion:
mode: "${intrusion_mode}"
ids_rulesets: "${ids_rulesets}"
content_filtering:
blocked_url_categories: "${blocked_categories}"
blocked_url_patterns: "${blocked_patterns}"
malware:
mode: "${malware_protection_mode}"
domains:
- name: "Enterprise"
organizations:
- name: "Secure-Branch"
networks:
- name: "High-Security-Branch"
templates: [security_optional_features]
variables:
intrusion_mode: "prevention"
ids_rulesets: "security"
blocked_categories: "Adult Content,Gambling,Malware"
blocked_patterns: "*.torrent,*.p2p"
malware_protection_mode: "enabled"
- name: "Standard-Branch"
templates: [security_optional_features]
variables:
intrusion_mode: "detection"
ids_rulesets: "balanced"
blocked_categories: "Malware"
blocked_patterns: ""
malware_protection_mode: "enabled"
  • Single Responsibility: Each template should handle one aspect of configuration
  • Logical Grouping: Group related templates (security, networking, wireless)
  • Consistent Naming: Use descriptive, consistent template names
  • Descriptive Names: Use clear, self-documenting variable names
  • Default Values: Consider providing defaults in templates where appropriate
  • Validation: Document required vs optional variables
retail-infrastructure/
├── templates/
│ ├── appliance-templates.nac.yaml # Security appliance templates
│ ├── wireless-templates.nac.yaml # Wireless configuration templates
│ └── monitoring-templates.nac.yaml # SNMP/syslog templates
├── deployments/
│ ├── retail-chain-emea.nac.yaml # EMEA region store networks
│ ├── retail-chain-americas.nac.yaml # Americas region store networks
│ └── corporate-hq.nac.yaml # Corporate headquarters
├── variables/
│ ├── store-london.yaml # London store variables
│ ├── store-manchester.yaml # Manchester store variables
│ └── corporate-shared.yaml # Shared corporate variables
└── terraform/
└── main.tf # Terraform module configuration

Variable Not Found

Error: template variable "${radius_server}" not provided for network "Store-London-01"
  • Ensure all template variables are defined in the network’s variables section

Template Not Found

Error: template "store_appliance_baseline" not found
  • Verify template names match exactly (case-sensitive)
  • Check template is defined in accessible YAML files under `meraki.template.networks“

Circular Dependencies

Error: circular dependency detected in template chain
  • Templates cannot reference themselves or create circular references
  1. Use write_model_file to inspect the fully resolved configuration
  2. Start simple with basic templates before adding complexity
  3. Validate variables by checking the resolved output matches expectations
  4. Test incrementally by applying templates to test networks first

The terraform meraki module processes templates during the planning phase:

module "meraki" {
source = "github.com/netascode/terraform-meraki-nac-meraki/modules/model"
yaml_directories = [
"./templates",
"./deployments"
]
# Optional: Write resolved model for debugging
write_model_file = "./debug/resolved-config.yaml"
}

Templates provide a powerful abstraction layer that enables scalable, maintainable network-as-code implementations while preserving the flexibility to customize configurations per site or deployment.