diff --git a/docs/develop/update/apache.rst b/docs/develop/update/apache.rst index b5ef235b..24dd9bff 100644 --- a/docs/develop/update/apache.rst +++ b/docs/develop/update/apache.rst @@ -209,6 +209,18 @@ The service should now be available at its ``https://`` web address. curl https://SERVERNAME/.httpd/certificate-status +Split site logs +--------------- + +Add to your server's Pillar file: + +.. code-block:: yaml + + apache: + site_logs: True + +This will configure sites to use their own log file in ``/var/log/apache2/{site}/access.log``. + .. _apache-modules: Enable Apache modules diff --git a/pillar/cms.sls b/pillar/cms.sls index 869fe88f..efee735a 100644 --- a/pillar/cms.sls +++ b/pillar/cms.sls @@ -28,6 +28,7 @@ backup: # Sites are configured in each CMS' Pillar file. apache: public_access: True + site_logs: True # Databases and users are configured in each CMS' Pillar file. mysql: diff --git a/salt/apache/files/sites/_common.conf b/salt/apache/files/sites/_common.conf index 9c34cd37..f08517d1 100644 --- a/salt/apache/files/sites/_common.conf +++ b/salt/apache/files/sites/_common.conf @@ -24,6 +24,12 @@ {#- https://github.com/icing/mod_md#tls-alpn-challenges #} Protocols h2 http/1.1 acme-tls/1 + {#- System-wide configuration files should be prefixed with numbers #} + {%- if pillar.apache.get('site_logs') and not filename[:1].isdigit() %} + ErrorLog /var/log/apache2/{{ filename }}/error.log + CustomLog /var/log/apache2/{{ filename }}/access.log vhost_combined + {%- endif %} + Include {{ includefile }} {%- elif not servername %} diff --git a/salt/apache/init.sls b/salt/apache/init.sls index edc72ce0..378b2e9e 100644 --- a/salt/apache/init.sls +++ b/salt/apache/init.sls @@ -1,4 +1,4 @@ -{% from 'lib.sls' import apache, set_firewall, unset_firewall %} +{% from 'lib.sls' import apache, logrotate, set_firewall, unset_firewall %} {% if salt['pillar.get']('apache:public_access') %} {{ set_firewall('PUBLIC_HTTP') }} @@ -63,7 +63,7 @@ apache2-utils: # Ensure this configuration is loaded first. {{ apache('00-default', {'configuration': 'default', 'servername': ''}) }} -{{ apache('fqdn', {'configuration': 'default', 'servername': grains.fqdn}) }} +{{ apache('10-fqdn', {'configuration': 'default', 'servername': grains.fqdn}) }} {% if salt['pillar.get']('apache:modules:mod_autoindex:enabled') %} autoindex: @@ -143,3 +143,7 @@ disable-conf-other-vhosts-access-log.conf: - onchanges: - file: /etc/systemd/system/apache2.service.d/customization.conf {% endif %} + +{% if pillar.apache.get('site_logs') %} +{{ logrotate('apache-site-logs') }} +{% endif %} diff --git a/salt/core/fail2ban/files/jail.local b/salt/core/fail2ban/files/jail.local index fe0f6e08..4b3da7a3 100644 --- a/salt/core/fail2ban/files/jail.local +++ b/salt/core/fail2ban/files/jail.local @@ -13,6 +13,16 @@ logpath = /var/log/apache2/access.log maxretry = 10 findtime = 1m bantime = 1h + +{% if pillar.apache.get('site_logs') %} +[apache-custom-site-logs] +enabled = true +filter = apache-auth +port = http,https +logpath = /var/log/apache2/*/*.log +maxretry = 10 +findtime = 1m +{%- endif %} {%- endif %} {%- if salt['pillar.get']('postgres:public_access') %} diff --git a/salt/core/logrotate/files/apache-site-logs b/salt/core/logrotate/files/apache-site-logs new file mode 100644 index 00000000..6ab7f674 --- /dev/null +++ b/salt/core/logrotate/files/apache-site-logs @@ -0,0 +1,20 @@ +/var/log/apache2/*/*.log { + rotate 14 + daily + missingok + notifempty + compress + delaycompress + sharedscripts + create 644 root adm + prerotate + if [ -d /etc/logrotate.d/httpd-prerotate ]; then + run-parts /etc/logrotate.d/httpd-prerotate + fi + endscript + postrotate + if pgrep -f ^/usr/sbin/apache2 > /dev/null; then + invoke-rc.d apache2 reload 2>&1 | logger -t apache2.logrotate + fi + endscript +} diff --git a/salt/core/logrotate/init.sls b/salt/core/logrotate/init.sls index 801b8117..a223825d 100644 --- a/salt/core/logrotate/init.sls +++ b/salt/core/logrotate/init.sls @@ -1,13 +1,9 @@ +{% from 'lib.sls' import logrotate %} + # Some configurations use `postrotate /usr/lib/rsyslog/rsyslog-rotate`, so rsyslog is required. include: - core.rsyslog {% for filename, entry in salt['pillar.get']('logrotate:conf', {})|items %} -/etc/logrotate.d/{{ filename }}: - file.managed: - - source: salt://core/logrotate/files/{{ entry.source }} -{% if 'context' in entry %} - - template: jinja - - context: {{ entry.context|yaml }} -{% endif %} +{{ logrotate(filename, entry) }} {% endfor %} diff --git a/salt/lib.sls b/salt/lib.sls index fea3aef0..c5119c34 100644 --- a/salt/lib.sls +++ b/salt/lib.sls @@ -167,6 +167,7 @@ unset {{ setting_name }} in {{ filename }}: servername: {{ entry.servername }} serveraliases: {{ entry.serveraliases|default([])|yaml }} https: {{ entry.https|default(true) }} + filename: {{ name }} - require: - file: /etc/apache2/sites-available/{{ name }}.conf.include - watch_in: @@ -190,6 +191,16 @@ add .htpasswd-{{ name }}-{{ username }}: - require: - pkg: apache2 {% endfor %} + +{% if pillar.apache.get('site_logs') and not name[:1].isdigit() %} +/var/log/apache2/{{ name }}: + file.directory: + - user: root + - group: adm + - dir_mode: 755 + - require_in: + - file: /etc/apache2/sites-available/{{ name }}.conf +{% endif%} {% endmacro %} {# @@ -242,3 +253,13 @@ add .htpasswd-{{ name }}-{{ username }}: - watch_in: - module: nginx-reload {% endmacro %} + +{% macro logrotate(name, entry={}) %} +/etc/logrotate.d/{{ name }}: + file.managed: + - source: salt://core/logrotate/files/{{ entry.source|default(name) }} +{% if 'context' in entry %} + - template: jinja + - context: {{ entry.context|yaml }} +{% endif %} +{% endmacro %}