Saltstack is a configuration management tool to efficiently administrate systems and define for example what packages should be installed on them or how SSH should be configured. In a usual environment, this is done via an agent on the systems (salt-minion) that connects to a main controlling instance (salt-master). On a smaller scale or if you just do not want to install the salt-minion on the system, salt also offers configuration over plain SSH called salt-ssh.

Following this guide you will setup salt-ssh and get an introduction into configuration management via Saltstack.

Setting up salt-ssh

First you will need to install the required packages on the system from which you will administrate the minions, e.g. your PC or laptop from which you usually connect to them via ssh (the exact name of the packages might differ depending on what distribution you are using):

  • salt-master
  • salt-ssh
  • git

The salt-master is needed even if the agentless salt-ssh method is used because salt-ssh uses the same configuration as the salt-master.

Next, create the ssh key that salt-ssh will use to connect to the systems:

ssh-keygen -t rsa -f /etc/salt/pki/master/ssh/salt-ssh.rsa

On the minions, add the /etc/salt/pki/master/ssh/salt-ssh.rsa.pub to the authorized_keys file of the root user or a user that has passwordless sudo privileges.
If you use cloud-init, you can use the following user-data example to fully prepare the system to be administrated by salt-ssh:

packages:
  - python3

groups:
  - salt-admin

users:
  - name: salt-admin
    gecos: Salt Admin
    primary_group: salt-admin
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      -  ###publickeyhere###

Normally, salt minions sign up with the salt-master but since the salt-minion is not used in this case, we need to make our local salt environment aware of the systems manually. This is done by creating a roster file at /etc/salt/roster. The roster file can configure for each host individually how a connection should be done but in our case the configuration is quite simple:

yourhost.example.com:
  user: salt-admin
  sudo: true

This tells salt-ssh that it should use the user salt-admin and execute all commands with sudo when managing the host yourhost.example.com.

To see if everything is set up correctly, you can use the test.ping command:

salt-ssh yourhost.example.com test.ping

If this returns True, then congratulations! You can now manage that system via Saltstack!

Terminology

Saltstack uses three main types of data to figure out how exactly to configure a client.:

Salt State

A salt state is a definition for one specific configuration you want the minion to have. This can be a package that is installed or a specific file that should be deployed.

By default, these live in /srv/salt.

Grain

This is information that is gathered from the minion itself. This for example includes the used OS and its version or the amount of CPUs installed. You can see a full list of available grains by executing the grains.ls command and get the content of a specific grains by using the grains.get command:

salt-ssh yourhost.example.com grains.ls
salt-ssh yourhost.example.com grains.get os

Or get the values of all grains:

salt-ssh yourhost.example.com grains.items

Pillar

This is information that is attached to a minion from the master using defined rules. Together with Jinja Templating in the states, this is the core feature that makes Saltstack really powerful and flexible. By default, there is no pillar data (because they are all provided by the user) but they can be looked at similarly as the grains:

salt-ssh yourhost.example.com pillar.ls
salt-ssh yourhost.example.com pillar.get foobar

Or get the values of all pillar data keys::

salt-ssh yourhost.example.com pillar.items

By default, these live in /srv/pillar.

Formula

A salt formula is not really a different type of data but important enough to be part of the Terminology section regardless.

A formula is a collection of salt states that work together to deploy a complex configuration on a system. There is a collection of formulas available on Github. They are almost always written to be used together with pillar data. For example the vim formula creates a vimrc based on the provided pillar data.

The first states

Now that the most common terms are known, the first states can be deployed onto the minion. For this, we will use the vim formula to install and configure vim (because everyone likes to have a common vim configuration in their infrastructure!).

As a first step, we need to add the formula to the master. Since this is the first formula that is added, the directory where they are going to live needs to be created:

mkdir -p /srv/formulas
cd /srv/formulas
git clone https://github.com/saltstack-formulas/vim-formula.git

Then, the salt-master needs to be made aware of the new formula. Create the file /etc/salt/master.d/roots.conf with the following content:

file_roots:
  base:
    - /srv/salt
    - /srv/formulas/vim-formula

This formula could now be applied and many formulas might suit your case with their default values but in this case we want to setup the pillar for the vim formula first. For that reason we create the file /srv/pillar/vim.sls with the following content:

vim:
  managed_vimrc: true
  allow_localrc: true
  config:
    syntax: 'on'
  settings:
    number: ~
    shiftwidth: 4
    tabstop: 4
    softtabstops: 4
    incsearch: ~
    hlsearch: ~

Hint

The pillar data used by the formula can be seen in the pillar.example file in the top directory of the formula repository.


This pillar data is currently not attached to any minion. Create the file /srv/pillar/top.sls with the following content:

base:
  '*':
    - vim

The top file handles which pillar data gets attached to which minion. In this case, the vim pillar data gets attached to all minion (denoted by the ‘*’). For more information about targeting minions in the top file, you can have a look at the top file documentation.

At last, the state can be applied. If you are uncertain about what saltstack will do, you can test the state first:

salt-ssh yourhost.example.com state.apply vim test=true

Saltstack will tell you to the best of its abilities what each state is going to do. This can be not 100% exact because states can depend on other states having actually run first but it usually is a good indicator.

If you are happy with the shown changes, apply them without the test parameter to have salt-ssh actually make the changes:

salt-ssh yourhost.example.com state.apply vim

Congratulations! You made your first actual change with Saltstack!

As a reminder, here is the workflow in short to add a new formula:

  1. Download the formula to /srv/formulas
  2. Add the directory to the roots.conf file
  3. Create a file for the pillar data and attach it to the minions.
  4. Apply the state!

Highstate

What if one would like salt to remember which states apply to which minions? That is where the Highstate comes into play. Analogous to the pillar top file, there is also a state top file that you can create at /srv/salt/top.sls:

base:
  '*':
    - vim

If you execute the state.apply without any state as a parameter, then Saltstack will apply the Highstate to that minion, meaning all states that match it in the top.sls in /srv/salt. With intelligent matching, adding new minions to your infrastructure will be a lot easier because Saltstack will automatically use the correct formulas and pillar data!

Next Steps

From this point on you are equipped to add more formulas from the repository and more systems to the roster to get managed by Saltstack.
If you would like to write your own states or formulas, then have a look at the States Tutorial.
If you would like to switch from agentless to the standard master-minion architecture, follow the Install Guide.