Merge branch 'heka'
diff --git a/README.rst b/README.rst
index a06d296..0780397 100644
--- a/README.rst
+++ b/README.rst
@@ -98,6 +98,58 @@
               max: 64
               max_requests: 4000
 
+Apache kerberos authentication:
+
+.. code-block:: yaml
+
+    parameters
+      apache:
+        server:
+          site:
+            auth:
+             engine: kerberos
+             name: "Kerberos Authentication"
+             require:
+               - "ldap-attribute memberOf='cn=somegroup,cn=groups,cn=accounts,dc=example,dc=com'"
+
+             kerberos:
+               realms:
+                 - EXAMPLE.COM
+               # Bellow is optional
+               keytab: /etc/apache2/ipa.keytab
+               service: HTTP
+               method:
+                 negotiate: true
+                 k5passwd: true
+
+             ldap:
+               url: "ldaps://idm01.example.com/dc=example,dc=com?krbPrincipalName"
+               # mech is optional
+               mech: GSSAPI
+
+Tune security settings (these are default):
+
+.. code-block:: yaml
+
+    parameters:
+      apache:
+        server:
+          # ServerTokens
+          tokens: Prod
+          # ServerSignature, can be also set per-site
+          signature: false
+          # TraceEnable, can be also set per-site
+          trace: false
+          # Deny access to .git, .svn, .hg directories
+          secure_scm: true
+          # Required for settings bellow
+          modules:
+            - headers
+          # Set X-Content-Type-Options
+          content_type_options: nosniff
+          # Set X-Frame-Options
+          frame_options: sameorigin
+
 Example pillar
 ==============
 
diff --git a/apache/files/_auth.conf b/apache/files/_auth.conf
new file mode 100644
index 0000000..82bc35e
--- /dev/null
+++ b/apache/files/_auth.conf
@@ -0,0 +1,63 @@
+{%- from "apache/map.jinja" import server with context %}
+{%- if auth.engine == 'basic' %}
+
+  AuthType Basic
+{%- if auth.htpasswd is defined %}
+  AuthUserFile {{ server.htpasswd_dir }}/{{ auth.htpasswd }}
+{%- else %}
+  AuthUserFile {{ server.htpasswd_dir }}/htpasswd
+{%- endif %}
+
+{%- elif auth.engine == 'kerberos' %}
+
+  AuthType Kerberos
+  KrbMethodNegotiate {% if auth.kerberos.get("method", {}).get("negotiate", True) %}on{% else %}off{% endif %}
+  KrbMethodK5Passwd on
+  KrbMethodK5Passwd {% if auth.kerberos.get("method", {}).get("k5passwd", True) %}on{% else %}off{% endif %}
+  KrbServiceName {{ auth.kerberos.get("service", "HTTP") }}
+  KrbAuthRealms {{ auth.kerberos.realms|join(' ') }}
+  Krb5KeyTab {{ auth.kerberos.get("keytab", "/etc/apache2/ipa.keytab") }}
+  KrbSaveCredentials on
+  #KrbConstrainedDelegation on
+
+  # Ensure X-Forwarded-User is correctly set
+  RequestHeader unset X-Forwarded-User
+  RewriteEngine On
+  RewriteCond %{LA-U:REMOTE_USER} (.+)@(.+)
+  RewriteRule .* - [E=RU:%1,NS]
+  RequestHeader set X-Forwarded-User %{RU}e
+
+{%- if auth.ldap is defined %}
+
+{%- if auth.ldap.get("mech", "basic") == "GSSAPI" %}
+  # Not supported without patching, see:
+  # https://bz.apache.org/bugzilla/show_bug.cgi?id=55178
+  AuthLDAPBindSASLMech {{ auth.ldap.get("mech", "GSSAPI") }}
+{%- if auth.ldap.interact is defined %}
+  AuthLDAPBindSASLInteract "{{ auth.ldap.interact }}"
+{%- else %}
+  AuthLDAPBindSASLInteract "/usr/bin/kinit -k -t {{ auth.kerberos.get("keytab", "/etc/apache2/ipa.keytab") }} {{ auth.kerberos.get("service", "HTTP") }}/{{ site.host.name }}"
+{%- endif %}
+{%- else %}
+  AuthLDAPBindDN "{{ auth.ldap.binddn }}
+  AuthLDAPBindPassword "{{ auth.ldap.password }}
+{%- endif %}
+
+  AuthLDAPURL "{{ auth.ldap.url }}"
+{%- endif %}
+
+{%- endif %}
+
+{%- if auth.engine == "none" %}
+  AuthType None
+{%- else %}
+  AuthName "{{ auth.get("name", "Authentication required") }}"
+{%- endif %}
+
+{%- if auth.require is defined %}
+{%- for require in auth.require %}
+  Require {{ require }}
+{%- endfor %}
+{%- else %}
+  Require valid-user
+{%- endif %}
diff --git a/apache/files/_locations.conf b/apache/files/_locations.conf
index ebfb1e1..d9bb74d 100644
--- a/apache/files/_locations.conf
+++ b/apache/files/_locations.conf
@@ -4,7 +4,24 @@
   {%- if location.script is defined and location.script %}
   ScriptAlias {{ location.uri }} {{ location.path }}
   {%- else %}
