CoursesSaltBeginner

States & the SLS format

Declarative desired state in YAML.

Intermediate12 min · lesson 3 of 12

States are Salt’s declarative side: an SLS (SaLt State) file describes desired state in YAML, and state modules enforce it idempotently. Each state has an ID, a state function (pkg.installed, file.managed, service.running), and arguments. Apply a state and Salt converges the minion to it, reporting what changed — the same declarative model as Puppet/Chef/Ansible, expressed in Salt’s YAML+Jinja format.

nginx/init.sls
nginx_installed:
pkg.installed:
- name: nginx
nginx_config:
file.managed:
- name: /etc/nginx/nginx.conf
- source: salt://nginx/nginx.conf.jinja
- template: jinja
- require:
- pkg: nginx_installed
- watch_in:
- service: nginx_running
nginx_running:
service.running:
- name: nginx
- enable: true

Requisites: ordering and reactions

Salt orders states with requisites: require (run after another state succeeds), watch (run, and react if the watched state changed — the service reloads when its config changes), plus onchanges, onfail, and the _in variants (require_in, watch_in) that declare the relationship from the other side. Like Puppet’s metaparameters, these build the dependency graph; without them Salt uses definition order, which you should not rely on for real dependencies.

terminal
$ salt 'web1' state.apply nginx # apply just this state
web1:
ID: nginx_config
Function: file.managed
Result: True
Comment: File /etc/nginx/nginx.conf updated
Changes: ... (diff) ...
Summary: Succeeded: 3 (changed=1)
Test with test=True before applying
Salt’s dry run is test=True: salt '<target>' state.apply nginx test=True reports what each state would do without changing anything. Always run it before applying a new or edited state, especially fleet-wide — it is your plan/preview, and skipping it on a state that touches config or services is how a bad SLS converges everywhere at once.