Salt – Fastrack

  • Salt is Configuration Management Tool.
  • It is written in Python
  • It uses YAML
  • Very flexible and faster
  • Server-Client technology for Configuration Management
  • Salt works on ZeroMQ for master and Minion Communication

Components of Salt:

salt-master Master node which pushes the configuration
salt-minion Slave node which connects to Master and get the configuration
Execution Modules Salt Modules which can be used on command line execution
State Modules Salt Modules which can be used in State Files/Formulas
  • Key-Value based information derived from Minions.
  • Used to get Data about your systems.
  • Grains are static information about the underlying OS, Memory, Disks and other system properties
  • Grains are gathered automatically when the minion starts and are refreshed periodically.
  • Grains also can be pushed from Master or can be defined in /etc/salt/grains on Minions.
  • Key-Values based variables pushed from Master to minion in secured manner.
  • Pillars are not stored on Minions.
  • Used to deliver data to your systems. Data like user names, service URLs, preferred installation paths, ports, non-default app settings, etc.
  • It lets you to define data values and then assign them to one or more minions using targets.
  • Data is encrypted, so it is used to transfer passwords, ssh keys, etc.
Top File / top.sls This file is mainly used in state.apply or highstate.  States are defined according to Minions, environments in this file.
Salt Mine Used to share data values among salt minions. For eg. If you set up a shared DB.  You can configure the Salt minion that is running on the DB server to push its IP address to the salt mine automatically. This is better than storing it in a salt state or pillar.
Runners Modules that execute on Salt master to perform supporting tasks. They report job status, connection status, read data from external APIs, query salt minions
Returners Send data returned by Minions to another system such as DB.
Reactor Trigger actions when events occur.












More Terminologies:

Formula A collection of Salt state and Salt pillar files that configure an application or system component. Most formulas are made up of several Salt states spread across multiple Salt state files.
State A reusable declaration that configures a specific part of a system. Each Salt state is defined using a state declaration.
State Declaration A top level section of a state file that lists the state function calls and arguments that make up a state. Each state declaration starts with a unique ID.
State Functions Commands, used to perform a configuration task on a system.
State File File with SLS extension, contains one or more state declarations aka formula.
Pillar File A file with an SLS extension, defines custom variables and data for a system.







Important files of Salt:

/etc/salt Root configuration folder
/etc/salt/master Configuration file for salt-master
/etc/salt/minion Configuration file for salt-minion
/etc/salt/master.d Configuration directory for salt-master
/etc/salt/minion.d Configuration directory for salt-minion
/etc/salt/minion_id Stores id generated by salt for minion
/etc/salt/pki/minion Stores SSL Keys for minion
/etc/salt/pki/master Stores SSL Keys for master and connected minions


Installing Salt:

Easiest way to install salt is using bootstrap script.

wget -O
sudo sh -M stable (It will install salt-master and salt-minion)
sudo sh stable (It will install salt-minion)

You will get other ways to install salt on

Setting up Environment:

File Roots:

  • Root location where State / SLS files are stored.
  • We can set it up as per our environments such as dev, stage, prod

Configuring file_roots:

     - /opt/salt/base