+  {%- if location.path is defined %}
   Alias {{ location.uri }} {{ location.path }}
   {%- endif %}
+  {%- endif %}
+
+  <Location {{ location.uri }}>
+  {%- if location.auth is defined%}
+    {%- set auth = location.auth %}
+    {%- include "apache/files/_auth.conf" %}
+  {%- else %}
+    AuthType none
+    Require all granted
+  {%- endif %}
+
+  {%- if location.webdav is defined %}
+    Dav {% if location.webdav.get('enabled', True) %}on{% else %}off{% endif %}
+  {%- endif %}
+  </Location>
+
   {%- endfor %}
   {%- endif %}
diff --git a/apache/files/_name.conf b/apache/files/_name.conf
index 4f023e9..a3b208f 100644
--- a/apache/files/_name.conf
+++ b/apache/files/_name.conf
@@ -1,5 +1,8 @@
+{%- from "apache/map.jinja" import server with context -%}
   {%- if site.host.admin is defined %}
   ServerAdmin {{ site.host.admin }}
+  {%- elif server.admin is defined %}
+  ServerAdmin {{ server.admin }}
   {%- endif %}
 
   {%- if site.host is defined and site.host.name is defined %}
@@ -8,3 +11,6 @@
   {%- if site.host.aliases is defined %}
   ServerAlias {{ site.host.aliases|join(' ') }}
   {%- endif %}
+
+  ServerSignature {% if site.get('signature', server.get('signature', False)) %}On{% else %}Off{% endif %}
+  TraceEnable {% if site.get('trace', server.get('trace', False)) %}On{% else %}Off{% endif %}
diff --git a/apache/files/_ssl.conf b/apache/files/_ssl.conf
index ea7a6c4..d6d8394 100644
--- a/apache/files/_ssl.conf
+++ b/apache/files/_ssl.conf
@@ -4,7 +4,7 @@
   SSLEngine on
   SSLCertificateFile /etc/ssl/certs/{{ site.host.name }}.crt
   SSLCertificateKeyFile /etc/ssl/private/{{ site.host.name }}.key
-  SSLCertificateChainFile /etc/ssl/certs/ca-chain.crt
+  SSLCertificateChainFile /etc/ssl/certs/{{ site.host.name }}-ca-chain.crt
 
   {%- if site.ssl.get('strict_transport_security', False) %}
   Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
diff --git a/apache/files/mpm/mpm_event.conf b/apache/files/mpm/mpm_event.conf
new file mode 100644
index 0000000..e6d72af
--- /dev/null
+++ b/apache/files/mpm/mpm_event.conf
@@ -0,0 +1,21 @@
+{%- from "apache/map.jinja" import server with context -%}
+{%- set mpm = server.mpm.event -%}
+# event MPM
+# StartServers: initial number of server processes to start
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestWorkers: maximum number of worker threads
+# MaxConnectionsPerChild: maximum number of requests a server process serves
+
+<IfModule mpm_event_module>
+    StartServers            {{ mpm.servers.start }}
+    MinSpareThreads         {{ mpm.servers.spare.min }}
+    MaxSpareThreads         {{ mpm.servers.spare.max }}
+    ThreadLimit             {{ mpm.limit }}
+    ThreadsPerChild         {{ mpm.servers.threads_per_child }}
+    MaxRequestWorkers       {{ mpm.max_clients }}
+    MaxConnectionsPerChild  {{ mpm.servers.max_requests }}
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr et
diff --git a/apache/files/mpm/mpm_prefork.conf b/apache/files/mpm/mpm_prefork.conf
index 21eeea1..238cbb1 100644
--- a/apache/files/mpm/mpm_prefork.conf
+++ b/apache/files/mpm/mpm_prefork.conf
@@ -1,4 +1,5 @@
-{%- from "apache/map.jinja" import server with context %}
+{%- from "apache/map.jinja" import server with context -%}
+{%- set mpm = server.mpm.prefork -%}
 # prefork MPM
 # StartServers: number of server processes to start
 # MinSpareServers: minimum number of server processes which are kept spare
@@ -7,12 +8,12 @@
 # MaxConnectionsPerChild: maximum number of requests a server process serves
 
 <IfModule mpm_prefork_module>
