NGINX Salt State
Configuration management with Salt State for an NGINX web proxy.
Nginx State File
To start off our Nginx configuration, we’ll create a directory in this location specific to the software we are configuring. Then create an init.sls
file within this directory to get started::
mkdir /srv/salt/nginx
nano /srv/salt/nginx/init.sls
Nginx Package and Service States
First we want to make sure that NGINX is installed on our Minion and the service is running:
nginx/init.sls
nginx:
pkg:
- installed
service.running:
- watch:
- pkg: nginx
- file: /etc/nginx/nginx.conf
- file: /etc/nginx/sites-available/default
Nginx should automatically reload when the package is updated, when the main configuration file has been changed, or when the default server block file is modified. We can tell Salt to restart the Nginx service when these conditions occur by using watch
.
Nginx Configuration File States
We now want to define the contents of the /etc/nginx/nginx.conf
file on the master server and upload it to each minion who needs it. We will later create this default configuration file in /srv/salt/nginx/files/etc/nginx
:
nginx/init.sls
nginx:
pkg:
- installed
service.running:
- watch:
- pkg: nginx
- file: /etc/nginx/nginx.conf
- file: /etc/nginx/sites-available/default
/etc/nginx/nginx.conf:
file.managed:
- source: salt://nginx/files/etc/nginx/nginx.conf
- user: root
- group: root
- mode: 640
Additionally we need to define the server block that controls how our content will be served with the /etc/nginx/sites-available/default
file. The difference here is that this file has to be a Jinja template. This means that we can pull information from each host and construct an appropriate, customized version of the file for each of our web servers:
nginx/init.sls
nginx:
pkg:
- installed
service.running:
- watch:
- pkg: nginx
- file: /etc/nginx/nginx.conf
- file: /etc/nginx/sites-available/default
/etc/nginx/nginx.conf:
file.managed:
- source: salt://nginx/files/etc/nginx/nginx.conf
- user: root
- group: root
- mode: 640
/etc/nginx/sites-available/default:
file.managed:
- source: salt://nginx/files/etc/nginx/sites-available/default.jinja
- template: jinja
- user: root
- group: root
- mode: 640
Now, we just need to create a state for our index.html
file which will be the frontpage for our site:
nginx/init.sls
nginx:
pkg:
- installed
service.running:
- watch:
- pkg: nginx
- file: /etc/nginx/nginx.conf
- file: /etc/nginx/sites-available/default
/etc/nginx/nginx.conf:
file.managed:
- source: salt://nginx/files/etc/nginx/nginx.conf
- user: root
- group: root
- mode: 640
/etc/nginx/sites-available/default:
file.managed:
- source: salt://nginx/files/etc/nginx/sites-available/default.jinja
- template: jinja
- user: root
- group: root
- mode: 640
/usr/share/nginx/html/index.html:
file.managed:
- source: salt://nginx/files/usr/share/nginx/html/index.html.jinja
- template: jinja
- user: root
- group: root
- mode: 644
Creating the Master Files
To get the default NGINX configuration files we can install it manually on our Minion using Salt:
salt ubuntuMaster pkg.install nginx
We can now configure our master to allow file transfers from Minions nano /etc/salt/master.d/local.conf
:
# Allow minions to push files to the master. This is disabled by default, for
# security purposes.
file_recv: True
Save and systemctl restart salt-master
your master. We can now grab the default versions of the files we’ll be managing:
salt ubuntuMaster cp.push /etc/nginx/nginx.conf
salt ubuntuMaster cp.push /etc/nginx/sites-available/default
salt ubuntuMaster cp.push /usr/share/nginx/html/index.html
These files should now be available on the master. The path to these files is recreated within the /var/cache/salt/master/minions/minion_id/files directory
. We can copy the directories beneath this location, which represents the file paths on the minion, to our Salt state directory:
cp -r /var/cache/salt/master/minions/ubuntuMaster/files /srv/salt/nginx
find /srv/salt/nginx -printf "%P\n"
init.sls
files
files/etc
files/etc/nginx
files/etc/nginx/sites-available
files/etc/nginx/sites-available/default
files/etc/nginx/nginx.conf
files/usr
files/usr/share
files/usr/share/nginx
files/usr/share/nginx/html
files/usr/share/nginx/html/index.html
NGINX Config
Start by creating a backup of the original configuration and adjust the conf file according to your needs:
cd /srv/salt/nginx/files/etc/nginx
cp nginx.conf nginx.conf.ori
diff nginx.conf nginx.conf.ori
NGINX Default Server
Next, let’s take a look at our default server block template. Start with making a copy of the original file and rename the file to .jinja
:
cd /srv/salt/nginx/files/etc/nginx/sites-available
cp default default.ori
mv default default.jinja
Now, we can open the template file to make some changes nano default.jinja
. We’ll then use the grains.get execution module function to grab the address associated with the selected interface and use that as the value for the addr
variable. We will add this to the very top of the file:
# Set interface to load balancer in production - change interface before using
{%- set interface = 'enp3s0' if salt['grains.get']('env') == 'dev' else 'enp3s0' -%}
{%- set addr = salt['network.interface_ip'](interface) -%}
##
# You should look at the following URL's in order to grasp a solid understanding
Next, we can edit the server block further down in the file. We can use the addr
variable we set at the top in the listen and server_name
directives. We’ve removed the IPv6 and default server portions to restrict what this block serves:
server {
listen {{ addr }}:80;
root /usr/share/nginx/html;
index index.html index.htm;
server_name {{ addr }};
location / {
try_files $uri $uri/ =404;
}
}
Save and close the file when you are finished.
NGINX Default Frontpage Template
cd /srv/salt/nginx/files/usr/share/nginx/html
cp index.html index.html.ori
mv index.html index.html.jinja
nano index.html.jinja
At the top, we’ll set another variable using Jinja. We’ll use the grains.get
execution module function to grab the minion’s hostname. We’ll store this in the host variable:
{% set host = salt['grains.get']('os-family') -%}
{% set os = salt['grains.get']('os') -%}
<!DOCTYPE html>
<html>
<head>
<title>Welcome from {{ host }}</title>
<body>
<h1>This is NGINX!</h1>
<p>{{ os }} Rocks!</p>
</body>
</html>
Testing the Nginx State File
First, we can use the state.show_sls
execution module function to view how Salt will interpret our Nginx state file:
salt ubuntuMaster state.show_sls nginx
ubuntuMaster:
----------
/etc/nginx/nginx.conf:
----------
__env__:
base
__sls__:
nginx
file:
|_
----------
source:
salt://nginx/files/etc/nginx/nginx.conf
|_
----------
user:
root
|_
----------
group:
root
|_
----------
mode:
640
- managed
|_
----------
order:
10002
/etc/nginx/sites-available/default:
----------
__env__:
base
__sls__:
nginx
file:
|_
----------
source:
salt://nginx/files/etc/nginx/sites-available/default.jinja
|_
----------
template:
jinja
|_
----------
user:
root
|_
----------
group:
root
|_
----------
mode:
640
- managed
|_
----------
order:
10003
/usr/share/nginx/html/index.html:
----------
__env__:
base
__sls__:
nginx
file:
|_
----------
source:
salt://nginx/files/usr/share/nginx/html/index.html.jinja
|_
----------
template:
jinja
|_
----------
user:
root
|_
----------
group:
root
|_
----------
mode:
644
- managed
|_
----------
order:
10004
nginx:
----------
__env__:
base
__sls__:
nginx
pkg:
- installed
|_
----------
order:
10000
service:
|_
----------
watch:
|_
----------
pkg:
nginx
|_
----------
file:
/etc/nginx/nginx.conf
|_
----------
file:
/etc/nginx/sites-available/default
- running
|_
----------
order:
10001
Next, we can do a dry-run of applying our state file. We can do this with the state.apply
function with the test=True
option:
salt ubuntuMaster state.apply nginx test=True
ubuntuMaster:
----------
ID: nginx
Function: pkg.installed
Result: True
Comment: All specified packages are already installed
Started: 11:14:33.183423
Duration: 21.944 ms
Changes:
----------
ID: /etc/nginx/nginx.conf
Function: file.managed
Result: None
Comment: The file /etc/nginx/nginx.conf is set to be changed
Note: No changes made, actual changes may
be different due to other states.
Started: 11:14:33.209030
Duration: 10.764 ms
Changes:
----------
mode:
0640
----------
ID: /etc/nginx/sites-available/default
Function: file.managed
Result: None
Comment: The file /etc/nginx/sites-available/default is set to be changed
Note: No changes made, actual changes may
be different due to other states.
Started: 11:14:33.219892
Duration: 70.677 ms
Changes:
----------
diff:
---
+++
@@ -1,4 +1,4 @@
-##
+# Set interface to load balancer in production - change interface before using##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
@@ -19,8 +19,7 @@
# Default server configuration
#
server {
- listen 80 default_server;
- listen [::]:80 default_server;
+ listen 192.168.2.110 80 default_server;
# SSL configuration
#
@@ -38,12 +37,12 @@
#
# include snippets/snakeoil.conf;
- root /var/www/html;
+ root /usr/share/nginx/html/;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
- server_name _;
+ server_name 192.168.2.110;
location / {
# First attempt to serve request as file, then
mode:
0640
----------
ID: nginx
Function: service.running
Result: None
Comment: Service is set to be started
Started: 11:14:33.330309
Duration: 12.555 ms
Changes:
----------
ID: /usr/share/nginx/html/index.html
Function: file.managed
Result: None
Comment: The file /usr/share/nginx/html/index.html is set to be changed
Note: No changes made, actual changes may
be different due to other states.
Started: 11:14:33.343135
Duration: 18.835 ms
Changes:
----------
diff:
---
+++
@@ -1,25 +1,9 @@
<!DOCTYPE html>
<html>
-<head>
-<title>Welcome to nginx!</title>
-<style>
- body {
- width: 35em;
- margin: 0 auto;
- font-family: Tahoma, Verdana, Arial, sans-serif;
- }
-</style>
-</head>
-<body>
-<h1>Welcome to nginx!</h1>
-<p>If you see this page, the nginx web server is successfully installed and
-working. Further configuration is required.</p>
-
-<p>For online documentation and support please refer to
-<a href="http://nginx.org/">nginx.org</a>.<br/>
-Commercial support is available at
-<a href="http://nginx.com/">nginx.com</a>.</p>
-
-<p><em>Thank you for using nginx.</em></p>
-</body>
+ <head>
+ <title>Welcome from </title>
+ <body>
+ <h1>This is NGINX!</h1>
+ <p>Ubuntu Rocks!</p>
+ </body>
</html>
Summary for ubuntuMaster
------------
Succeeded: 5 (unchanged=4, changed=3)
Failed: 0
------------
Total states run: 5
Total run time: 134.775 ms
If the dry-run did not reveal any problems, you can try to apply the state to all of your available web servers by typing:
salt ubuntuMaster state.apply nginx
You can check that the Page is actually running on your Minions IP address:
curl 192.168.2.110
<!DOCTYPE html>
<html>
<head>
<title>Welcome from </title>
<body>
<h1>This is NGINX!</h1>
<p>Ubuntu Rocks!</p>
</body>
</html>