Configuration management systems – H1 and H2

This report is written from my desktop and I’m reporting Assignment 1 from Tero Karvinen’s Configuration management systems-course.[1] I have to do the assignment and report it now because I’m leaving to Japan for 2.5 weeks (which makes it so that I’m going to miss the first 2 classes of the course). A close friend of mine[2] offered to help me with the given assignments since I have no earlier background using salt. Assignment started 09.10.2018 @ 17:23

What am I working with?


  • Operating system: Xubuntu-18.04.1 64b[3] (Bootable USB)
  • CPU: Intel I5-6600k @ 3.5GHz
  • GPU: Geforce GTX 1070, 8Gb VRAM
  • RAM: 2x 8Gb DDR4 @ 2667MHz
  • MoBo: Asus Maximus VIII Ranger (boot menu F8)


  • Laptop: HP ProBook 655 G1
  • CPU: AMD A10-5750M APU with Radeon(tm) HD Graphics
  • OS: Xubuntu-18.04.1 64b[3] (Bootable USB)

I started by booting my desktop and the laptop that my friend brought with him using a bootable USB-drive which had Xubuntu-18.04.1[3]inside. Both systems booted normally so all I had to do was to test was that the systems actually worked and I did this by opening the web-browser.

I then opened terminal on both computers and changed the keyboard layout to Finnish

setxkbmap fi

and updated the packages

sudo apt-get update

Now that I had all my personalized settings done; It was time to move to the given assignments.



Assignment 1C)

Install salt master and slave with pull-architecture (master being the server). Try it out by using commands remotely.[1]

I started by installing salt-master on my desktop and salt-minion on my slave computer.

Both setups were done at the same time.

Setting up the master

I installed salt-master

sudo apt-get -y install salt-master

Looked up my ip-adress for the slave computer

ip addr

After I had installed salt-minion and configured the /etc/salt/minion file on the slave computer; I checked the unaccepted keys

sudo salt-key

And accepted the keys

sudo salt-key -A
Showing keys and accepting them

Setting up the minion

I installed salt-minion

sudo apt-get -y install salt-minion

I configured the minion file from /etc/salt/

sudoedit minion

And wrote

id: robs-orja (slaves id)

Then I restarted the salt-minion service

sudo systemctl restart salt-minion.service

Seeing if it works

After configuring both systems it was time to try them out.

I ran a few simple commands

master$ sudo salt 'robs-orja' 'whoami'


  • sudo: I used salt with sudo since it didn’t work without it.
  • salt: Salt is the primary command when using salt.
  • slave-id’: Is the minion-computer that I am targeting. ‘*’ targets every minion and you can use it to target specific minions like ‘management.*’.
  • Is a salt function that runs a given command on the minion computer.
  • ‘whoami’: Is the command that i ran on the minion computer.
  • robs-orja: root: Shows the output of the command.

I also listed the directories under /home/

master$ sudo salt 'robs-orja' 'ls /home/' 

Seems to work like it should.


Assignment 1D)

Try out one state from Laine[4] and test that it works.[1]

I decided to repeat the user.sls state from Laine.[5]

I started by making a new directory /salt under /srv

cd /srv
sudo mkdir salt

Then i created a new state called user.sls

cd salt
sudo nano user.sls

The state is written in YAML

After creating the state I applied it to my minion

master$ sudo salt '*' state.apply user

And it created a user called orjatesti on my minions computer

Succesfully applied the state

I applied the state again after manually deleting the user on the minion-computer and it created the user again like it should have.


Assignment 1E)

Gather device-information from the computers using salts grain-mechanism.[1]

To gather information from the minion I used the salt function grains.items

sudo salt 'robs-orja' grains.items

and it printed out a huge list of information about the target minion. Information such as the operating system version, computer model, what CPU the computer had etc.

I figured out that you can also grep the output of grains if you only want to see certain information from the minion

sudo salt 'robs-orja' grains.items | grep python

And it printed out the following information

Grep result

(In this case I grepped everything that had to do with Python)

In my opinion grains.items is a really useful function, since you can get a lot of different kinds of information from the target minions computer in a matter of seconds. Usually finding information about computers is really bothersome and kind of hard to find.


Assignment 1F)

Configure something outside of your test environment “real life situation”.[1]

I decided to install something very important to my desktop using my VPS as the salt-master and my desktop as the salt-minion.

I started out by connecting to my VPS via ssh


then I installed salt-master and opened up the ports required

sudo apt-get -y install salt-master
sudo ufw allow 4505/tcp
sudo ufw allow 4506/tcp