-    StartServers            {{ server.mpm.prefork.servers.start }}
-    MinSpareServers         {{ server.mpm.prefork.servers.spare.min }}
-    MaxSpareServers         {{ server.mpm.prefork.servers.spare.max }}
-    MaxRequestWorkers       {{ server.mpm.prefork.max_clients }}
-    MaxConnectionsPerChild  {{ server.mpm.prefork.servers.max_requests }}
-	ServerLimit             {{ server.mpm.prefork.limit }}
+    StartServers            {{ mpm.servers.start }}
+    MinSpareServers         {{ mpm.servers.spare.min }}
+    MaxSpareServers         {{ mpm.servers.spare.max }}
+    MaxRequestWorkers       {{ mpm.max_clients }}
+    MaxConnectionsPerChild  {{ mpm.servers.max_requests }}
+    ServerLimit             {{ mpm.limit }}
 </IfModule>
 
-# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
+# vim: syntax=apache ts=4 sw=4 sts=4 sr et
diff --git a/apache/files/mpm/mpm_worker.conf b/apache/files/mpm/mpm_worker.conf
new file mode 100644
index 0000000..6b75d36
--- /dev/null
+++ b/apache/files/mpm/mpm_worker.conf
@@ -0,0 +1,23 @@
+{%- from "apache/map.jinja" import server with context -%}
+{%- set mpm = server.mpm.event -%}
+# worker MPM
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadLimit: ThreadsPerChild can be changed to this maximum value during a
+#                         graceful restart. ThreadLimit can only be changed by stopping
+#                         and starting Apache.
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestWorkers: maximum number of threads
+# MaxConnectionsPerChild: maximum number of requests a server process serves
+
+<IfModule mpm_event_module>
+    StartServers            {{ mpm.servers.start }}
+    MinSpareThreads         {{ mpm.servers.spare.min }}
+    MaxSpareThreads         {{ mpm.servers.spare.max }}
+    ThreadLimit             {{ mpm.limit }}
+    ThreadsPerChild         {{ mpm.servers.threads_per_child }}
+    MaxRequestWorkers       {{ mpm.max_clients }}
+    MaxConnectionsPerChild  {{ mpm.servers.max_requests }}
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr et
diff --git a/apache/files/ports.conf b/apache/files/ports.conf
new file mode 100644
index 0000000..8658d96
--- /dev/null
+++ b/apache/files/ports.conf
@@ -0,0 +1,24 @@
+# If you just change the port or add more ports here, you will likely also
+# have to change the VirtualHost statement in
+# /etc/apache2/sites-enabled/000-default.conf
+
+Listen 80
+
+<IfModule ssl_module>
+	Listen 443
+</IfModule>
+
+<IfModule mod_gnutls.c>
+	Listen 443
+</IfModule>
+
+{%- from "apache/map.jinja" import listen_ports with context %}
+{%- for port in listen_ports.iterkeys() %}
+
+{%- if port not in [80, 443] %}
+Listen {{ port }}
+{%- endif %}
+
+{%- endfor %}
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/apache/files/proxy.conf b/apache/files/proxy.conf
index 93daa8e..bd63a77 100644
--- a/apache/files/proxy.conf
+++ b/apache/files/proxy.conf
@@ -1,24 +1,33 @@
 {%- set site = salt['pillar.get']('apache:server:site:'+site_name) %}
 <VirtualHost *:{% if site.host.port is defined %}{{ site.host.port }}{% else %}{% if site.ssl is defined %}443{% else %}80{% endif %}{% endif %}>
