SaltStack – Getting started with SaltStack – Part 1

SaltStack Introduction

SaltStack – Fast, scalable and flexible systems management software for data center automation, cloud orchestration, server provisioning, configuration management and more

This quick tutorial describes a way to install a shell script onto a remote “Minion” (read: SLAVE) in a Saltstack environment. I wont go into details about what SaltStack is, there are plenty of websites that give you high level overviews, instead, I will present a simple tutorial on how to install and how to run a shell script onto a slave server (AKA a “Minion”). It took me a while to get my head around this, partly due to the config file definition format which is sensitive to spaces and the location and placement of files in the SaltStack environment.

State Files

A State File is like a configuration file, it defines the config/state for an application or service. In our case we will create an “install.sls” file which has commands to install a shell script on the remote server and a “run.sls” file which will run the script. You could use any names but these will be obvious.

The script we will install is one I commonly install on servers, its a cleanup script to remove old log files. The script is called the code is on this blog so you can download it and use it. The state files contain the definitions that salt uses to implement functionality, so they can contain running commands as well as configuration. The first file to create is “install.sls”, we will place it in salt’s base script directory which on my install is /srv/salt, we will need to create a directory under that called “cleanup” so you need to create /srv/salt/cleanup.

The “install.sls” file contents are as follows:

 - managed
 - source: salt://
 - name: /usr/local/bin/
 - user: root
 - group: root
 - mode: 754

NOTE: “file:” is indented two spaces, then the “-” lines are indented 2 more spaces (column 4). Salt uses YAML to parse the files and YAML requires specific spacing, tabs are a NO-NO and the wrong spacing will result in errors.

As you can see the shell script will live in /usr/local/bin, the “source” tag defines its on the master and the “minions” will download it from there. I use vi to edit this file and its saved back to /srv/salt/cleanup. Keep in mind that the base path is defined in /etc/salt/master. If the salt config files are not here then place the cleanup folder in the right place for your OS installation (I’m running an Ubuntu OS for my Salt master).

The RUN file

The run.sls file lives in the same place as the install.sls file, it also has the same indent requirements.

 - name: /usr/local/bin/
 - cwd: /usr/local/bin
 - stateful: True

The Shell Script

Place the shell script in the /srv/salt/cleanup directory, this is where it will be downloaded from by the “Minions”.

The “top.sls” file

If you have a look inside the /srv/salt folder there should be a file called top.sls. This file contains commands to run specifically for each “Minion” when you set them up or execute a state.highstate using the Minions “salt-call” command. I have added the cleanup entries so the script is installed. I could also use a wildcard ‘*’ to make it install on all servers if needed.

 - bind-utils
 - cleanup.install


Executing the install.sls

Below is the basic command line to initiate an install of the script. I use the “salt” command, specify the server as “repo.local.lan” and use the state.sls module to run the command and finally the cleanup.install command.

salt ‘repo.local.lan’ state.sls cleanup.install

Executing the script remotely

Our basic script does not yet have any dependency testing so this script assumes it is already installed. The only difference is the command which will execute the “run.sls” file located in the “cleanup” folder under the folder /srv/salt.

salt ‘repo.local.lan’ state.sls

Sample Output

ID: install-cleanup-script
Function: file.managed
Name: /usr/local/bin/
Result: True
Comment: File /usr/local/bin/ updated
New file

Succeeded: 1
Failed: 0
Total: 1

If you run the command a second time, then the output will be different, it will show any updates to the file (state changes).


If you are creating a new file to run on a specific client the try running the following command from the Minion:

salt-call state.highstate -l debug

I found that the debug output is more extensive on the client, a sample follows”

[DEBUG ] Reading configuration from /etc/salt/minion
[INFO ] Using cached minion ID from /etc/salt/minion_id:
[DEBUG ] Configuration file path: /etc/salt/minion
[DEBUG ] Reading configuration from /etc/salt/minion
[WARNING ] Although ‘dmidecode’ was found in path, the current user cannot execute it. Grains output might not be accurate.
[WARNING ] Although ‘lspci’ was found in path, the current user cannot execute it. Grains output might not be accurate.
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] Decrypting the current master AES key
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem

… lots of output

[DEBUG ] Results of YAML rendering:

OrderedDict([(‘cleanup-directories’, OrderedDict([(‘’, [OrderedDict([(‘name’, ‘’)]), OrderedDict([(‘cwd’, ‘/usr/local/bin’)]), OrderedDict([(‘stateful’, True)])])]))])
[INFO ] Running state [/usr/local/bin/] at time 14:07:34.954816
[INFO ] Executing state file.managed for /usr/local/bin/
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] Decrypting the current master AES key
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[DEBUG ] Decrypting the current master AES key
[DEBUG ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[INFO ] File /usr/local/bin/ is in the correct state
[INFO ] Completed state [/usr/local/bin/] at time 14:07:35.614072
[INFO ] Running state [] at time 14:07:35.614648
[INFO ] Executing state for
[INFO ] Executing command ‘’ in directory ‘/usr/local/bin’
[INFO ] No changes made for
[INFO ] Completed state [] at time 14:07:35.665263
[DEBUG ] Loaded no_out as virtual quiet
[DEBUG ] Loaded json_out as virtual json
[DEBUG ] Loaded yaml_out as virtual yaml
[DEBUG ] Loaded pprint_out as virtual pprint
ID: install-cleanup-script
Function: file.managed
Name: /usr/local/bin/
Result: True
Comment: File /usr/local/bin/ is in the correct state
ID: cleanup-directories
Result: True

Succeeded: 2
Failed: 0
Total: 2

 Related Pages:


Enjoy – More to come so do a search on SaltStack to get more articles.

2 thoughts on “SaltStack – Getting started with SaltStack – Part 1”

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s