And added the required directory

sudo mkdir /srv/salt

I then installed salt-minion on my desktop

sudo apt-get -y install salt-minion

After that I edited the /etc/salt/minion and added the lines

id: slave

After that I restarted my salt-minion

minion$ sudo systemctl restart salt-minion

Then i checked for unaccepted keys

master$ sudo salt-key

and accepted them

master$ sudo salt-key -A
Showing the keys above, Accepting the keys below

The one tool to rule them all

I wanted the master to make sure that I would always have cmatrix on my desktop, no matter what happens.

I started by creating a state in /srv/salt

master$ cd /srv/salt
master$ sudo nano cmatrix.sls

I applied the configuration

master$ sudo salt '*' state.apply cmatrix
Applying the state/

I the tested cmatrix

minion$ cmatrix -C cyan

And it worked like a charm

Testing cmatrix

I then wanted to try out state.highstate and my salty-tutor[2] showed me how to do it.

So I removed cmatrix from my salt-minion.

minion$ sudo apt-get remove cmatrix

I created cmatrix directory under /srv/salt

master$ sudo mkdir cmatrix

I then moved the state to the new directory and renamed it to init.sls

master$ sudo mv cmatrix.sls cmatrix/
master$ cd cmatrix/master$ sudo mv cmatrix.sls init.sls

I learned that this is the correct way to create states since they get the name from the directory they are in and you can store all the files used in the state inside the same directory. This keeps the salt directory neat and tidy.

Then I created a new state top.sls in /srv/salt

master$ cd ..
sudo nano top.sls
    - cmatrix
    - notfound

The first one I created was false just to see what happens if I apply it

sudo salt '*' state.highstate
Flawed syntax on purpose

I then corrected the state

master$ sudoedit top.sls
    - cmatrix

And tried it again

sudo salt '*' state.highstate

And I tested cmatrix again

minion$ cmatrix -C magenta

And it worked like a charm! (again)

Testing cmatrix again

Now I could use my favorite tool in Linux without having a risk of losing it.



I decided that it would be easier to make both of these assignments back to back since H2 is basically continuation from H1. H1 was technically scratching the surface of salt and H2 takes a more in-depth approach to salt, which I think will be the theme for the rest of the course.

Since I already have everything set up because of the last assignment I can just start from the first assignment.

Everything from here on out needs to be done through the usage of salts states, unless the assignment says otherwise.

Assignment 2B)

Get user directories to work with Apache.[1]

Before creating the state I went through the steps that I would take when installing Apache normally. By doing this it was easier for me to perceive what I would have to do when creating the salt state and in what order everything should be in.

  • sudo apt-get -y install apache2
    • to install apache
  • echo moi | sudo tee /var/www/html/index.html
    • to overwrite the localhost default page
  • sudo a2enmod userdir
    • to enable the user directory module to get user directories to work
    • this creates the symlink that enables the user directory module
  • mkdir public_html
    • creating the directory while under /home/xubuntu/
  • nano index.html
    • creating the index.html while under /home/xubuntu/public_html/
    • writing something inside the index.html file
  • sudo systemctl restart apache2
    • to restart the apache service

I started by creating a new directory under /srv/salt/ as the salt-master

master$ sudo mkdir apache

Then I created an init.sls state under /srv/salt/apache/ and the first step the state would have to take is to install apache I wrote the first line accordingly

master$ sudo nano init.sls

I ran the state to try it out

master$ sudo salt '*' state.apply apache

Since the state is named init.sls the state that i’m applying comes from the directory the state is located and in this case it’s in “apache”.

The state ran without errors.
I ran it again and everything succeeded but nothing changed since I already had Apache on the minion.
I then removed Apache from the minion-computer and ran the state, which installed Apache again.

Overwriting the localhost default page from /var/www/html/index.html on the target minion

I copied the index.html (that had already been overwritten with sudo tee) from /var/www/html/ to /srv/salt/apache/

master$ sudo cp /var/www/html/index.html /srv/salt/apache

Then I edited init.sls

master$ sudoedit init.sls


    - source: salt://apache/index.html

The newest line of YAML shows the path where the file I want to replace is located, what function the state is using and what I’m replacing the file with. By running this state the index.html got replaced and the localhost default page was over written instantly after the state had installed apache2.

Next up was to enable the user directory mod. Normally it’s done by using

master$ sudo a2enmod userdir