-  {%- include "apache/files/_name.conf %}
-  {%- include "apache/files/_ssl.conf %}
-  {%- include "apache/files/_log.conf %}
+  {%- include "apache/files/_name.conf" %}
+  {%- include "apache/files/_ssl.conf" %}
+  {%- include "apache/files/_log.conf" %}
 
-  {%- if site.host.admin is defined %}
-  ServerAdmin {{ site.host.admin }}
-  {%- endif %}
-  ServerSignature Off
   DocumentRoot /var/www
-  ProxyPass / {{ site.proxy.protocol }}://{{ site.proxy.host }}:{{ site.proxy.port }}/
+
+  {%- if site.proxy.get('initial_pooled', True) == False %}
+  SetEnv proxy-initial-not-pooled 1
+  {%- endif %}
+  ProxyPass / {{ site.proxy.protocol }}://{{ site.proxy.host }}:{{ site.proxy.port }}/{% if site.proxy.get('nocanon', False)%} nocanon{% endif %}
+  {%- if site.proxy.preservehost is defined %}
+  ProxyPreserveHost {% if site.proxy.preservehost %}On{% else %}Off{% endif %}
+  {%- endif %}
   {%- if site.get('ssl', {'enabled': False}).get('enabled', False) %}
   RequestHeader set X-Forwarded-Proto "https"
   RequestHeader set Front-End-Https "On"
   {%- endif %}
   <Location / >
+  {%- if site.auth is defined%}
+    {%- set auth = site.auth %}
+    {%- include "apache/files/_auth.conf" %}
+  {%- endif %}
     ProxyPassReverse {{ site.proxy.protocol }}://{{ site.proxy.host }}:{{ site.proxy.port }}/
     <Limit OPTIONS PROPFIND GET REPORT MKACTIVITY PROPPATCH PUT CHECKOUT MKCOL MOVE COPY DELETE LOCK UNLOCK MERGE>
       Order Deny,Allow
       Allow from all
     </Limit>
   </Location>
+
+  {%- include "apache/files/_locations.conf" %}
 </VirtualHost>
diff --git a/apache/files/security.conf b/apache/files/security.conf
new file mode 100644
index 0000000..2437dd1
--- /dev/null
+++ b/apache/files/security.conf
@@ -0,0 +1,28 @@
+{%- from "apache/map.jinja" import server with context -%}
+ServerSignature {% if server.get('signature', False) %}On{% else %}Off{% endif %}
+TraceEnable {% if server.get('trace', False) %}On{% else %}Off{% endif %}
+ServerTokens {{ server.get('tokens', 'Prod') }}
+
+{%- if server.get('secure_scm', True) %}
+<DirectoryMatch "/\.svn">
+    Require all denied
+</DirectoryMatch>
+
+<DirectoryMatch "/\.git">
+    Require all denied
+</DirectoryMatch>
+
+<DirectoryMatch "/\.hg">
+    Require all denied
+</DirectoryMatch>
+{%- endif %}
+
+{%- if 'headers' in server.get('modules', []) %}
+{%- if server.get('content_type_options', "nosniff") %}
+Header set X-Content-Type-Options: "{{ server.get('content_type_options', 'nosniff') }}"
+{%- endif %}
+
+{%- if server.get('frame_options', "sameorigin") %}
+Header set X-Frame-Options: "{{ server.get('frame_options', 'sameorigin') }}"
+{%- endif %}
+{%- endif %}
diff --git a/apache/files/static.conf b/apache/files/static.conf
index 4e39bb8..88b48d5 100644
--- a/apache/files/static.conf
+++ b/apache/files/static.conf
@@ -15,5 +15,20 @@
     Order allow,deny
     allow from all
   </Directory>
+
+  <Location />
+  {%- if site.auth is defined%}
+    {%- set auth = site.auth %}
+    {%- include "apache/files/_auth.conf" %}
+  {%- else %}
+    AuthType none
+    Require all granted
+  {%- endif %}
+
+  {%- if site.webdav is defined %}
+    Dav {% if site.webdav.get('enabled', True) %}on{% else %}off{% endif %}
+  {%- endif %}
+  </Location>
+
   {%- include "apache/files/_locations.conf" %}
 </VirtualHost>
diff --git a/apache/map.jinja b/apache/map.jinja
index b697c8d..dde5d4f 100644
--- a/apache/map.jinja
+++ b/apache/map.jinja
@@ -7,11 +7,15 @@
         'mod_php': 'libapache2-mod-php5',
 	'mod_perl': 'libapache2-mod-perl2',
 	'mod_xsendfile': 'libapache2-mod-xsendfile',
+	'mod_auth_kerb': 'libapache2-mod-auth-kerb',
+        'htpasswd_dir': '/etc/apache2',
         'vhost_dir': '/etc/apache2/sites-available',
-        'conf_dir': '/etc/apache2/conf.d',
+        'conf_dir': '/etc/apache2/conf-available',
         'conf_ext': '.conf',
         'log_dir': '/var/log/apache2',
         'wwwdir': '/srv',
+        'service_user': 'www-data',
+        'service_group': 'www-data',
     },
     'Arch': {
         'pkgs': ['apache'],
@@ -19,29 +23,49 @@
         'mod_wsgi': 'wsgi-apache',
         'mod_php': 'php-apache',
         'vhost_dir': '/etc/httpd/conf/extra',
+        'htpasswd_dir': '/etc/httpd',
         'conf_dir': '/etc/httpd/conf',
         'conf_ext': '.conf',
         'log_dir': '/var/log/httpd',
         'wwwdir': '/srv',
+        'service_user': 'apache',
+        'service_group': 'apache',
     },
     'RedHat': {
         'pkgs': ['httpd'],
         'service': 'httpd',
         'mod_wsgi': 'mod_wsgi',
         'vhost_dir': '/etc/httpd/conf.d',
+        'htpasswd_dir': '/etc/httpd',
         'conf_dir': '/etc/httpd/conf.d',
         'conf_ext': '.conf',
         'log_dir': '/var/log/httpd',
         'www_dir': '/var/www',
+        'service_user': 'apache',
+        'service_group': 'apache',
     },
     'FreeBSD': {
         'pkgs': ['apache22'],
         'service': 'apache22',
         'mod_wsgi': 'ap22-mod_wsgi3',
         'vhost_dir': '/usr/local/etc/apache22/Includes',
+        'htpasswd_dir': '/usr/local/etc/apache22',
         'conf_dir': '/usr/local/etc/apache22/Includes',
         'conf_ext': '',
         'log_dir': '/var/log/',
         'www_dir': '/usr/local/www/apache22/',
+        'service_user': 'apache',
+        'service_group': 'apache',
     },
 }, merge=salt['pillar.get']('apache:server')) %}
