A personal SaltStack formula

This time I’m writing about a SaltStack formula I made for myself. Its purpose is to set up a new computer running Linux with some of the programs I use the most and with some that I consider useful. I used Git for version control and made a repository in Github. It’s publicly available, so go check it out!

This post is part of a server management course I’m attending, taught by Tero Karvinen.

Creating the modules

I started by listing the programs I wanted to include. Here’s the full list:

  • Apache2
  • SSH
  • SSHguard
  • Thunderbird
  • VLC
  • LibreOffice
  • htop
  • Teamviewer

I also wanted to further configure Apache, SSH and SSHguard. Here I’ll go through all of my state files so you can see what they do.


The top.sls file includes all the states I created and states the order they are applied in. I also added a clause that required the receiving minion machines to be running on a Linux kernel:


Match: grain means that it searches for the Linux kernel from the grains of the minions.

The top file is applied with “sudo salt ‘*’ state.highstate”.

Apache and the skel folder

With Apache my goal was to install it, enable the user directories and install PHP as well. In addition, I wanted that every new user would have their own homepage working instantly, so I utilized the skel folder and added a public_html folder in it with a index.php file, so that every newly created user would inherit the site. Here’s a look at the init.sls file I made:

1 init

Here you can see I started by stating the packages I wanted installed. If they’re not installed, the packages are downloaded and installed. The packages were for Apache and its PHP mod. Next I stated the paths to the PHP configuration files and with file.managed made it so, that if the local configuration file didn’t match the one in the salt folder, it would be replaced.

The symlink parts make it so that userdir.conf and .load are transferred to the mods-enabled folder. The configuration and load files are listed under “watch”, so if one of these is changed, Apache is restarted and the changes become effective.

Here’s a picture of my PHP configuration file which is the wanted form. I commented the last lines out as per the instructions so that PHP comes into effect in user directories.

2 conf.PNG

I also wanted to use the skel folder in relation to Apache’s user directories. I created a state file that adds a public_html folder to the skel folder and adds my index.php file inside it. This way, when a new user is created, the public_html folder is copied along with its contents to the users home folder.

3 init skel

SSH and port switch

My second installation and configuration was SSH.

4 init ssh.PNG

The first part is the same as before with Apache, it checks if openssh-server is installed and installs it if not. After this the source file I placed is transferred to /etc/ssh/ if the .conf file there doesn’t match my source file. Using Jinja, the predefined context in the source file is replaced with the value 2222:

5 conf ssh.PNG
The {{ port }} acts as the context for Jinja

SSHguard and whitelisting

To add some additional security against brute force attacks among other things, I decided to add SSHguard to my list and whitelist my own virtual server, which I typically use as a master for my minions:

6 init guard.PNG

This was a simple state file. Here the program is installed if it already isn’t and the whitelist gets replaced if it doesn’t match the source list.

7 conf guard
The source whitelist

Non-configured programs

I listed all of the programs I didn’t want to configure into one state file:

8 init installations.PNG

All the above mentioned packages are checked on the minions and installed if not found. I consider all of these quite useful but didn’t really want to configure them any further (I considered thunderbird, but since I use multiple different addresses and never put them all on one machine, I didn’t bother with the hassle).


Teamviewer is a program I frequently use so I wanted to add it to my future minions. I could have added it to the previous state but decided to put it in its own, since it isn’t listed on the Ubuntu package-list by default and I used a few commands new to myself. I ended up installing it with three terminal command using “wget” to download the .deb package, “apt install” to install the package and “rm” to remove the installation package:

9 init teamviewer.PNG
Here’s a direct link to Github: https://github.com/oliverlahti/personal/blob/master/srv/salt/teamviewer/init.sls 


Testing the modules

When I created these modules, I tested them individually multiple times so that I would save some time, since things never seem to work on the first try. This was a good idea, because the final testing on a “empty” VirtualBox machine worked flawlessly! The machine had 2GB of dedicated RAM with 10GB HDD and was running on my personal computer (CPU i7-4790K, GPU NVIDIA GTX 1080). Surprisingly, it only took a couple of minutes to install all of this. I made the virtual machine its own minion, so the application was local, but executed in a truthful environment.

1 installed
Everything was installed beautifully

Here are pictures of the test results, every program worked just as intended. The whole process want almost too well to be honest!

2 apache
Apache frontpage
3 apacheuser
The site I wrote, in a new user’s home folder
4 sshport
SSH port changed
5 sshguard
Whitelisting came through
6 installations
The programs without configurations
7 teamviewer
Teamviewer startup
8 teamvieweraction
Controlling the minion from another minion via Teamviewer

I also added a short bash script in the repository for local installations. With “sudo bash high.sh” you can apply the top file locally and don’t need a minion for execution.

EDIT: I tested this formula on multiple setups and noticed that the teamviewer state wouldn’t work on live USB systems. This doesn’t really matter to me since the whole purpose of the formula is to use it on machines with installed operating systems, but I would still like to solve the problem at some point, or at the least understand the reason for it:


User story: why did I make this formula?

The idea for these modules is to help me in the future when I’m configuring new Linux machines. I quite often buy cheap laptops from work or other places and refit them (usually just change the HDD to SSD and install Ubuntu). Sometimes I pass these machines along to relatives for example, and it’s nice to have stuff like Teamviewer or SSH already installed, when I know I’m going to act as the IT support. In short, this whole formula was created in order to save my own time and make things a little bit easier!


http://terokarvinen.com/2018/aikataulu-%E2%80%93-palvelinten-hallinta-ict4tn022-4-ti-5-ke-5-loppukevat-2018-5p – The course I’m attending

https://github.com/oliverlahti/personal – My Github repository

https://community.teamviewer.com/t5/Knowledge-Base/How-to-install-TeamViewer-on-Ubuntu/ta-p/45 – Help with Teamviewer

https://docs.saltstack.com/en/latest/contents.html – All sorts of help with SaltStack

https://www.sshguard.net/ – Refresher on SSHguard

Leave a Reply

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

WordPress.com Logo

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

Facebook photo

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

Connecting to %s