When managing infrastructure at scale with Puppet, administrators often need to apply configurations to groups of servers sharing common domain patterns. The traditional approach of listing each node individually becomes impractical in large environments.
Puppet does support wildcard node matching in nodes.pp, though the syntax differs slightly from the example provided:
# nodes.pp
node /^[\w-]+\.acme\.com$/ {
include adminc
include common_services
}
The regex pattern /^[\w-]+\.acme\.com$/
will match any hostname ending with .acme.com, where [\w-]+
matches one or more word characters or hyphens before the domain.
Here's a more complete example showing how to combine wildcard matching with inheritance:
# Base configuration for all nodes
node base {
include puppet_agent
include security::baseline
include monitoring::agent
}
# Development environment servers
node /^dev-\d+\.acme\.com$/ inherits base {
include development_tools
include test_databases
}
# Production webservers
node /^web-\d+\.prod\.acme\.com$/ inherits base {
include apache
include app_server
include load_balancer
}
When using wildcard node definitions:
- The matching occurs in the order nodes are defined in nodes.pp
- More specific patterns should appear before general patterns
- Test patterns thoroughly before deploying to production
- Consider using Hiera for more complex classification needs
For more sophisticated node classification, you might consider:
# Using external node classifiers (ENC)
# Or with Hiera-based classification:
lookup('classes', Array[String], 'unique', []).include
The Hiera approach allows maintaining node classification data separately from your Puppet code, which can be particularly useful in large environments.
Puppet's node definitions in nodes.pp
support basic pattern matching, but the syntax differs from regular expressions. Many administrators want to apply configurations to all hosts within a specific domain without listing each host individually.
Puppet allows two types of wildcard matching in node definitions:
# Exact string match (traditional)
node 'web01.acme.com' {
include webserver
}
# Basic pattern matching
node /^.*\.acme\.com$/ {
include domain_common
}
Here's how to structure your nodes.pp
to handle both specific nodes and domain-wide patterns:
# nodes.pp
# Base configuration for all nodes
node default {
include security::baseline, monitoring::agent
}
# Specific node configuration
node 'db01.acme.com' {
include mysql::server
}
# Wildcard match for all acme.com hosts
node /.*\.acme\.com/ {
include company::internal_dns
include company::ntp
}
# Multiple domain pattern example
node /.*\.(acme|corp)\.com$/ {
include network::vpn
}
- Pattern matches use Ruby regular expression syntax
- The most specific match will be used when multiple patterns could apply
- Regex anchors (
^
and$
) are recommended for precise matching - Test patterns thoroughly in your development environment
For more complex scenarios, consider using Hiera with node classification:
# hiera.yaml
---
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Per-domain configuration"
path: "domains/%{facts.domain}.yaml"
- name: "Common configuration"
path: "common.yaml"
If your wildcard patterns aren't matching as expected:
- Verify the node's certname with
puppet config print certname
- Check for typos in your regex pattern
- Test your pattern in Ruby's regex tester
- Ensure no more specific node definition is taking precedence