+
+{%- set listen_ports = {} %}
+{%- if server.site is defined %}
+{%- for site_name, site in server.site.iteritems() %}
+
+{%- if site.host.get('port', 80) %}
+{%- set dummy=listen_ports.update({site.host.get('port', 80): None}) %}
+{%- endif %}
+
+{%- endfor %}
+{%- endif %}
diff --git a/apache/meta/sphinx.yml b/apache/meta/sphinx.yml
index 07b6f00..b7ca98a 100644
--- a/apache/meta/sphinx.yml
+++ b/apache/meta/sphinx.yml
@@ -1,5 +1,6 @@
 {%- from "apache/map.jinja" import server with context -%}
 doc:
+  description: The Apache HTTP Server Project is a collaborative software development effort aimed at creating a robust, commercial-grade, featureful, and freely-available source code implementation of an HTTP (Web) server
   name: Apache
   role:
     server:
@@ -16,4 +17,4 @@
           address: http{% if site.get('ssl', {}).get('enabled', False) %}s{% endif %}://{{ site.host.name }}:{{ site.host.get('port', '80') }}/
           protocol: http{% if site.get('ssl', {}).get('enabled', False) %}s{% endif %}
   {%- endif %}
-  {%- endfor %}
\ No newline at end of file
+  {%- endfor %}
diff --git a/apache/server/init.sls b/apache/server/init.sls
index df5ed64..46d4d4f 100644
--- a/apache/server/init.sls
+++ b/apache/server/init.sls
@@ -1,3 +1,4 @@
 include:
 - apache.server.service
-- apache.server.site
\ No newline at end of file
+- apache.server.site
+- apache.server.users
diff --git a/apache/server/service.sls b/apache/server/service.sls
deleted file mode 100644
index 44b7565..0000000
--- a/apache/server/service.sls
+++ /dev/null
@@ -1,131 +0,0 @@
-{%- from "apache/map.jinja" import server with context %}
-{%- if server.enabled %}
-
-apache_packages:
-  pkg.installed:
-  - names: {{ server.pkgs }} 
-
-{%- for module in server.modules %}
-
-{%- if module == 'passenger' %}
-
-apache_passenger_package:
-  pkg.installed:
-  - name: libapache2-mod-passenger
-  - require:
-    - pkg: apache_packages
-
-{%- endif %}
-
-{%- if module == 'php' %}
-
-apache_php_package:
-  pkg.installed:
-  - name: {{ server.mod_php }}
-  - require:
-    - pkg: apache_packages
-
-{%- set module = 'php5' %}
-
-{%- endif %}
-
-{%- if module == 'perl' %}
-
-apache_perl_package:
-  pkg.installed:
-  - name: {{ server.mod_perl }}
-  - require:
-    - pkg: apache_packages
-
-{%- endif %}
-
-{%- if module == 'wsgi' %}
-
-apache_wsgi_package:
-  pkg.installed:
-  - name: {{ server.mod_wsgi }}
-  - require:
-    - pkg: apache_packages
-
-{%- endif %}
-
-{%- if module == 'xsendfile' %}
-
-apache_xsendfile_package:
-  pkg.installed:
-  - name: {{ server.mod_xsendfile }}
-  - require:
-    - pkg: apache_packages
-
-{%- endif %}
-
-apache_{{ module }}_enable:
-  cmd.run:
-  - name: "a2enmod {{ module }}"
-  - creates: /etc/apache2/mods-enabled/{{ module }}.load
-  - require:
-    - pkg: apache_packages
-  - watch_in:
-    - service: apache_service
-
-{%- endfor %}
-
-/etc/apache2/sites-enabled/000-default.conf:
-  file.absent
-
-apache_service:
-  service.running:
-  - name: {{ server.service }}
-  - reload: true
-  - enable: true
-  - require:
-    - pkg: apache_packages
-
-{%- else %}
-
-apache_service_dead:
-  service.dead:
-  - name: {{ server.service }}
-
-apache_remove_packages:
-  pkg.purged:
-  - pkgs: {{ server.pkgs }}
-  - require:
-    - service: apache_service_dead
-
-{%- for mpm_type, mpm in server.mpm.iteritems() %}
-
-{%- if mpm.enabled %}
-
-apache_mpm_{{ mpm_type }}_enable:
-  cmd.run:
-  - name: "a2enmod mpm_{{ mpm_type }}"
-  - creates: /etc/apache2/mods-enabled/mpm_{{ mpm_type }}.load
-  - require:
-    - file: apache_mpm_{{ mpm_type }}_config
-  - watch_in:
-    - service: apache_service
-
-apache_mpm_{{ mpm_type }}_config:
-  file.managed:
-  - name /etc/apache2/mods-available/mpm_{{ mpm_type }}.conf
-  - source: salt://apache/files/mpm/mpm_{{ mpm_type }}.conf
-  - template: jinja
-  - require:
-    - pkg: apache_packages
-  - watch_in:
-    - service: apache_service
-
-{%- else %}
-
-apache_mpm_{{ mpm_type }}_disable:
-  file.absent:
-  - name: /etc/apache2/mods-enabled/mpm_{{ mpm_type }}.load
-  - watch_in:
-    - service: apache_service
-
-{%- endif %}
-
-{%- endfor %}
-
-{%- endif %}
diff --git a/apache/server/service/init.sls b/apache/server/service/init.sls
new file mode 100644
index 0000000..c7f43c1
--- /dev/null
+++ b/apache/server/service/init.sls
@@ -0,0 +1,68 @@
+{%- from "apache/map.jinja" import server with context %}
+
+include:
+- apache.server.service.modules
+- apache.server.service.mpm
+
+{%- if server.enabled %}
+
+apache_packages:
+  pkg.installed:
+  - names: {{ server.pkgs }}
+
+apache_ports_config:
+  file.managed:
+  - name: /etc/apache2/ports.conf
+  - source: salt://apache/files/ports.conf
+  - template: jinja
+  - require:
+    - pkg: apache_packages
+  - watch_in:
+    - service: apache_service
+
+apache_security_config:
+  file.managed:
+  - name: {{ server.conf_dir }}/security.conf
+  - source: salt://apache/files/security.conf
+  - template: jinja
+  - require:
+    - pkg: apache_packages
+  - watch_in:
+    - service: apache_service
+
+{%- if grains.os_family == "Debian" %}
+/etc/apache2/conf-enabled/security.conf:
+  file.symlink:
+  - target: {{ server.conf_dir }}/security.conf
+  - require:
+    - file: {{ server.conf_dir }}/security.conf
+  - watch_in:
+    - service: apache_service
+{%- endif %}
+
+/etc/apache2/sites-enabled/000-default.conf:
+  file.absent:
+    - watch_in:
+      - service: apache_service
+
+apache_service:
+  service.running:
+  - name: {{ server.service }}
+  - reload: true
+  - enable: true
+  - require:
+    - pkg: apache_packages
+
+{%- else %}
+
+apache_service_dead:
+  service.dead:
+  - name: {{ server.service }}
+
+apache_remove_packages:
+  pkg.purged:
+  - pkgs: {{ server.pkgs }}
+  - require:
+    - service: apache_service_dead
+
+{%- endif %}
diff --git a/apache/server/service/modules.sls b/apache/server/service/modules.sls
new file mode 100644
index 0000000..cee92fe
--- /dev/null
+++ b/apache/server/service/modules.sls
@@ -0,0 +1,79 @@
+{%- from "apache/map.jinja" import server with context %}
+{%- if server.enabled %}
+
+{%- for module in server.modules %}
+
+{%- if module == 'passenger' %}
+
+apache_passenger_package:
+  pkg.installed:
+  - name: libapache2-mod-passenger
+  - require:
+    - pkg: apache_packages
+
+{%- endif %}
+
+{%- if module == 'php' %}
+
+apache_php_package:
+  pkg.installed:
+  - name: {{ server.mod_php }}
+  - require:
+    - pkg: apache_packages
+
+{%- set module = 'php5' %}
+
+{%- endif %}
+
+{%- if module == 'perl' %}
+
+apache_perl_package:
+  pkg.installed:
+  - name: {{ server.mod_perl }}
+  - require:
+    - pkg: apache_packages
+
+{%- endif %}
+
+{%- if module == 'wsgi' %}
+
+apache_wsgi_package:
+  pkg.installed:
+  - name: {{ server.mod_wsgi }}
+  - require:
+    - pkg: apache_packages
+
+{%- endif %}
+
+{%- if module == 'xsendfile' %}
+
+apache_xsendfile_package:
+  pkg.installed:
+  - name: {{ server.mod_xsendfile }}
+  - require:
+    - pkg: apache_packages
+
+{%- endif %}
+
+{%- if module == 'auth_kerb' %}
+
+apache_auth_kerb_package:
+  pkg.installed:
+  - name: {{ server.mod_auth_kerb }}
+  - require:
+    - pkg: apache_packages
+
+{%- endif %}
+
+apache_{{ module }}_enable:
+  cmd.run:
+  - name: "a2enmod {{ module }}"
+  - creates: /etc/apache2/mods-enabled/{{ module }}.load
+  - require:
+    - pkg: apache_packages
+  - watch_in:
+    - service: apache_service
+
+{%- endfor %}
+
+{%- endif %}
diff --git a/apache/server/service/mpm.sls b/apache/server/service/mpm.sls
new file mode 100644
index 0000000..58a6e94
--- /dev/null
+++ b/apache/server/service/mpm.sls
@@ -0,0 +1,52 @@
+{%- from "apache/map.jinja" import server with context %}
+{%- if server.enabled %}
+
+{%- if grains.os_family == 'Debian' %}
+
+{%- for mpm_type, mpm in server.mpm.iteritems() %}
+
+{%- if mpm_type == server.get('default_mpm', 'prefork') %}
+
+apache_mpm_{{ mpm_type }}_enable:
+  cmd.run:
+  - name: "a2enmod mpm_{{ mpm_type }}"
+  - creates: /etc/apache2/mods-enabled/mpm_{{ mpm_type }}.load
+  - require:
+    - file: apache_mpm_{{ mpm_type }}_config
+    {%- for mpm_name, dummy in server.mpm.iteritems() if mpm_name != mpm_type %}
+    - file: apache_mpm_{{ mpm_name }}_disable
+    {%- endfor %}
+  - watch_in:
+    - service: apache_service
+
+apache_mpm_{{ mpm_type }}_config:
+  file.managed:
+  - name: /etc/apache2/mods-available/mpm_{{ mpm_type }}.conf
+  - source: salt://apache/files/mpm/mpm_{{ mpm_type }}.conf
+  - template: jinja
+  - require:
+    - pkg: apache_packages
+  - watch_in:
+    - service: apache_service
+
+{%- else %}
+
+apache_mpm_{{ mpm_type }}_disable:
+  file.absent:
+  - name: /etc/apache2/mods-enabled/mpm_{{ mpm_type }}.load
+  - watch_in:
+    - service: apache_service
+
+apache_mpm_{{ mpm_type }}_conf_disable:
+  file.absent:
+  - name: /etc/apache2/mods-enabled/mpm_{{ mpm_type }}.conf
+  - watch_in:
+    - service: apache_service
+
+{%- endif %}
+
+{%- endfor %}
+
+{%- endif %}
+
+{%- endif %}
diff --git a/apache/server/site.sls b/apache/server/site.sls
index cf93c5f..f7ed232 100644
--- a/apache/server/site.sls
+++ b/apache/server/site.sls
@@ -21,6 +21,26 @@
   - watch_in:
     - service: apache_service
 