Pillar Roots:

  • Root location where Pillar files are stored
  • Similar like File Roots, we can setup pillar roots as per environments such as dev, stage, prod

     - /opt/pillar/base


  • In above example we have defined “base” environment in salt and configured location of state files and pillar.
  • Best practice is to configure these parameters in separate file in
    /etc/salt/master.d/file_roots.conf and pillar_roots.conf. For this we need to uncomment “default_include: master.d/*.conf” inside /etc/salt/master.
  • Whenever we use saltenv=base, it will check for state file in /opt/salt/base and pillar information in /opt/pillar/base.Ports: By default salt uses 4505 and 4506.
    We can define these ports inside /etc/salt/master.
    Restart salt-master

Configure salt-minion

Provide minion id in /etc/salt/minion_id. By default hostname of minion is stored in it.
Provide master name in /etc/salt/minion or /etc/salt/minion.d/master

master: salt-master

Note: Make sure Salt-master is reachable using hostname from Minion machine.

Restart salt-minion

Now salt-minion will request salt-master to accept key.
On Salt Master Check salt keys:

$ salt-key
  Accepted Keys:
  Denied Keys:
  Unaccepted Keys:
  minionID ====>; Minion id provided in /etc/salt/minion_id
  Rejected Keys:

Accept Salt-key:

 $ salt-key -a minionID
 $ salt-key
   Accepted Keys:
   Denied Keys:
   Unaccepted Keys:
   Rejected Keys:

Delete Salt-key:

$ salt-key -d minionID

Basic Ping Test from salt-master:

 $ salt minionID


Salt Modules:

  • Salt has 2 types of modules: Execution Modules and State Modules.
  • Salt Modules are written in Python
  • Location of Modules: /usr/lib/python2.7/dist-packages/salt

Execution Modules:

  • Execution Modules are executed on Command line. Such as in above example we used
  • Formulation of commands modules:
     salt <target> <module.function> <argument>

    In above eg. target is minionID, module is test and ping is function from that module.

  • Location: /usr/lib/python2.7/dist-packages/salt/modules

For eg. Sysctl Execution module

  • Location is /usr/lib/python2.7/dist-packages/salt/modules/
  • Using sysctl Execution Module:
$ salt '*'
$ salt '*' sysctl.assign vm.swappiness 20

More Examples of Execution Modules:

$ salt '*' user.add fred shell=/bin/zsh
$ salt '*' network.connect port=53 proto=udp timeout=3
$ salt '*' cp.get_file salt://vimrc /etc/vimrc gzip=5
$ salt ns1 pkg.install pkgs=['bind9','bind9-docs','bind-utils']
$ salt '*' pkg.install sources='[{"foo": "salt://foo.deb"},{"bar": "salt://bar.deb"}]’


State Modules:

  • State Modules are executed using State files.
  • Location: /usr/lib/python2.7/dist-packages/salt/states

For eg. Sysctl state module

  • Location is /usr/lib/python2.7/dist-packages/salt/states/

Create State file sysctl.sls:

           - name: vm.swappiness
           - value: 30

Apply state using:

$ salt '*' state.apply sysctl

Note: Many times salt uses Execution Modules inside State Modules.

More examples of State Modules:

Add user:

    - name: fred
    - shell: /bin/zsh

Install bind packages:

   - pkgs:
       - bind9
       - bind9-docs
       - bind-utils

Install some packages using other sources:

   - name: mypkgs
   - sources:
       - foo: salt://foo.deb
       - bar:


More Command line examples:
Run a command:

$ salt '*' 'ls -l /etc'

Check Disk Usage:

$ salt '*' disk.usage

Install a Package:

$ salt '*' pkg.install cowsay

List Network Interfaces:

$ salt '*' network.interfaces

Select Target as per OS:

$ salt -G 'os:Ubuntu'

Select Target as per Minion ID:

$ salt 'minionID' disk.usage

Select Targets using Regular Expressions:

$ salt -E 'minion[0-9]'

Select Targets as list:

$ salt -L 'minion1,minion2'

Select Multiple targets in one command:

$ salt -C 'G@os:Ubuntu and minion* or S@192.168.0.*'


Writing & applying first state file or formula:

  • We will install gpm and curl using state file.
  • As per above configuration our base environment is configured.
  • File root is configured under /opt/salt/base
  • Create first state file name “first.sls” under /opt/salt/base

$ vi /opt/salt/base/first.sls
       - pkgs:
          - gpm
          - curl

We can apply particular state using “state.sls”. Here “state” is Execution Module and “sls” is function inside that.
When we apply state on particular file, it will check that file into file_roots of that environment.

So to apply above state, we need to run:

$ salt minionID state.sls first

Notes: Do not add sls extension.
If first.sls is inside /opt/salt/base/install/, then command will be ==>  salt minionID state.sls install.first

Top File

  • The Top file is used to apply multiple state files to your Salt minions during a highstate.
  • The states that are applied to each system are determined by the targets that are specified in the Top file.
  • A highstate causes all targeted minions to download the /srv/salt/top.sls file and find any matching targets.
  • If a matching target is found, the minion applies all of the states listed under that target.
  • Many users schedule highstate runs at regular intervals to ensure that systems remain in compliance.
  • Top file is used to apply state as per the type of server such as Webserver, db Server, Common for all, etc.

For eg. Top file can be like

    - vim
    - users
    - scripts
    - apache
    - python
    - mysql

Above top file will apply vim, users, scripts states to all Minions and apache, python to web servers and mysql to db servers.

Note: Do not use TAB, use Space in any SLS file  as it is YAML, it will throw an error in log file saying illegal tab character.


Top file example:
Create a Top file /opt/salt/base/top.sls and add below lines:

    - common
    - apache


Create /opt/salt/base/common.sls and add below lines:

      - pkgs:
          - vim
          - gpm

Create /opt/salt/base/apache.sls and add below lines:

      - name: apache2

Apply State:

$ salt '*' state.apply
Summary for minion1
Succeeded: 2 (changed=2)
Failed: 0
Total states run: 2
Total run time: 91.590 s

Note: If you have a large number of connected minions, you might want to limit how many systems are updated at once. You can do this using the –batch-size option:

$ salt --batch-size 10 '*' state.apply

Understanding Salt State:
Format of Salt State declaration. It uses YAML.
State_ID:     –> String that describes this state. Must be Unique
module.function:     –> State Module and Function to call
– name: name    –> Arguments: Every function takes ‘name’ as the first arg.
– argument: value
– arguments:     –> Other arguments are listed under the function.
– value1
– value2

Examples of States:
Create a Directory:

create my_new_directory:
      - name: /opt/my_new_directory
      - user: root
      - group: root
      - mode: 755

Configure service running:

      - name: mysql

Configure service running during boot:

is mysql enable at boot:
      - name: mysql
      - enable: True

Download git repo:
Salt uses State ID for the value of name. In below example name parameter is
“….” URL

   - rev: develop
   - target: /tmp/salt

We also can write like this:
Clone the SaltStack bootstrap script repo:


   - name: git # make sure git is installed first!
    - name:
    - rev: develop
    - target: /tmp/salt

Add A User:

user account for xyz:
       - name: xyz
       - shell: /bin/bash
       - home: /home/xyz
       - groups:
           - sudo

An entry to /etc/hosts file:

myserver in hosts file:
      - name: myserver
      - ip:

Call an execution function:

restart vsftpd:
        - name: service.restart
        - m_name: vsftpd  ==> # m_name gets passed to the execution module as "name"

Dry Run State:
Salt state functions provide a mechanism to display the changes that will be made during a live run. The return info will show states that will be applied in yellow and the result is reported as None.

 $ salt 'minionID' state.apply test=True

If target a directory during a state.apply or in the state Top file, salt looks for an init.sls file in that directory and applies it.

List all grains available for specific minion

 $ salt minionID

Get Grains with values using

$ salt minionID grains.items

Get value of specific Grain item

$ salt minionID grains.get os

Set Grain item role with value webserver

$ salt minionID grains.set 'role:webserver'

We also can set Grain items and values in /etc/salt/grains on minion.

List all pillar values for specific minion:

$ salt minionID

Configure Pillar values:

Create /opt/pillar/base/top.sls and add below lines:

     - common

Create /opt/pillar/base/common.sls and add below lines:

   - ramesh: 1001

Refresh Pillars on Minion:

$ salt '*' saltutil.refresh_pillar

Git Pillar items:

$ salt minionID pillar.items

Git Value of Pillar items:

$ salt '*' pillar.get users

Using Pillar in State file with the help of Jinja2:

{% for user, uid in pillar.get('users', {}).items() %}
      - uid: {{uid}}
{% endfor %}

This state will add user with defined UID in Pillar.

We also can use Grains to define values in Pillar. For eg. setup below values in common.sls

{% if grains['os_family'] == 'RedHat' %}
apache: httpd
git: git
{% elif grains['os_family'] == 'Debian' %}
apache: apache2
git: git-core
{% endif %}

And in State file use:

install apache:
      - name: {{ pillar['apache'] }}

Managing Files and Folders using Salt:
salt://  URL followed by path to the file relative to the srv/salt
Using file.managed:

deploy http.conf file:
      - name: /etc/http/conf/http.conf
      - source: salt://apache/http.conf

In above example “salt://apache/http.conf ”  is “/opt/salt/base/apache/http.conf”

Use file.append:

Insert new line we want to add to the config file.

update lftp conf:
      - name: /etc/lftp.conf
      - text: set net:limit-rate 100000:500000


Salt is very flexible and faster Configuration Management Tool. Which can be used by many ways.

Hope this note will help us to understand salt basics.

Do let me know your suggestions, questions on ngurjar [at] neeleshgurjar [dot] co [dot] in

Neelesh Gurjar has written 122 articles

One thought on “Salt – Fastrack

Leave a Reply