CoursesChefIntermediate

Attributes & precedence

Where node values come from.

Intermediate14 min · lesson 5 of 12

Attributes are the data that parameterize cookbooks — the port to listen on, the number of workers, the packages to install. They can be set in many places (cookbook attribute files, roles, environments, the node itself, recipes) and, like Ansible variables, that flexibility comes with a precedence hierarchy. Chef’s precedence has levels — default, force_default, normal, override, force_override, automatic — and the highest set level wins.

ATTRIBUTE PRECEDENCE (LOW to HIGH)
1default
cookbook attribute files
2force_default
force cookbook default
3normal
node normal attributes
4override
role / environment override
5force_override
force override level
6automatic
ohai facts, un-overridable
Attributes can be set at any level; the highest level that sets a value wins, and automatic (ohai) always wins.
attributes/default.rb
default['nginx']['worker_processes'] = 4
default['nginx']['port'] = 80
# used in a recipe or template as node['nginx']['port']

Automatic attributes (ohai)

At the start of every run, a tool called ohai profiles the node and produces automatic attributes — the highest precedence, and un-overridable — describing the platform, network, memory, CPUs, and more. You read them (node[‘platform_family’], node[‘memory’][‘total’]) to write portable recipes, exactly as you use Ansible facts. Automatic attributes always win because they are ground truth about the machine.

recipe
pkg = node['platform_family'] == 'debian' ? 'apache2' : 'httpd'
package pkg
# scale workers to the node's real CPU count (an automatic attribute)
node.default['nginx']['worker_processes'] = node['cpu']['total']
Attribute precedence is a frequent foot-gun
With six precedence levels across cookbooks, roles, environments, and nodes, a “why won’t this value change” bug usually means something at a higher level is overriding you. Keep tunable defaults at default level in cookbooks, set environment/role differences deliberately, and avoid scattering override-level attributes — like Ansible’s var precedence, discipline here saves hours of debugging.