+{%- if site.get('webdav', {}).get('enabled', False) %}
+{{ site.name }}_webdav_dir:
+  file.directory:
+  - name: {{ site.root }}
+  - user: {{ server.service_user }}
+  - group: {{ server.service_group }}
+  - makedirs: true
+{%- endif %}
+
+{%- for location in site.get('locations', []) %}
+{%- if location.get('webdav', {}).get('enabled', False) %}
+{{ site.name }}_webdav_{{ location.uri }}_dir:
+  file.directory:
+  - name: {{ location.path }}
+  - user: {{ server.service_user }}
+  - group: {{ server.service_group }}
+  - makedirs: true
+{%- endif %}
+{%- endfor %}
+
 {%- if site.get('ssl', {'enabled': False}).enabled %}
 
 /etc/ssl/certs/{{ site.host.name }}.crt:
@@ -43,7 +63,7 @@
   - require:
     - pkg: apache_packages
 
-/etc/ssl/certs/ca-chain.crt:
+/etc/ssl/certs/{{ site.host.name }}-ca-chain.crt:
   file.managed:
   {%- if site.ssl.chain is defined %}
   - contents_pillar: apache:server:site:{{ site_name }}:ssl:chain
diff --git a/apache/server/users.sls b/apache/server/users.sls
new file mode 100644
index 0000000..20bc3a2
--- /dev/null
+++ b/apache/server/users.sls
@@ -0,0 +1,39 @@
+{%- from "apache/map.jinja" import server with context %}
+{%- if server.enabled %}
+
+{%- for user_name, user in server.get('user', {}).iteritems() %}
+{%- if user.enabled %}
+
+apache_setup_user_{{ user_name }}:
+  webutil.user_exists:
+  - name: {{ user_name }}
+  {%- if user.htpasswd is defined %}
+  - htpasswd_file: {{ server.htpasswd_dir }}/{{ user.htpasswd }}
+  {%- else %}
+  - htpasswd_file: {{ server.htpasswd_dir }}/htpasswd
+  {%- endif %}
+  - password: {{ user.password }}
+  {%- if user.opts is defined %}
+  - options: '{{ user.opts }}'
+  {%- endif %}
+  - require:
+    - pkg: apache_packages
+
+{%- else %}
+
+apache_setup_user_{{ user_name }}_absent:
+  module.run:
+  - name: htpasswd.userdel
+  - user: {{ user_name }}
+  {%- if user.htpasswd is defined %}
+  - pwfile: /etc/apache/{{ user.htpasswd }}
+  {%- else %}
+  - pwfile: {{ server.htpasswd_dir }}/htpasswd
+  {%- endif %}
+  - require:
+    - pkg: apache_packages
+
+{%- endif %}
+{%- endfor %}
+
+{%- endif %}
diff --git a/metadata/service/server/single.yml b/metadata/service/server/single.yml
index 304285e..a80124b 100644
--- a/metadata/service/server/single.yml
+++ b/metadata/service/server/single.yml
@@ -15,9 +15,9 @@
       modules:
       - ssl
       - rewrite
