SaltStack is commonly used to manage and patch systems deployed in many environments. However, users less commonly utilize these same capabilities to manage the Salt related infrastructure itself. The Salt community refers to this as "Salting your Salt", or simply using the same tools (states, templates, and remote execution, etc. ) to manage the Salt related infrastructure itself. This normally includes the following components:
Tanzu Salt - all versions
Aria Config - all versions
Salt - all versions
A commonly used feature of Salt is the ability to write states, which are YAML files that are templated with the Jinja templating engine. But Salt actually really excels at remote execution at scale. So a very basic implementation of "Salting your Salt" might just be to kick off a shell script that performs the upgrade like the following:
# salt <TARGET> cmd.script salt://path/on/salt/file/server/to/script.sh --async
This command will kick off a task on the Salt minion, but will not wait for it to complete. We use the `--async` option since we expect the Salt minion to require a restart, which will cause the minion to not return the job results. However, we can monitor the Salt master event bus for an event indicating the minion is back online like this:
# salt-run state.event tagmatch='minion_start'
minion_start {"id": "MINION_ID", "cmd": "_minion_event", "pretag": null, "data": "Minion MINION_ID started at Sat Apr 26 01:12:18 2025", "tag": "minion_start", "_stamp": "2025-04-26T01:12:18.215162"}
Another basic implementation might be to have a Salt state like the following:
{# This code is intended as an example only and may not work in production. Please test your states prior to executing in production environments. #}
update_salt_minion_config:
file.managed:
- name: /etc/salt/minion
- source: salt://{{ slspath }}/minion.jinja
- mode: 640
- user: root # Set to same user that runs the Salt minion agent
- group: root # Set to same group that runs the Salt minion agent
- context: {# This allows us to pass variables into the Jinja templating engine to render the file dynamically #}
recon_max: {{ pillar['recon_max'] }}
recon_randomize: True
restart_minion_agent_as_needed:
service.running:
- name: salt-minion
- enable: true
- reload: true
- watch:
- file: update_salt_minion_config
This example is a bit contrived and may require some additional code to actually work in your specific environment, but these are the same basic modules leveraged once a service has been deployed. Of course, with the power of Jinja, there is a lot more than can be added in the way of logic, such as region specific settings, etc. Here is some additional reading that will be helpful in learning how to use Salt in general that can also be used to "Salt your Salt".
Additional tips: