SaltStack / Apache Logo

Ever since I’ve started hosting my own domains, I’ve searched for ways to automate the website provisioning.

Normally, the documentation includes the information on configuring your infrastructure based on roles. But if you have a webserver role for all your minions it doesn’t help with the individual provisioning I am aiming at.

Table of Contents

tl;dr

All the files for setting up the website provisioning with SaltStack are available on tlex/Website-Provisioning.

Planing Phase

The first rule: plan for what you need with what you have.

For this example I’ll be using the following set-up:

  • e-tel.eu hosted on srv01.so.ai with SSL and HSTS enabled
  • www.bitleader.com hosted on srv01.so.ai with SSL enabled
  • bitleader.one hosted on srv02.so.ai without SSL
  • so.ai hosted on srv03.so.ai without SSL
  • all the hostnames are unique (not the fqdns)
  • all the SSL key files are found in /etc/ssl/salt-managed/keys/website.key
  • all the SSL certificate files are found in /etc/ssl/salt-managed/certs/website.crt
  • the SSL chain file is located in /etc/ssl/salt-managed/bundle.crt
  • all the servers run either Ubuntu 14.04 or Ubuntu 16.04

Data Required

The main idea is to split the provisioning data in two main categories:

  1. Identical across servers and websites
  2. Website and/or server specific

The website and server specific data will be stored in pillars, the rest directly in the state files (in the sls files).

Salt-Master Configuration

pillar_source_merging_strategy

To be able to overwrite part of the pillars with data from other pillar files, you need to set it on recurse. See this link on information about it).

file_roots

Make sure you include a filebase folder. If you don’t, you’ll need to change the examples accordingly.

/etc/salt/master.d/local.conf:

pillar_source_merging_strategy: recurse
file_roots:
  base:
    - /srv/salt
    - /srv/salt/filebase

fileserver_backend:
  - roots

pillar_roots:
  base:
    - /srv/pillars

Pillars

pillars/top.sls

In your pillars/top.sls you should have:

base:
  '*':
    - apache

pillars/apache/init.sls

In the folder pillars/apache you create the file init.sls:

mkdir -p pillars/apache && touch pillars/apache/init.sls

In order for you to be able to load pillars with different content for the different hosts, you need to specify this in the pillars/apache/init.sls file. The common setting are the only ones that will be directly in this file.

pillars/apache/init.sls:

{% set localhost = salt['grains.get']('host') %}

include:
  - apache.{{ localhost }}

apache:
  default_host_root: /var/www
  default_host_log: /var/log/apache2
  default_host_enable_ssl: True
  default_virtual_base: /www # the website name will be appended to this
  default_virtual_log: logs # the folder will be in form /www/f.q.d.n/logs
  default_virtual_root: htdocs # the folder will be in form /www/f.q.d.n/logs
  default_virtual_tmp: tmp # the folder will be in form /www/f.q.d.n/tmp
  document_root_options: '-Indexes +FollowSymLinks -MultiViews'
  server_admin: [email protected]
  server_signature: 'off'
  server_tokens: 'Prod'
  ssl_enable_bundle: True # If True it will manage the /etc/ssl/bundle.crt file
  hsts_max_age: 31536000 # about a year
  access_log_format_ssl: '"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x "%r" %b"'
  access_log_format: combined
  access_log_merge_ssl: True

pillars/apache/{host}.sls

You’ll need to have a sls file for every host:

for i in srv01 srv02 srv03; do touch pillars/apache/${i}.sls; done

The host settings will be light. The convention used:

  • ssl will be used to enable/disable SSL
  • force_ssl will be used to redirect HTTP traffic to HTTPS (redirect 301)
  • hsts will be used to enable HSTS for the specified hsts_max_age

You can overwrite all the settings from init.sls in the host settings file (for example, hsts_max_age).

pillars/apache/srv01.sls:

apache:
  hsts_max_age: 15768000 # about half a year
  websites:
    - name: e-tel.eu
      aliases:
        - www.e-tel.eu
      ssl: True
      force_ssl: True
      hsts: True
    - name: www.bitleader.com
      aliases:
        - bitleader.com
      ssl: True

pillars/apache/srv02.sls:

apache:
  default_virtual_base: '/sites'
  websites:
    - name: bitleader.one
      aliases:
        - www.bitleader.one

pillars/apache/srv03.sls:

apache:
  websites:
    - name: so.ai
      aliases:
        - www.so.ai

States

You need to create the folder and all the files. For a better structure, the following are split into separate state files: package dependencies, states for the default website and states for the other websites.

mkdir salt/apache &&
for i in folders files packages init; do
    touch salt/apache/${i}.sls;
done

salt/top.sls

You include the Apache state in the salt/top.sls file:

base:
  '*':
  ...
  - apache
  ...

salt/apache/init.sls

The folder, package and file states will be included in this file:

salt/apache/init.sls:

include:
  - apache.packages
  - apache.default
  - apache.websites

salt/apache/packages.sls

All the package dependencies, as well as the Apache service, are monitored here. Depending on the Apache modules you need, this is also where you can enable or disable them.

You’ll need to change the package names and add a service name if you plan on using RH/CentOS!

Note! If you’re using salt < 2016.3 you need to replace apache_module.enabled with apache_module.enable and apache_module.disabled with apache_module.disable

salt/apache/packages.sls:

apache2:
  pkg.installed:
    - pkgs:
      - apache2
      - apache2-utils
  service:
    - running
    - watch.pkg:
      - pkgs:
        - apache2
    - require:
      - pkg: apache2

mod_rewrite:
  apache_module.enabled:
    - name: rewrite
    - require:
      - pkg: apache2
    - listen_in:
      - service: apache2

mpm_event:
  apache_module.disabled:
    - name: mpm_event
    - require:
      - pkg: apache2
    - listen_in:
      - service: apache2

mpm_worker:
  apache_module.disabled:
    - name: mpm_worker
    - require:
      - pkg: apache2
    - listen_in:
      - service: apache2

mpm_prefork:
  apache_module.enabled:
    - name: mpm_prefork
    - require:
      - pkg: apache2
      - apache_module: mpm_event
      - apache_module: mpm_worker
    - listen_in:
      - service: apache2

The Default Website