+      default_mpm: prefork
       mpm:
         prefork:
-          enabled: true
           servers:
             start: 5
             spare:
@@ -30,6 +30,26 @@
           # Should be same or more than max clients
           limit: ${apache:server:mpm:prefork:max_clients}
         event:
-          enabled: false
+          servers:
+            start: 5
+            spare:
+              min: 25
+              max: 75
+            threads_per_child: 25
+            # Avoid memory leakage by restarting workers every x requests
+            max_requests: 0
+          # Should be 80% of server memory / average memory usage of one worker
+          max_clients: 150
+          limit: 64
         worker:
-          enabled: false
+          servers:
+            start: 5
+            spare:
+              min: 25
+              max: 75
+            threads_per_child: 25
+            # Avoid memory leakage by restarting workers every x requests
+            max_requests: 0
+          # Should be 80% of server memory / average memory usage of one worker
+          max_clients: 150
+          limit: 64
diff --git a/tests/pillar/apache_server.sls b/tests/pillar/apache_server.sls
index 5b24819..da59713 100644
--- a/tests/pillar/apache_server.sls
+++ b/tests/pillar/apache_server.sls
@@ -4,6 +4,11 @@
     modules:
       - cgi
       - php
+    user:
+      cloudlab:
+        enabled: true
+        password: cloudlab
+        htpasswd: cloudlab.htpasswd
     site:
       roundcube:
         enabled: true
@@ -13,11 +18,32 @@
         locations:
           - uri: /admin
             path: /usr/share/postfixadmin
+            auth:
+             engine: kerberos
+             name: "Kerberos Authentication"
+             require:
+               - "ldap-attribute memberOf='cn=jenkins,cn=groups,cn=accounts,dc=example,dc=eu'"
+             kerberos:
+               realms:
+                 - EXAMPLE.EU
+               keytab: /etc/apache2/ipa.keytab
+               service: HTTP
+               method:
+                 negotiate: true
+                 k5passwd: true
+             ldap:
+               url: "ldaps://idm01.example.eu/dc=example,dc=eu?krbPrincipalName"
+               mech: GSSAPI
           - uri: /mailman
             path: /usr/lib/cgi-bin/mailman
             script: true
+            auth:
+              engine: basic
+              htpasswd: cloudlab.htpasswd
           - uri: /pipermail
             path: /var/lib/mailman/archives/public
+            webdav:
+              enabled: true
           - uri: /images/mailman
             path: /usr/share/images/mailman
         host:
@@ -27,4 +53,18 @@
             - lists.example.com
             - mail01.example.com
             - mail01
-
+    default_mpm: prefork
+    mpm:
+      prefork:
+        enabled: true
+        servers:
+          start: 5
+          spare:
+            min: ${apache:server:mpm:prefork:servers:start}
+            max: 10
+          # Avoid memory leakage by restarting workers every x requests
+          max_requests: 0
+        # Should be 80% of server memory / average memory usage of one worker
+        max_clients: 150
+        # Should be same or more than max clients
+        limit: ${apache:server:mpm:prefork:max_clients}