which creates a symlink (symbolic link) to the directory ../mods-enabled/ from the configuration file in ../mods-available/.
When in /etc/apache2/mods-enabled/ directory you can see what symlinks are created when you enable the module and disable it

master$ ls
master$ sudo a2dismod userdir
master$ ls
master$ sudo a2enmod userdir
master$ ls

This way you will see what modules turn up after creating the symlink and what modules disappear when you destroy the symlink

The symlinks that appeared and disappeared were userdir.conf and userdir.load

Now that you know which files get changed you can check which file the symlink targets

master$ file userdir.conf
master$ file userdir.load

and in this case the symlink is to ../mods-available/userdir.conf and ../userdir.load

The steps I took to check what happened with a2enmod and a2dismod

Now I need a way to create the symlink to both files with the state

master$ cd /srv/salt/apache/
master$ sudoedit init.sls
    - target: ../mods-available/userdir.load

    - target: ../mods-available/userdir.conf

The first one creates a symlink for ../mods-enable/userdir.load, uses file.symlink function to create it which targets ../mods-available/userdir.load. The same thing happens with the second part. This basically turns the module on (creates a symlink) through the state that I apply.

The last thing to do is to restart Apache2 this is done using the service.running function.

master$ sudoedit init.sls
    - name: apache2
    - watch:
      - file: /etc/apache2/mods-enabled/userdir.load
      - file: /etc/apache2/mods-enabled/userdir.conf
  • I named the ID as apache2restart (it can’t be apache2 since there already is a part called apache2 in this same state).
  • the function service.running (takes care that the service you have named is running).
  • name: apache2 (service name).
  • watch: (restarts the service if the files listed under “file:” are changed in any way).
  • file: These are the files that have to be changed for the “watch:” condition to trigger.

Applying the state as a whole

master$ sudo '*' state.apply apache
Running the state using salt.

init.sls ended up looking like this:


    - source: salt://apache/index.html

    - target: ../mods-available/userdir.load

    - target: ../mods-available/userdir.conf

    - name: apache2
    - watch:
      - file: /etc/apache2/mods-enabled/userdir.load
      - file: /etc/apache2/mods-enabled/userdir.conf


Assignment 2C)

Get PHP to work on the user directory sites.[1]

What needs to be done when getting php to work normally.

  • sudo apt-get -y install libapache2-mod-php
    • to install the apache2-php-mod that allows them to work together, when installing the module it creates the symlink for you.
  • you need to comment out some lines from ../mods-available/php7.2.conf
    • Specificly the lines starting from
    • commenting out is done using # in front of the lines
  • sudo systemctl restart apache2
    • restarts apache server and applies new configurations

I started by creating a new directory under /srv/salt/

master$ sudo mkdir php

and a new state under /srv/salt/php/

master$ sudo nano init.sls

    - source: salt://php/php7.2.conf

    - service: apache2
    - watch:
      - file: /etc/apache2/mods-enabled/php7.2.conf
      - file: /etc/apache2/mods-available/php7.2.conf

This is the first init.sls state I ended up creating, now for the test

master$ sudo salt '*' state.apply php


A keen eye might’ve already noticed that something was wrong in one part of the state; specifically the “– service: apache2” should’ve been “- name: apache“.

I corrected the error and added a new part to the state which creates a symlink for the ../mods-available/php7.2.conf

master$ sudoedit init.sls

    - source: salt://php/php7.2.conf

    - target: ../mods-available/php7.2.conf

    - name: apache2
    - watch:
      - file: /etc/apache2/mods-enabled/php7.2.conf
      - file: /etc/apache2/mods-available/php7.2.conf


  • libapache2-mod-php:
    • Name of the package that I want installed
  • pkg.installed:
    • Function that makes sure that the package already exists; if not it installs it.
  • /etc/apache2/mods-available/php7.2.conf
    • Name of the file I want to manage
  • file.managed:
    • Function that handles the managing, checks if the file matches the one inside “masters source.” (if not it replaces it with the one in the masters source) or if it exists at all (if not it copies one from the masters source)
  • – source: salt://php/php7.2.conf
    • Masters source: “salt://” = “/srv/salt/..”
  • file.symlink:
    • This part isn’t nescessary (because the symlink is already created when the package is installed), but it serves as a back up if the symlink is somehow destroyed.
  • phprestart:
    • ID of the restart.
  • service.running:
    • Checks if the service is running (if not, it starts it)
    • name: Which service is checked.
    • watch: If files listed below are changed restarts service.
    • files: Files that need to have an inconsistency compared to the files in masters source which trigger the “watch:” if there are any inconsistencies.