The last state file is salt/apache/default.sls. But before we start with it, some more conventions:

  • all the configuration files, that will be deployed on the server, are located on the Salt-Master under /srv/salt/filebase/apache/.
  • all the SSL certificates are located on the Salt-Master under /srv/salt/filebase/apache/ssl/certs/*.crt
  • all the SSL keys are located on the Salt-Master under /srv/salt/filebase/apache/ssl/keys/*.key
  • the SSL certificates are named either fqdn.crt for the default server certificate, or website.crt for the hosted virtual servers
  • the same applies for SSL keys, their form will be fqdn.key and website.key

This guide doesn’t cover generating your certificate. Information on how to do that can be found on DigitalOcean for example.

Automatic scale apache with your setup: salt/apache/default.sls

For the actual Apache configuration files also wanted to automatically make the tuning of the prefork module. Wish I could link the source of the formulas, but alas, I have lost it.

salt/apache/default.sls:

{% set fqdn = salt['grains.get']('fqdn') %} # the servers fqdn
{% set mem = salt['grains.get']('mem_total') %} # the servers total memory
{% set settings = salt['pillar.get']('apache') %} # as defined in pillars/apache/
{% set ram_base = (((mem / 1000)|round) +1)|int %}
{% set max_spare_servers = (ram_base + 1)|int %}
{% set server_limit = ( 50 + ((ram_base ** 2) * 10 ) + ((ram_base - 2)*10) )|int %}
{% set max_requests_per_child = ( 2048 + (ram_base * 256) )|int %}
include:
  - apache.packages

{{ settings.default_host_root }}:
  file.directory:
    - user: root
    - group: root
    - dir_mode: '0755'
    - makedirs: True # Like running makedir -p
    - require:
      - pkg: apache2

{{ settings.default_host_log }}:
  file.directory:
    - user: root
    - group: adm
    - dir_mode: '0750'
    - makedirs: True # Like running makedir -p
    - require:
      - pkg: apache2

/etc/apache2/mods-available/mpm_prefork.conf:
  file.managed:
    - source: salt://filebase/apache/mpm_prefork.conf
    - user: root
    - group: root
    - mode: 0644
    - template: jinja
    - listen_in:
      - service: apache2
    - defaults:
      mem: {{ mem }}
      ram_base: {{ ram_base }}
      max_spare_servers: {{ max_spare_servers }}
      server_limit: {{ server_limit }}
      max_requests_per_child: {{ max_requests_per_child }}

/etc/logrotate.d/apache2:
  file.managed:
    - source: salt://filebase/apache/logrotate # will generate the logrotate file also for the websites
    - user: root
    - group: root
    - mode: '0644'
    - require:
      - pkg: apache2
      - file: {{ settings.default_host_log }}
    - template: jinja
    - defaults:
      settings: {{ settings }}
      fqdn: {{ settings }}

/etc/apache2/sites-available/000-default.conf:
  file.managed:
    - source: salt://filebase/apache/site_available_template.conf # will also be used in salt/apache/websites.sls
    - mode: '0644'
    - user: root
    - group: root
    - template: jinja
    - listen_in:
      - service: apache2
    - require:
      - pkg: apache2
      - file: {{ settings.default_host_root }}
      - file: {{ settings.default_host_log }}
    - defaults:
      fqdn: {{ fqdn }}
      settings: {{ settings }}
      website: False

/etc/ssl/salt-managed/certs:
  file.directory:
    - user: root
    - group: root
    - dir_mode: '0755'
    - makedirs: True

/etc/ssl/salt-managed/keys:
  file.directory:
    - user: root
    - group: root
    - dir_mode: '0700'
    - require:
      - file: /etc/ssl/salt-managed/certs

{% if settings.ssl_enable_bundle %}
/etc/ssl/salt-managed/bundle.crt:
  file.managed:
    - source: salt://filebase/apache/ssl/bundle.crt
    - require:
      - file: /etc/ssl/salt-managed/certs
    - listen_in:
      - service: apache2
{% endif %}

{% if settings.default_host_enable_ssl %}
/etc/ssl/salt-managed/certs/{{ fqdn }}.crt:
  file.managed:
    - source: salt://filebase/apache/ssl/certs/{{ fqdn }}.crt
    - user: root
    - group: root
    - mode: 0644
    - listen_in:
      - service: apache2

/etc/ssl/salt-managed/keys/{{ fqdn }}.key:
  file.managed:
    - source: salt://filebase/apache/ssl/keys/{{ fqdn }}.key
    - user: root
    - group: root
    - mode: 0400
    - listen_in:
      - service: apache2
{% endif %}

salt/apache/websites.sls

All states related to a hosted website are in this file.

{% set settings = salt['pillar.get']('apache') %} # as defined in pillars/apache/
include:
  - apache.default

{% for website in settings.websites %}

{% set base = settings.default_virtual_base + '/' + website.name %}
{% set log = base + '/' + settings.default_virtual_log %}
{% set root = base + '/' + settings.default_virtual_root %}
{% set tmp = base + '/' + settings.default_virtual_tmp %}

{{ base }}:
  file.directory:
    - name: '{{ base }}'
    - user: root
    - group: root
    - mode: '0755'
    - makedirs: True # Like running mkdir -p

{{ root }}:
  file.directory:
    - name: '{{ root }}'
    - user: www-data # you could have here a custom username or uid, stored under website.uid for example
    - group: www-data
    - dir_mode: '0770'
    - recurse:
      - user
      - group

{{ tmp }}:
  file.directory:
    - name: '{{ tmp }}'
    - user: www-data
    - group: www-data
    - dir_mode: '0770'
    - require:
      - file: {{ root }}
    - recurse:
      - group

{{ log }}:
  file.directory:
    - name: '{{ log }}'
    - user: www-data # has to have with the same username as the web server
    - group: adm
    - dir_mode: '0770'
    - require:
      - file: {{ root }}

/etc/apache2/sites-available/{{ website.name }}:
  file.managed:
    - source: salt://filebase/apache/site_available_template.conf # will also be used in salt/apache/websites.sls
    - mode: '0644'
    - user: root
    - group: root
    - template: jinja
    - listen_in:
      - service: apache2
    - require:
      - pkg: apache2
    - defaults:
      fqdn: {{ website.name }}
      settings: {{ settings }}
      website: {{ website }}

/etc/apache2/sites-enabled/{{ website.name }}:
  file.symlink:
    - name: /etc/apache2/sites-enabled/{{ website.name }}
    - target: /etc/apache2/sites-available/{{ website.name }}
    - force: True
    - require:
      - file: /etc/apache2/sites-available/{{ website.name }}
    - watch_in:
      - service: apache2

{% if 'ssl' in website and website.ssl %}
/etc/ssl/salt-managed/certs/{{ website.name }}.crt:
  file.managed:
    - source: salt://filebase/apache/ssl/certs/{{ website.name }}.crt
    - user: root
    - group: root
    - mode: 0644
    - require:
      - pkg: apache2
    - listen_in:
      - service: apache2

/etc/ssl/salt-managed/keys/{{ website.name }}.key:
  file.managed:
    - source: salt://filebase/apache/ssl/keys/{{ website.name }}.key
    - user: root
    - group: root
    - mode: 0400
    - listen_in:
      - service: apache2
    - require:
      - pkg: apache2
{% endif %}

{% endfor %}

The template files

According to the sls definitions, the following files are needed:

  • salt/filebase/apache/mpm_prefork.conf
  • salt/filebase/apache/site_available_template.conf
  • salt/filebase/apache/logrotate
  • salt/filebase/apache/ssl/keys/srv01.so.ai.key
  • salt/filebase/apache/ssl/keys/srv02.so.ai.key
  • salt/filebase/apache/ssl/keys/srv03.so.ai.key
  • salt/filebase/apache/ssl/keys/e-tel.eu.key
  • salt/filebase/apache/ssl/keys/www.bitleader.com.key
  • salt/filebase/apache/ssl/keys/bitleader.one.key
  • salt/filebase/apache/ssl/keys/so.ai.key
  • salt/filebase/apache/ssl/certs/srv01.so.ai.crt
  • salt/filebase/apache/ssl/certs/srv02.so.ai.crt
  • salt/filebase/apache/ssl/certs/srv03.so.ai.crt
  • salt/filebase/apache/ssl/certs/e-tel.eu.crt
  • salt/filebase/apache/ssl/certs/www.bitleader.com.crt
  • salt/filebase/apache/ssl/certs/bitleader.one.crt
  • salt/filebase/apache/ssl/certs/so.ai.crt
  • salt/filebase/apache/ssl/certs/bundle.crt

Olny three of these files are SaltStack templates:

salt/filebase/apache/logrotate

Include the logs for the default website and all the virtual ones:

# Managed by Salt in salt/filebase/apache/logrotate
{% for website in settings.websites %}{{ settings.default_virtual_base + '/' + website.name + '/' + settings.default_virtual_log }}/*.log
{% endfor %}
{{ settings.default_host_log }}/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 644 root adm
        sharedscripts
        postrotate
                if /etc/init.d/apache2 status > /dev/null ; then
                    /etc/init.d/apache2 reload > /dev/null;
                fi;
        endscript
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then
                        run-parts /etc/logrotate.d/httpd-prerotate;
                fi;
        endscript
}

salt/filebase/apache/mpm_prefork.conf

Now to apply the settings calculated at the previous step:

salt/filebase/apache/mpm_prefork.conf:

# Managed by Salt in salt/filebase/apache/mpm_prefork.conf
<IfModule mpm_prefork_module>
        StartServers                    {{ ram_base }}
        MinSpareServers                 {{ ram_base }}
        MaxSpareServers                 {{ max_spare_servers }}
        ServerLimit                     {{ server_limit }}
        MaxClients                      {{ server_limit }}
        MaxRequestWorkers               {{ server_limit }}
        MaxConnectionsPerChild          {{ max_requests_per_child }}
        MaxRequestsPerChild             {{ max_requests_per_child }}
</IfModule>

salt/filebase/apache/site_available_template.conf

All the website provisioning variables go in this template:

# Managed by Salt in salt/filebase/apache/site_available_template.conf
#
# {% set server_name = website.name if website else fqdn %} server_name: {{ server_name }}
# {% set aliases = website.aliases if (website and ('aliases' in website) and website.aliases) else False %} aliases: {{ aliases }}
# {% set root = settings.default_virtual_base + '/' + website.name +'/' + settings.default_virtual_root if website else settings.default_host_root %} root: {{ root }}
# {% set tmp = settings.default_virtual_base + '/' + website.name +'/' + settings.default_virtual_tmp if website else False %} tmp: {{ tmp }}
# {% set log = settings.default_virtual_base + '/' + website.name +'/' + settings.default_virtual_log if website else settings.default_host_log %} log: {{ log }}
# {% set ssl = website.ssl if (website and ('ssl' in website)) else settings.default_host_enable_ssl %} ssl: {{ ssl }}
# {% set force_ssl = website.force_ssl if (website and ssl and ('force_ssl' in website)) else False %} force_ssl: {{ force_ssl }}
# {% set hsts = website.hsts if (website and ('hsts' in website) and website.hsts) else False %}

{% if not website %}# This is the default site configuration
ServerSignature {{ settings.server_signature }}
ServerTokens {{ settings.server_tokens }}
{% endif %}

<VirtualHost *:80>
        ServerAdmin {{ settings.server_admin }}
        ServerName {{ server_name }}
        {% if aliases %}
        ServerAlias{% for alias in aliases %} {{ alias }}{% endfor %}
        {% endif %}

        # Indexes + Directory Root.
        DirectoryIndex index.php index.html
        DocumentRoot {{ root }}

        <Directory {{ root }}/>
                Options {{ settings.document_root_options }}
                AllowOverride All
                Require all granted
        </Directory>

        {% if tmp %}
        <IfModule mod_php5.c>
            php_admin_value upload_tmp_dir "{{ tmp }}"
        </IfModule>
        {% endif %}

        {% if force_ssl %}
                Redirect permanent / https://{{ server_name  }}/
        {% endif %}

    # Logfiles
    ErrorLog  {{ log }}/error.log
    CustomLog {{ log }}/access.log combined

</VirtualHost>

{% if ssl %}
<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin {{ settings.server_admin }}
        ServerName {{ server_name }}:443
        ServerAlias {{ server_name }} {% if aliases %}{% for alias in aliases %} {{ alias }} {{ alias }}:443{% endfor %}{% endif %}

        # Indexes + Directory Root.
        DirectoryIndex index.php index.html
        DocumentRoot {{ root }}

        <Directory {{ root }}/>
            Options {{ settings.document_root_options }}
            AllowOverride All
            Require all granted
        </Directory>

        {% if tmp %}
        <IfModule mod_php5.c>
            php_admin_value upload_tmp_dir "{{ tmp }}"
        </IfModule>
        {% endif %}

        # Logfiles
        ErrorLog  {{ log }}/error.log
        CustomLog {{ log }}/access.log combined
        CustomLog {{ log }}/ssl-access.log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x "%r" %b"

        SSLEngine on
        SSLStrictSNIVHostCheck on
        SSLProtocol All -SSLv2 -SSLv3
        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM

        <FilesMatch ".(cgi|shtml|phtml|php)$">
                SSLOptions +StdEnvVars
        </FilesMatch>

        BrowserMatch "MSIE [2-6]"
                nokeepalive ssl-unclean-shutdown
                downgrade-1.0 force-response-1.0
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

        # once again we test, only for the inclusion in the default-ssl.conf file
        {% if hsts %}
        <IfModule mod_headers.c>
            Header always set Strict-Transport-Security "max-age={{ settings.hsts_max_age }}; includeSubDomains; preload"
        </IfModule>
        {% endif %}

        SSLCertificateFile  /etc/ssl/salt-managed/certs/{{ fqdn }}.crt
        SSLCertificateKeyFile   /etc/ssl/salt-managed/keys/{{ fqdn }}.key

        {% if settings.ssl_enable_bundle %}
        SSLCertificateChainFile /etc/ssl/salt-managed/bundle.crt
        {% endif %}

    </VirtualHost>
</IfModule>
{% endif %}

Full Website Provisioning Run

And this is how the full automated website provisioning runs, once it’s set up:

[email protected]:~$ sudo salt srv01\* state.highstate
srv01.so.ai:
----------
          ID: apache2
    Function: pkg.installed
      Result: True
     Comment: 2 targeted packages were installed/updated.
     Started: 13:56:23.792250
    Duration: 11071.197 ms
     Changes:
              ----------
              apache2:
                  ----------
                  new:
                      2.4.7-1ubuntu4.9
                  old:
              apache2-api-20120211:
                  ----------
                  new:
                      1
                  old:
              apache2-bin:
                  ----------
                  new:
                      2.4.7-1ubuntu4.9
                  old:
              apache2-data:
                  ----------
                  new:
                      2.4.7-1ubuntu4.9
                  old:
              apache2-utils:
                  ----------
                  new:
                      2.4.7-1ubuntu4.9
                  old:
              httpd:
                  ----------
                  new:
                      1
                  old:
              httpd-cgi:
                  ----------
                  new:
                      1
                  old:
              libapr1:
                  ----------
                  new:
                      1.5.0-1
                  old:
              libaprutil1:
                  ----------
                  new:
                      1.5.3-1
                  old:
              libaprutil1-dbd-sqlite3:
                  ----------
                  new:
                      1.5.3-1
                  old:
              libaprutil1-ldap:
                  ----------
                  new:
                      1.5.3-1
                  old:
----------
          ID: /etc/ssl/salt-managed/certs
    Function: file.directory
      Result: True
     Comment: Directory /etc/ssl/salt-managed/certs updated
     Started: 13:56:35.626166
    Duration: 2.995 ms
     Changes:
              ----------
              /etc/ssl/salt-managed/certs:
                  New Dir
----------
          ID: /etc/ssl/salt-managed/certs/www.bitleader.com.crt
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/certs/www.bitleader.com.crt updated
     Started: 13:56:35.632002
    Duration: 106.534 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: mpm_event
    Function: apache_module.disabled
      Result: True
     Comment:
     Started: 13:56:35.745560
    Duration: 48.88 ms
     Changes:
              ----------
              new:
                  None
              old:
                  mpm_event
----------
          ID: mpm_prefork
    Function: apache_module.enabled
      Result: True
     Comment:
     Started: 13:56:35.800219
    Duration: 53.127 ms
     Changes:
              ----------
              new:
                  mpm_prefork
              old:
                  None
----------
          ID: /www/e-tel.eu
    Function: file.directory
      Result: True
     Comment: Directory /www/e-tel.eu updated
     Started: 13:56:35.865182
    Duration: 2.707 ms
     Changes:
              ----------
              /www/e-tel.eu:
                  New Dir
----------
          ID: /www/e-tel.eu/htdocs
    Function: file.directory
      Result: True
     Comment: Directory /www/e-tel.eu/htdocs updated
     Started: 13:56:35.870584
    Duration: 2.356 ms
     Changes:
              ----------
              /www/e-tel.eu/htdocs:
                  New Dir
----------
          ID: /www/e-tel.eu/logs
    Function: file.directory
      Result: True
     Comment: Directory /www/e-tel.eu/logs updated
     Started: 13:56:35.875569
    Duration: 2.111 ms
     Changes:
              ----------
              /www/e-tel.eu/logs:
                  New Dir
----------
          ID: /www/e-tel.eu/tmp
    Function: file.directory
      Result: True
     Comment: Directory /www/e-tel.eu/tmp updated
     Started: 13:56:35.880327
    Duration: 2.201 ms
     Changes:
              ----------
              /www/e-tel.eu/tmp:
                  New Dir
----------
          ID: /etc/apache2/sites-available/e-tel.eu.conf
    Function: file.managed
      Result: True
     Comment: File /etc/apache2/sites-available/e-tel.eu.conf updated
     Started: 13:56:35.885600
    Duration: 201.94 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: /etc/apache2/sites-available/000-default.conf
    Function: file.managed
      Result: True
     Comment: File /etc/apache2/sites-available/000-default.conf updated
     Started: 13:56:36.114058
    Duration: 163.635 ms
     Changes:
              ----------
              diff:
                  ---
                  +++
                  @@ -1,31 +1,92 @@
                  +# Managed by Salt in salt/filebase/apache/site_available_template.conf
                  +#
                  +#  server_name: srv01.so.ai
                  +#  aliases: False
                  +#  root: /var/www
                  +#  tmp: False
                  +#  log: /var/log/apache2
                  +#  ssl: True
                  +#  force_ssl: False
                  +#  hsts: False
                  +
                  +# This is the default site configuration
                  +ServerSignature off
                  +ServerTokens Prod
                  +
                  +
                   <VirtualHost *:80>
                  -     # The ServerName directive sets the request scheme, hostname and port that
                  -     # the server uses to identify itself. This is used when creating
                  -     # redirection URLs. In the context of virtual hosts, the ServerName
                  -     # specifies what hostname must appear in the request's Host: header to
                  -     # match this virtual host. For the default virtual host (this file) this
                  -     # value is not decisive as it is used as a last resort host regardless.
                  -     # However, you must set it for any further virtual host explicitly.
                  -     #ServerName www.example.com
                  +        ServerAdmin [email protected]
                  +        ServerName srv01.so.ai
                  +
                  +
                  +        # Indexes + Directory Root.
                  +        DirectoryIndex index.php index.html
                  +        DocumentRoot /var/www
                  +
                  +        <Directory /var/www/>
                  +                Options -Indexes +FollowSymLinks -MultiViews
                  +                AllowOverride All
                  +                Require all granted
                  +        </Directory>
                  +
                  +
                  +
                  +
                  +
                  +    # Logfiles
                  +    ErrorLog  /var/log/apache2/error.log
                  +    CustomLog /var/log/apache2/access.log combined
                  +
                  +</VirtualHost>
                  +

                  -     ServerAdmin [email protected]
                  -     DocumentRoot /var/www/html
                  +<IfModule mod_ssl.c>
                  +    <VirtualHost _default_:443>
                  +        ServerAdmin [email protected]
                  +        ServerName srv01.so.ai:443
                  +        ServerAlias srv01.so.ai
                  +
                  +        # Indexes + Directory Root.
                  +        DirectoryIndex index.php index.html
                  +        DocumentRoot /var/www
                  +
                  +        <Directory /var/www/>
                  +            Options -Indexes +FollowSymLinks -MultiViews
                  +            AllowOverride All
                  +            Require all granted
                  +        </Directory>
                  +
                  +
                  +
                  +        # Logfiles
                  +        ErrorLog  /var/log/apache2/error.log
                  +        CustomLog /var/log/apache2/access.log combined
                  +        CustomLog /var/log/apache2/ssl-access.log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x "%r" %b"
                  +
                  +        SSLEngine on
                  +        SSLStrictSNIVHostCheck on
                  +        SSLProtocol All -SSLv2 -SSLv3
                  +        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM
                  +
                  +        <FilesMatch ".(cgi|shtml|phtml|php)$">
                  +                SSLOptions +StdEnvVars
                  +        </FilesMatch>
                  +
                  +        BrowserMatch "MSIE [2-6]"
                  +                nokeepalive ssl-unclean-shutdown
                  +                downgrade-1.0 force-response-1.0
                  +        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
                  +
                  +        # once again we test, only for the inclusion in the default-ssl.conf file
                  +

                  -     # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
                  -     # error, crit, alert, emerg.
                  -     # It is also possible to configure the loglevel for particular
                  -     # modules, e.g.
                  -     #LogLevel info ssl:warn
                  +        SSLCertificateFile  /etc/ssl/salt-managed/certs/srv01.so.ai.crt
                  +        SSLCertificateKeyFile   /etc/ssl/salt-managed/keys/srv01.so.ai.key

                  -     ErrorLog ${APACHE_LOG_DIR}/error.log
                  -     CustomLog ${APACHE_LOG_DIR}/access.log combined
                  +
                  +        SSLCertificateChainFile /etc/ssl/salt-managed/bundle.crt
                  +
                  +
                  +    </VirtualHost>
                  +</IfModule>

                  -     # For most configuration files from conf-available/, which are
                  -     # enabled or disabled at a global level, it is possible to
                  -     # include a line for only one particular virtual host. For example the
                  -     # following line enables the CGI configuration for this host only
                  -     # after it has been globally disabled with "a2disconf".
                  -     #Include conf-available/serve-cgi-bin.conf
                  -</VirtualHost>
                  -
                  -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
----------
          ID: /etc/ssl/salt-managed/certs/e-tel.eu.crt
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/certs/e-tel.eu.crt updated
     Started: 13:56:36.280921
    Duration: 95.313 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: /etc/apache2/mods-available/mpm_prefork.conf
    Function: file.managed
      Result: True
     Comment: File /etc/apache2/mods-available/mpm_prefork.conf updated
     Started: 13:56:36.379454
    Duration: 116.343 ms
     Changes:
              ----------
              diff:
                  ---
                  +++
                  @@ -1,16 +1,11 @@
                  -# prefork MPM
                  -# StartServers: number of server processes to start
                  -# MinSpareServers: minimum number of server processes which are kept spare
                  -# MaxSpareServers: maximum number of server processes which are kept spare
                  -# MaxRequestWorkers: maximum number of server processes allowed to start
                  -# MaxConnectionsPerChild: maximum number of requests a server process serves
                  -
                  +# Managed by Salt in salt/filebase/apache/mpm_prefork.conf
                   <IfModule mpm_prefork_module>
                  -     StartServers                     5
                  -     MinSpareServers           5
                  -     MaxSpareServers          10
                  -     MaxRequestWorkers         150
                  -     MaxConnectionsPerChild   0
                  +        StartServers                    1
                  +        MinSpareServers                 1
                  +        MaxSpareServers                 2
                  +        ServerLimit                     50
                  +        MaxClients                      50
                  +        MaxRequestWorkers               50
                  +        MaxConnectionsPerChild          2304
                  +        MaxRequestsPerChild             2304
                   </IfModule>
                  -
                  -# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
----------
          ID: mod_rewrite
    Function: apache_module.enabled
        Name: rewrite
      Result: True
     Comment:
     Started: 13:56:36.498495
    Duration: 44.182 ms
     Changes:
              ----------
              new:
                  rewrite
              old:
                  None
----------
          ID: /etc/apache2/sites-available/default-ssl.conf
    Function: file.absent
      Result: True
     Comment: Removed file /etc/apache2/sites-available/default-ssl.conf
     Started: 13:56:36.545451
    Duration: 1.337 ms
     Changes:
              ----------
              removed:
                  /etc/apache2/sites-available/default-ssl.conf
----------
          ID: /etc/ssl/salt-managed/keys
    Function: file.directory
      Result: True
     Comment: Directory /etc/ssl/salt-managed/keys updated
     Started: 13:56:36.556205
    Duration: 2.27 ms
     Changes:
              ----------
              /etc/ssl/salt-managed/keys:
                  New Dir
----------
          ID: /etc/ssl/salt-managed/keys/www.bitleader.com.key
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/keys/www.bitleader.com.key updated
     Started: 13:56:36.561270
    Duration: 77.511 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0400
----------
          ID: /etc/ssl/salt-managed/keys/e-tel.eu.key
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/keys/e-tel.eu.key updated
     Started: 13:56:36.641737
    Duration: 80.016 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0400
----------
          ID: /etc/ssl/salt-managed/bundle.crt
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/bundle.crt updated
     Started: 13:56:36.724865
    Duration: 92.505 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: /www/www.bitleader.com
    Function: file.directory
      Result: True
     Comment: Directory /www/www.bitleader.com updated
     Started: 13:56:36.830795
    Duration: 2.293 ms
     Changes:
              ----------
              /www/www.bitleader.com:
                  New Dir
----------
          ID: /www/www.bitleader.com/htdocs
    Function: file.directory
      Result: True
     Comment: Directory /www/www.bitleader.com/htdocs updated
     Started: 13:56:36.835800
    Duration: 2.444 ms
     Changes:
              ----------
              /www/www.bitleader.com/htdocs:
                  New Dir
----------
          ID: /www/www.bitleader.com/logs
    Function: file.directory
      Result: True
     Comment: Directory /www/www.bitleader.com/logs updated
     Started: 13:56:36.840949
    Duration: 2.204 ms
     Changes:
              ----------
              /www/www.bitleader.com/logs:
                  New Dir
----------
          ID: /www/www.bitleader.com/tmp
    Function: file.directory
      Result: True
     Comment: Directory /www/www.bitleader.com/tmp updated
     Started: 13:56:36.845863
    Duration: 2.347 ms
     Changes:
              ----------
              /www/www.bitleader.com/tmp:
                  New Dir
----------
          ID: /etc/apache2/sites-available/www.bitleader.com.conf
    Function: file.managed
      Result: True
     Comment: File /etc/apache2/sites-available/www.bitleader.com.conf updated
     Started: 13:56:36.851368
    Duration: 170.484 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: /etc/ssl/salt-managed/certs/srv01.so.ai.crt
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/certs/srv01.so.ai.crt updated
     Started: 13:56:37.024805
    Duration: 107.543 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0644
----------
          ID: /etc/apache2/sites-enabled/www.bitleader.com.conf
    Function: file.symlink
      Result: True
     Comment: Created new symlink /etc/apache2/sites-enabled/www.bitleader.com.conf -> /etc/apache2/sites-available/www.bitleader.com.conf
     Started: 13:56:37.136412
    Duration: 3.58 ms
     Changes:
              ----------
              new:
                  /etc/apache2/sites-enabled/www.bitleader.com.conf
----------
          ID: /etc/ssl/salt-managed/keys/srv01.so.ai.key
    Function: file.managed
      Result: True
     Comment: File /etc/ssl/salt-managed/keys/srv01.so.ai.key updated
     Started: 13:56:37.142581
    Duration: 76.257 ms
     Changes:
              ----------
              diff:
                  New file
              mode:
                  0400
----------
          ID: /etc/apache2/sites-enabled/e-tel.eu.conf
    Function: file.symlink
      Result: True
     Comment: Created new symlink /etc/apache2/sites-enabled/e-tel.eu.conf -> /etc/apache2/sites-available/e-tel.eu.conf
     Started: 13:56:37.221604
    Duration: 2.203 ms
     Changes:
              ----------
              new:
                  /etc/apache2/sites-enabled/e-tel.eu.conf
----------
          ID: apache2
    Function: service.running
      Result: True
     Comment: Service restarted
     Started: 13:56:37.272397
    Duration: 2174.69 ms
     Changes:
              ----------
              apache2:
                  True
----------
          ID: /etc/logrotate.d/apache2
    Function: file.managed
      Result: True
     Comment: File /etc/logrotate.d/apache2 updated
     Started: 13:56:39.451629
    Duration: 130.237 ms
     Changes:
              ----------
              diff:
                  ---
                  +++
                  @@ -1,20 +1,24 @@
                  +# Managed by Salt in salt/filebase/apache/logrotate
                  +/www/e-tel.eu/logs/*.log
                  +/www/www.bitleader.com/logs/*.log
                   /var/log/apache2/*.log {
                  -     weekly
                  -     missingok
                  -     rotate 52
                  -     compress
                  -     delaycompress
                  -     notifempty
                  -     create 640 root adm
                  -     sharedscripts
                  -     postrotate
                  +        weekly
                  +        missingok
                  +        rotate 52
                  +        compress
                  +        delaycompress
                  +        notifempty
                  +        create 644 root adm
                  +        sharedscripts
                  +        postrotate
                                   if /etc/init.d/apache2 status > /dev/null ; then
                                       /etc/init.d/apache2 reload > /dev/null;
                                   fi;
                  -     endscript
                  -     prerotate
                  -             if [ -d /etc/logrotate.d/httpd-prerotate ]; then
                  -                     run-parts /etc/logrotate.d/httpd-prerotate;
                  -             fi;
                  -     endscript
                  +        endscript
                  +        prerotate
                  +                if [ -d /etc/logrotate.d/httpd-prerotate ]; then
                  +                        run-parts /etc/logrotate.d/httpd-prerotate;
                  +                fi;
                  +        endscript
                   }
                  +

Summary for srv01.so.ai
-------------
Succeeded: 34 (changed=30)
Failed:     0
-------------
Total states run:     34

All the files for setting up the website provisioning with SaltStack are available on tlex/Website-Provisioning.