Exploring Saltstack at work and home.

Author avatar
Aden
AI Salt Image

I am a big advocate of SaltStack. I first started using it a couple of years ago when I was introduced to it at my workplace. After learning how it worked I deployed it across my entire home network and have used it on everything ever since.

SaltStack is a powerful configuration management and orchestration tool that I have grown to appreciate for its flexibility and efficiency. It allows you to automate the deployment and management of infrastructure, ensuring consistency and reducing manual effort.

I’ve published a few Salt States on my GitHub. They are mostly simple Salt States that will install and run programs such as LibreNMS.

LibreNMS

Prometheus & Node Exporter

Wazuh Agent

Why, though?

I am particularly fond of SaltStack because of its ease of use and scalability. Its declarative language, YAML, makes writing configuration states straightforward and readable.

In addition to being passive (Deploy X state to install this program) SaltStack can handle events as they happen and supports both sending and receiving instructions, making it versatile enough to manage complicated setups easily.

It being written in Python makes it very easily extensible, with tons of Salt Modules existing for third party applications available on GitHub.

How It Works

SaltStack operates using a master-minion architecture. The master server sends commands to the minion agents installed on each managed system (VM’s, containers, hardware etc.).

You can use the command line salt '*' cmd.run 'ls -l /etc' which will run ls -l /etc on all of the Salt Minions.

But Salt really shines when you start creating files called Salt States which are YAML files but with file extension sls. They describe the desired configuration of the systems. The minions execute these states, ensuring that the systems are configured as defined in the .sls file. This setup allows for efficient, scalable management of numerous systems.

See this example:

install_tree_now: <--- ID: (Identifier)
  pkg.installed:  <--- State: Name of the module containing the function (like `pkg`) & the name of the Function (Like `installed`)
    - pkgs:       <--- Modifier: 
        - tree    <--- Name: is the name of the state call, which is usually the name of the file to be managed or the name of the package to be installed.

This Salt Module will check if tree is installed on the system. If it isn’t, it will install it. If it’s already installed, it will move on, and do nothing.

You could also simplify this salt state by doing the following:

If you set the ID to match the name of the package you want to install (or command you want to run, or file you want to create…), you can omit the -name option because it will be automatically derived from the ID. For instance, this snippet installs NGINX:

## install_tree.sls
tree:
  pkg.installed

I really like this compared to Ansible or Puppet because Salt simply ensures the state of the system matches the Salt State. It will not undo current configurations if you apply a configuration twice.

Use your new Salt State

To use your new Salt State, you would run the following: salt my-nas state.apply install_tree

With my-nas being the name of the Salt Minion you want to use, and state.apply being the Salt function that… applies states :)

Notice the file extension is dropped. Salt interprets the file reading only the filename.

Outro

This is a super basic introduction to Saltstack. If you are curious to learn more I would highly recommend checking out the Salt Documentation, it is really quite good.