Applying the php state

master$ sudo salt '*' state.apply php
This state was tested multiple times, to see if it corrects the inconsistencies, to see if it applies the php7.2.conf from the masters source and to see if it restarts the service when things have changed in the files.


Assignment 2D)

Create a state, which makes a new name based virtual host for Apache.[1]

What I would do manually.

  • edit hosts under /etc/
  • create a new .conf under etc/apache2/sites-available/ called “”
  • use a2ensite to create the symlink for me
  • restart apache2 service

I started by editing hosts under /etc/ and added a line inside

sudoedit /etc/hosts
↓ localhost xubuntu
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

I then created a new .conf file under ../sites-available/

master$ cd /etc/apache2/sites-available/
master$ sudoedit saltwebsite.conf


	DocumentRoot /home/xubuntu/public_html/

		Require all granted
Saltywebsite.conf ended up looking like this.

I copied both of these files under /srv/salt/apache/

master$ sudo cp /etc/hosts /srv/salt/apache/
master$ sudo cp /etc/apache2/sites-available/saltwebsite.conf /srv/salt/apache/

I have to edit the init.sls that is already under /srv/salt/apache/

master$ sudoedit init.sls
    - source: salt://apache/hosts

    - source: salt://apache/saltwebsite.conf

    - target: ../sites-available/saltwebsite.conf

I wrote these parts in between the part where userdir symlink is created and the part where apache2 service is restarted.

The first part targets /etc/hosts and checks that the file is the same, if not it replaces it with the one from masters source or creates one if its missing completely.

The second part targets /etc/apache2/sites-available/saltwebsite.conf and checks that the file is the same, if not it replaces the file (saltwebsite.conf) with the one from masters source or creates a completely new one (saltwebsite.conf).

The third part creates a symlink (basically turns the settings on found in the saltwebsite.conf) that applies the configuration from /sites-available/saltwebsite.conf.

init.sls after adding the parts.


    - source: salt://apache/index.html

    - target: ../mods-available/userdir.load

    - target: ../mods-available/userdir.conf

    - source: salt://apache/hosts

    - source: salt://apache/saltwebsite.conf

    - target: ../sites-available/saltwebsite.conf 

    - name: apache2
    - watch:
      - file: /etc/apache2/mods-enabled/userdir.load
      - file: /etc/apache2/mods-enabled/userdir.conf
      - file: /etc/apache2/sites-enabled/saltwebsite.conf

I ran the state in the same fashion as before.

master$ sudo salt '*' state.apply apache

It now installed apache, added the userdir.conf from masters source created the symlink for userdir, added hosts file from masters source, added satlwebsite.conf in sites-available from masters source, created the symlink for saltwebsite.conf and restarted apache.


Assignment 2E)

Create a state that creates userdir pages for users.[1]

How I would do this manually?

  • Go to /etc/skel
    • Everything from /skel is copied to new user directories /home/”newuser”/
  • create a directory called public_html under /skel/
  • create a new file under ../skel/public_html/ called index.html (or index.php depending if you want to use php).

I wasn’t sure how to go about this, but Roope[2] told me that there is a function which can create directories. This way I wouldn’t have to even think about /etc/skel/.

I started by creating a new directory under /srv/salt/

master$ sudo mkdir skeleton

I then created a new php file under /srv/salt/skeleton/ that will later act as the masters source file

master$ sudo nano index.php
hello new user

Now to create the state

master$ sudo nano init.sls
    - makedirs: True

    - source: salt://skeleton/index.php

First part creates “public_html” directory under /etc/skel/ if one doesn’t already exist.

Second part checks if there is any changes in the index.php file under ../skel/public_html/ if there is changes, it replaces it with the one from masters source, if the file doesn’t exist at all it copies the one from the masters source.

Applying the state

master$ sudo salt '*' state.apply skeleton

Then creating a new user on the minion computer

minion$ sudo adduser "new user"

And lastly testing that the userdir page works.

The index.php printed in terminal is from the user xubuntu, not the new user.


Assignment 2F)

Different settings. Create different settings from the ones that you have already created in package-file-service style[1]

I decided that a good example would be sysstat installation, since you need to manage all three from package-file-service.

What I would do manually

  • Install sysstat
  • Edit the sysstat file from /etc/default/
  • Restart sysstat

Since this will be a completely new state I want to create a new directory under /srv/salt

master$ sudo mkdir sysstat

Then I created a new init.sls state under ../salt/sysstat and added the first part which is package installation

master$ sudo nano init.sls

