CoursesSaltIntermediate

Formulas & state organization

Reusable, shareable state trees.

Intermediate12 min · lesson 8 of 12

As your state tree grows, you organize it into formulas — pre-written, reusable, parameterized state trees for a piece of software (an nginx-formula, a users-formula), structured by convention with a map.jinja for OS differences and pillar-driven configuration. Salt publishes many official formulas, and the pattern is how you keep states shareable and DRY rather than copy-pasting SLS between projects.

nginx/map.jinja
{% set nginx = salt['grains.filter_by']({
'Debian': { 'pkg': 'nginx', 'conf': '/etc/nginx/nginx.conf' },
'RedHat': { 'pkg': 'nginx', 'conf': '/etc/nginx/nginx.conf', 'user': 'nginx' },
}, merge=salt['pillar.get']('nginx:lookup')) %}
# states import this map to stay OS-portable and pillar-tunable

File roots and environments

The master serves states and files from configured file_roots, organized by environment (base, dev, prod), and gitfs lets the master pull the state tree directly from Git — so your infrastructure code is version-controlled and the master syncs it. This is how teams manage Salt at scale: formulas as reusable units, a top file wiring them to minions, pillar supplying data, all from a reviewed Git repo.

/etc/salt/master
fileserver_backend:
- gitfs
gitfs_remotes:
- https://git.acme.internal/salt/states.git:
- root: states
# the master serves the state tree straight from Git, per environment/branch
A formula runs privileged — pin and review it
A community or third-party formula applies states as root on your minions, so treat it as a dependency: pin it to a known revision (a Git tag/commit via gitfs), review what its states do before adopting, and test with state.apply test=True. An unpinned formula pulled from a moving branch can change what converges on your fleet without you touching your own code.