CoursesSaltIntermediate

Grains: minion facts

Static data for targeting and logic.

Intermediate12 min · lesson 6 of 12

Grains are static facts about a minion, gathered by the minion itself: OS and version, CPU and memory, network, virtualization, and any custom grains you set (commonly a role or environment). They are the Salt equivalent of Puppet facts or Ansible facts, used two ways — to target commands and states (-G ‘os:Ubuntu’, top-file matching) and to make states portable by branching on them.

terminal
$ salt 'web1' grains.items | head
os: Ubuntu
osrelease: 22.04
cpuarch: x86_64
mem_total: 7950
$ salt -G 'roles:web' state.apply nginx # target by a custom grain

Setting and using custom grains

You set custom grains in the minion config or with grains.setval, most often to tag a minion’s role or datacenter so you can target it. In states and templates you read grains via the grains dictionary to pick OS-appropriate package names and paths. The important distinction from pillar: grains live on and are reported by the minion, so they are not a place for secrets or for anything a compromised minion should not be able to influence.

state
{% set pkg = 'apache2' if grains['os_family'] == 'Debian' else 'httpd' %}
webserver:
pkg.installed:
- name: {{ pkg }}
Grains are minion-controlled — do not trust them for security
A minion reports its own grains, so a compromised minion can set a custom grain to claim it is, say, a ‘prod-db’ to receive states or (via targeting) data meant for that role. Never base a security decision or secret delivery purely on a settable grain; use pillar targeting and minion-id/key-based trust for anything sensitive, and treat grains as convenient, spoofable metadata.