Then I would have to edit the sysstat file under /etc/default/ and edit the last line that says ” ENABLED=”false” ” to ” ENABLED=”true”

# Default settings for /etc/init.d/sysstat, /etc/cron.d/sysstat
# and /etc/cron.daily/sysstat files

# Should sadc collect system activity informations? Valid values
# are "true" and "false". Please do not put other values, they
# will be overwritten by debconf!

Then I want to copy this file to /srv/salt/sysstat/ since I want it to be modified when the state is applied, or if the minion has for any reason changed the file

master$ sudo cp sysstat /srv/salt/sysstat/

After that I want to add a new part to the state

sudo nano init.sls

    - source: salt://sysstat/sysstat

The new part now check if the file exists, if it does it changes it the one from masters source, if it doesn’t it adds it from masters source
Last thing is to check if the service is alive and to restart it if something has changed in the /etc/default/sysstat file we do this by using service.running function so the init.sls state should look something this


    - source: salt://sysstat/sysstat

    - name: sysstat
    - watch:
      - file: /etc/default/sysstat

Applying the state:

master$ sudo salt '*' state.apply sysstat

This now installed sysstat, enabled it and restarted the sysstat service for its various commands to work.



This part wasn’t necessary, but I wanted to try state.highstate with all the states that I had already created so far.

I restarted the minion computer, configured the /etc/salt/minion file (masters ip and minion id: “minion name”).

Then I accepted the key from master computer and the computer was now ready to be mastered.

I started by creating top.sls under /srv/salt/

master$ sudo nano top.sls
    - apache
    - php
    - skeleton
    - sysstat

I then applied the state on the fresh minion computer

master$ sudo salt '*' state.highstate

And it did most of the things that I had learned from the Linux Servers -course[7] in approx. 65 seconds.

The state ran perfectly (except it didn’t create the php symlink, since it was already up).


So what did I learn from all this?

Writing yaml

  • Read from top to bottom
  • You have to indent it with two(2)/four(4)/six(6)/.. spaces
  • Even a small syntax error like one extra at the start of the state can break the whole thing
  • The error report doesn’t always give credible information where the error might’ve happened, it was a 50/50 in my case.

Why salt and other centralized management systems like puppet and chef are amazing.

  • Installing something like LAMP-webstack can be done in a matter of minutes.
  • Controlling multiple computers, no matter the Operating System.
  • You can also target certain minions with “*” e.g. you have 5 minions called:
    • windows-pc1
    • windows-pc2
    • windows-laptop1
    • windows-laptop2
    • linux-best
  • Applying to minions that have windows is marked like this: ‘windows*’
  • Applying to minions that have a windows laptop like: ‘windows-l*’
  • And so on.

Pull architecture and why it’s better than push.

  • We didn’t use pull architecture, but I learned the basics of how it works.
  • Ports only need to be open for master.
  • Pull basically asks the master computer for changes.
    • Only master computer/server needs to be up (compared to push which needs every minion to be connected) for the changes to go through.
    • So when minions come back online they ask for new changes in e.g. 1hr cycles.


  • Holy triangle of centralized management
  • In salt pkg.installed, file.managed and service.running


  • E.g. In apache when you enable a module, it creates a symbolic link inside the ../mods-available/ directory. And the symlink targets the file in ../mods-available/ directory and uses the configurations found in the file.


  • Means that when we e.g. apply a state, it can be applied multiple times without changing the outcome from the initial application.

sudo !!

  • The most useful thing known to man
  • had to use this command multiple times since I tended to forget to use sudo when in root directories.


All these assignments (H1 and H2) were done by trial and error instead of me copying and running the states. Roope[2] tried to go through everything with me as thoroughly as possible.

Roope had me write YAML on my own and instead of telling me what was wrong; he made me figure out the problem myself by pointing out that something was wrong.

We only used Roopes[2] and Laineens states[4] as a source when were checking the syntax or function names (and at the start to get a better understanding of YAML:s structure).

In addition we did the assignments in small parts to better understand what certain configurations do or don’t do and why.

We also analyzed errors that occurred when they happened to get a closer understanding of the common problems when using salt.

Our session was finished – 10.10.2018 @ 23:50


The states I created can also be found from my GitHub.[8]



[1] Course and its assignments:

[2] Salty-tutor:

[3] Xubuntu:

[4] Laine salt:

[5] Laine user.sls src:

[6] explaining parts of user.sls:

[7] Linux servers course:


4 thoughts on “Configuration management systems – H1 and H2”

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