# States tutorial, part 1 - Basic Usage

The purpose of this tutorial is to demonstrate how quickly you can configure a system to be managed by Salt States. For detailed information about the state system please refer to the full states reference.

This tutorial will walk you through using Salt to configure a minion to run the Apache HTTP server and to ensure the server is running.

Before continuing make sure you have a working Salt installation by following the instructions in the Salt install guide.

Stuck?

The Salt Project community can help offer advice and help troubleshoot technical issues as you're learning about Salt. One of the best places to talk to the community is on the Salt Project Discord Community.

## Setting up the Salt State Tree

States are stored in text files on the master and transferred to the minions on demand via the master's File Server. The collection of state files make up the `State Tree`.

To start using a central state system in Salt, the Salt File Server must first be set up. Edit the master config file (`file_roots`) and uncomment the following lines:

    file_roots:
      base:
        - /srv/salt

Note

If you are deploying on FreeBSD via ports, the `file_roots` path defaults to `/usr/local/etc/salt/states`.

Restart the Salt master in order to pick up this change:

    pkill salt-master
    salt-master -d

## Preparing the Top File

On the master, in the directory uncommented in the previous step, (`/srv/salt` by default), create a new file called `top.sls` and add the following:

    base:
      '*':
        - webserver

The top file is separated into environments (discussed later). The default environment is `base`. Under the `base` environment a collection of minion matches is defined; for now simply specify all hosts (`*`).

Targeting minions

The expressions can use any of the targeting mechanisms used by Salt — minions can be matched by glob, PCRE regular expression, or by grains. For example:

    base:
      'os:Fedora':
        - match: grain
        - webserver

## Create an `sls` file

In the same directory as the top file, create a file named `webserver.sls`, containing the following:

    apache:                 # ID declaration
      pkg:                  # state declaration
        - installed         # function declaration

The first line, called the ID declaration, is an arbitrary identifier. In this case it defines the name of the package to be installed.

Note

The package name for the Apache httpd web server may differ depending on OS or distro — for example, on Fedora it is `httpd` but on Debian/Ubuntu it is `apache2`.

The second line, called the State declaration, defines which of the Salt States we are using. In this example, we are using the `pkg state` to ensure that a given package is installed.

The third line, called the Function declaration, defines which function in the `pkg state` module to call.

Renderers

States `sls` files can be written in many formats. Salt requires only a simple data structure and is not concerned with how that data structure is built. Templating languages and DSLs are a dime-a-dozen and everyone has a favorite.

Building the expected data structure is the job of Salt Renderers and they are dead-simple to write.

In this tutorial we will be using YAML in Jinja2 templates, which is the default format. The default can be changed by editing `renderer` in the master configuration file.

## Install the package

Next, let's run the state we created. Open a terminal on the master and run:

    salt '*' state.apply

Our master is instructing all targeted minions to run `state.apply`. When this function is executed without any SLS targets, a minion will download the top file and attempt to match the expressions within it. When the minion does match an expression the modules listed for it will be downloaded, compiled, and executed.

Note

This action is referred to as a "highstate", and can be run using the `state.highstate` function. However, to make the usage easier to understand ("highstate" is not necessarily an intuitive name), a `state.apply` function was added in version 2015.5.0, which when invoked without any SLS names will trigger a highstate. `state.highstate` still exists and can be used, but the documentation (as can be seen above) has been updated to reference `state.apply`, so keep the following in mind as you read the documentation:

- `state.apply` invoked without any SLS names will run `state.highstate`

- `state.apply` invoked with SLS names will run `state.sls`

Once completed, the minion will report back with a summary of all actions taken and all changes made.

Warning

If you have created custom grain modules, they will not be available in the top file until after the first highstate. To make custom grains available on a minion's first highstate, it is recommended to use this example to ensure that the custom grains are synced when the minion starts.

SLS File Namespace

Note that in the example above, the SLS file `webserver.sls` was referred to simply as `webserver`. The namespace for SLS files when referenced in `top.sls` or an Include declaration follows a few simple rules:

1. The `.sls` is discarded (i.e. `webserver.sls` becomes `webserver`).

2. Subdirectories can be used for better organization.

     1. Each subdirectory under the configured file_roots (default: `/srv/salt/`) is represented with a dot (following the Python import model) in Salt states and on the command line. `webserver/dev.sls` on the filesystem is referred to as `webserver.dev` in Salt

     2. Because slashes are represented as dots, SLS files can not contain dots in the name (other than the dot for the SLS suffix). The SLS file `webserver_1.0.sls` can not be matched, and `webserver_1.0` would match the directory/file `webserver_1/0.sls`

3. A file called `init.sls` in a subdirectory is referred to by the path of the directory. So, `webserver/init.sls` is referred to as `webserver`.

4. If both `webserver.sls` and `webserver/init.sls` happen to exist, `webserver/init.sls` will be ignored and `webserver.sls` will be the file referred to as `webserver`.

Troubleshooting Salt

If the expected output isn't seen, the following tips can help to narrow down the problem.

Turn up logging

  Salt can be quite chatty when you change the logging setting to `debug`:

      salt-minion -l debug

Run the minion in the foreground

  By not starting the minion in daemon mode (`-d`) one can view any output from the minion as it works:

      salt-minion

Increase the default timeout value when running salt. For example, to change the default timeout to 60 seconds:

    salt -t 60

For best results, combine all three:

    salt-minion -l debug        # On the minion
    salt '*' state.apply -t 60  # On the master

## Next steps

This tutorial focused on getting a simple Salt States configuration working. Part 2 will build on this example to cover more advanced `sls` syntax and will explore more of the states that ship with Salt.