While SaltStack is a great tool for running operations on many servers simultaneously, it also supports per-host defined configuration presets stored in an unique file which are further called “pillar”. In this guide, we will write a small SaltStack formula for installing Nginx and automating the deployment of virtual hosts using pillars.
Requirements
- Vultr instance running Ubuntu 17.04 ( master )
- Two Vultr instances running Ubuntu 17.04 ( minions )
Setting up master
If you’re just getting started and did not set up your SaltStack master yet, check out this article which explains how to get started with SaltStack.
Formula
We start with creating the folder for our formula which further holds the files required for SaltStack’s operations on our minions.
mkdir -p /srv/salt/nginx
After creating the folder, we can continue with writing up the init.sls
file which is an essential part of every formula:
nginx:
pkg:
- installed
/etc/nginx/sites-enabled/virtualhosts.conf:
file.managed:
- source: salt://nginx/files/virtualhosts.jinja
- template: jinja
- user: root
- group: root
- mode: 655
cmd:
- run
- names:
- service nginx restart
As you have probably noticed, SaltStack uses the Jinja templating engine for generating dynamic configuration files. This provides a broad range of possibilities within our configuration template files, such as accessing native Python code or setting variables and similar. The next step consists of creating the template for our virtualhosts.conf
file, whereas we need to create the folder first:
mkdir -p /srv/salt/nginx/files
Once the folder is created, we can continue with writing up the virtualhosts.jinja
file:
{% for vhost in pillar['vhosts'] %}
server {
listen {{ vhost['listenPort'] }};
server_name {{ vhost['serverName'] }};
root {{ vhost['documentRoot'] }};
index {%- for index in vhost['indexFiles'] -%}{{ index }}{%- endfor -%};
location / {
try_files $uri $uri/ =404;
}
}
{% endfor %}
Pillar
After creating the formula, we can go ahead and setup our Pillar base:
mkdir -p /srv/pillar/
Any references for hosts matching a particular pillar file are written into the top.sls
file within the directory we just created. In our example, we assume that two minions exist with the hostname nginxwww1
and nginxwww2
whereas we will assign them both unique pillar files:
base:
'id:nginxwww1':
- match: grain
- nginxwww1
'id:nginxwww2':
- match: grain
- nginxwww2
Next, we will continue with creating a pillar file for nginxwww1
whereas we will create a vhost listening on port 81 for the domain example.com
, the document root being /var/www/example_com/
and the index files being index.shtml
:
vhosts:
-
listenPort: '81'
serverName: 'example.com'
documentRoot: '/var/www/example_com'
indexFiles:
- index.shtml
We will continue with creating a pillar file for nginxwww2
whereas we will create a vhost listening on port 82 for the domain example2.com
, the document root being /var/www/example2_com/
and the index files being index.js
and index.css
:
vhosts:
-
listenPort: '82'
serverName: 'example2.com'
documentRoot: '/var/www/example2_com'
indexFiles:
- index.js
- index.css
Note: Pillar files are stored within /srv/pillar/
Deploying
We can now complete our first-try with pillars by updating them on our minions:
salt '*' saltutil.refresh_pillar
Afterwards, we can run the SaltStack formula:
salt '*' state.sls nginx
Confirming
Once the SaltStack formula has been run and completed without any errors, we should be able to see nginx
listening on port 81
on nginxwww1
and on port 82
on nginxwww2
as confirmation.
Conclusion
This rather lightweight but already powerful SaltStack formula can be extended further to add support for HTTPS, possibly with an integration of Let’s Encrypt, support for CGI or PHP backends and everything you can manually do as well. This guide should have given you a basic idea of SaltStack formulas and pillars used for the deployment of configuration files. Happy automating!
Want to contribute?
You could earn up to $300 by adding new articles
Suggest an update
Request an article