diff --git a/CHANGES.rst b/CHANGES.rst index 814c897..d5a0e55 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,7 +12,7 @@ The current role maintainer_ is ypid_. debops.apache v0.1.0 - unreleased ----------------------------------------- +--------------------------------- Added ~~~~~ @@ -20,9 +20,39 @@ Added - Initial coding and design. [ypid_] - Add/Set the default `Referrer Policy`_ to ``no-referrer`` and made it - configurable via :ref:`item.http_referrer_policy `. + configurable via :ref:`item.http_referrer_policy `. [ypid_] +- Add the :envvar:`apache__mpm_max_connections_per_child` variable to allow to + configure the number of requests a child process should handle before + terminating. [ypid_] + +- Add support to enable and configure `Apache mod_status`_. You can set + :envvar:`apache__status_enabled` to ``True`` to enable it and make the status + page accessible from localhost. [ypid_] + +- Add support for generic Apache template generation using the `Apache IfVersion directive`_. + This feature can be configured by :envvar:`apache__config_use_if_version` and + :envvar:`apache__config_min_version`. [ypid_] + +- Add Ansible tags for env roles. To only prepare the Apache role + environment, you can use the ``role::apache:env`` tag. [ypid_] + +Changed +~~~~~~~ + +- Change default virtual host server name from ``000-default`` to ``default.{{ + apache__domain }}`` to increase the chances that a valid certificate is + available for this virtual host (either wildcard or SAN) in order to avoid + the warning of Apache that the certificate is not valid for the server name. [ypid_] + +- Change :envvar:`apache__hsts_preload` from ``True`` to ``False`` by default. + Setting this value to ``True`` alone does not achieve anything and can + actually cause problems if you are not prepared. + Thus it is disabled by default. + If you are ready for the future of HTTPS and TLS only, you are encouraged to + enable it! [ypid_] + Fixed ~~~~~ @@ -31,3 +61,16 @@ Fixed Note that all dependency variables should be passed to the main ``debops.apache`` role to avoid confusion. :envvar:`apache__dependent_packages` now only works when passed to the main role. + +- Ensure that the shared object cache provider module is loaded when required + for :envvar:`apache__ocsp_stapling_cache`. Before, the ``socache_shmcb`` + module was implicitly loaded by the ``ssl`` module. [ypid_] + +- Ensure that the rewrite module is loaded when it is used by the configuration + generated by the role. [ypid_] + +- Fix ``item.https_enabled`` support for virtual hosts. This variable was + ignored previously using the global default (``True``) directly. [ypid_] + +- Fix role run with ``apache__deploy_state == "absent"`` after the role has + been run with ``present`` before. [ypid_] diff --git a/COPYRIGHT b/COPYRIGHT index 62b1d87..7f97f93 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,7 +1,7 @@ debops.apache - Manage and configure the Apache HTTP Server -Copyright (C) 2016 Robin Schneider -Copyright (C) 2016 DebOps https://debops.org/ +Copyright (C) 2016-2017 Robin Schneider +Copyright (C) 2016-2017 DebOps https://debops.org/ This Ansible role is part of DebOps. diff --git a/README.md b/README.md index ff7b7d9..494fc77 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ [![Ansible Galaxy](https://img.shields.io/badge/galaxy-debops.apache-660198.svg?style=flat)](https://galaxy.ansible.com/debops/apache) -The ``debops.apache`` role allows you to setup and mange the [Apache HTTP Server]. +The ``debops.apache`` role allows you to setup and manage the [Apache HTTP Server] +with version 2.4 and above. [Apache HTTP Server]: https://en.wikipedia.org/wiki/Apache_HTTP_Server @@ -47,4 +48,4 @@ License: [GPL-3.0](https://tldrlegal.com/license/gnu-general-public-license-v3-% *** -This role is part of the [DebOps](https://debops.org/) project. README generated by [ansigenome](https://github.com/nickjj/ansigenome/). +This role is part of [DebOps](https://debops.org/). README generated by [ansigenome](https://github.com/nickjj/ansigenome/). diff --git a/defaults/main.yml b/defaults/main.yml index 2dfccc9..d7feb4f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -47,7 +47,11 @@ apache__dependent_packages: [] # # .. code-block:: shell # -# for file in /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/000-default.conf /etc/apache2/conf-available/security.conf; do dpkg-divert --remove $file; done && rm /etc/apache2 -rf +# for file in /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/000-default.conf /etc/apache2/conf-available/security.conf +# do +# dpkg-divert --remove $file +# done +# rm /etc/apache2 -rf # apache__deploy_state: 'present' # ]]] @@ -63,6 +67,15 @@ apache__fqdn: '{{ ansible_local.core.fqdn ansible_local.core.fqdn|d()) else ansible_fqdn }}' + # ]]] +# .. envvar:: apache__domain [[[ +# +# The domain name of the host running Apache. +apache__domain: '{{ ansible_local.core.domain + if (ansible_local|d() and ansible_local.core|d() and + ansible_local.core.domain|d()) + else (ansible_domain if ansible_domain else ansible_hostname) }}' + # ]]] # .. envvar:: apache__config_path [[[ # @@ -93,7 +106,8 @@ apache__server_name: '{{ apache__fqdn }}' # # Default server admin contact information. Either a Email address or a URL # (preferable on another webserver if this one fails). -# Can be overwritten for virtual hosts. +# Refer to :ref:`item.server_admin ` for +# how to overwrite this for a virtual host. apache__server_admin: '{{ ansible_local.core.admin_public_email[0] if (ansible_local|d() and ansible_local.core|d() and ansible_local.core.admin_public_email|d()) @@ -139,6 +153,56 @@ apache__http_listen: [ 80 ] # List of transport layer ports to listen on for HTTPS connections. # Note that changing this variable is currently not supported. apache__https_listen: [ 443 ] + + # ]]] +# .. envvar:: apache__config_use_if_version [[[ +# +# Should the `Apache IfVersion directive` be used to generate a generic form +# of the Apache configuration? +# +# ``True`` +# Default. +# Use the `Apache IfVersion directive` to generate a configuration which is +# intended to work with as many Apache versions as this role supports. +# +# This has the advantage that if your Apache version does not already support +# all features which this role is able to configure then you can upgrade +# Apache independently of this role and the new features will be used in +# Apache as soon as a recent enough version of Apache starts up. +# +# Note however that it is still recommended to rerun this role against your +# host after version upgrades because if certain features are enabled might +# not only depend on the Apache version. For example the version of the used +# cryptography library (OpenSSL) is also relevant and checked by this role at +# Ansible role execution time. +# +# ``False`` +# The configuration is specifically generated for the Apache version which +# is detected at Ansible role execution time. +# +# This has the advantage that the generated configuration is potentially +# smaller and easier to read. +# +apache__config_use_if_version: True + + # ]]] +# .. envvar:: apache__config_min_version [[[ +# +# Specifies the minimum Apache version to support when +# :envvar:`apache__config_use_if_version` is set to ``True``. +# By default, this defaults to the current Apache major and minor version detected +# because ``major.minor`` version downgrades are considered uncommon and to +# avoid too much legacy directives. +# (You can still do such downgrades if the role supports the Apache version +# you are downgrading to but then you might need to rerun the role so that a +# suitable configuration can be generated.) +# +# Supported special strings: +# +# ``current_major_minor`` +# Gets replaced by the currently detected ``major.minor`` version. +# +apache__config_min_version: 'current_major_minor' # ]]] # ]]] # Filesystem access [[[ @@ -151,7 +215,7 @@ apache__https_listen: [ 443 ] # # Refer to `Apache DirectoryMatch directive documentation`_ for details. -# .. envvar:: apache__role_directory_match [[[ +# .. envvar:: apache__default_directory_match [[[ # # Default ``DirectoryMatch`` directives maintained by this Ansible role. apache__default_directory_match: @@ -253,6 +317,28 @@ apache__role_modules: enabled: '{{ True if (apache__https_listen) else False }}' 'security2': enabled: '{{ apache__security_module_enabled|bool }}' + 'status': + enabled: '{{ apache__status_enabled|bool }}' + config: | + + # Revoke default permissions granted in `/etc/apache2/mods-available/status.conf`. + Require all denied + + 'socache_shmcb': + enabled: '{{ True + if (apache__ocsp_stapling_enabled|bool + and "shmcb" in apache__ocsp_stapling_cache) + else omit }}' + 'authz_host': + enabled: '{{ True + if (apache__status_enabled|bool + and apache__status_allow_localhost) + else omit }}' + 'rewrite': + enabled: '{{ True + if (apache__register_mod_rewrite_used is defined and + apache__register_mod_rewrite_used.rc|d(1) == 0) + else omit }}' # ]]] # .. envvar:: apache__combined_modules [[[ @@ -281,6 +367,22 @@ apache__security_module_enabled: False apache__security_module_server_signature: '{{ omit }}' # ]]] # ]]] +# Multi-processing module [[[ +# --------------------------- + +# Selection of the MPM to use is leaved to Debian package maintainer scripts +# which will select a suitable MPM. +# Note that some Apache modules can depend on certain MPMs being used which +# will be configured in the package maintainer scripts of those modules. +# + +# .. envvar:: apache__mpm_max_connections_per_child [[[ +# +# Number of requests a child process will handle before terminating. +# Refer to the `Apache MaxConnectionsPerChild directive documentation`_ for details. +apache__mpm_max_connections_per_child: '0' + # ]]] + # ]]] # Configuration snippets [[[ # -------------------------- @@ -327,12 +429,13 @@ apache__role_snippets: raw: | # This file exists here to make Debian package scripts happy. # For the actual security directives enabled in server context refer to - # the `local-debops_apache` file. + # the `local-debops_apache.conf` file. # # `postinst` of the `apache2` package normally tries to enable the # `security` snippet in server context without checking if it is actually - # there. The package provided `security` snippet has been diverted to - # `package-security`. + # there. The package provided `security.conf` snippet has been diverted + # to `package-security.conf` and is not enabled to allow `debops.apache` + # to configure and change security related settings. divert_filename: 'package-security' divert_suffix: '' @@ -421,53 +524,6 @@ apache__pki_trusted_filename: '{{ ansible_local.pki.trusted else "trusted.crt" }}' # ]]] # ]]] -# OCSP Stapling [[[ -# ~~~~~~~~~~~~~~~~~ - -# .. envvar:: apache__ocsp_stapling_enabled [[[ -# -# Enable or disable OCSP Stapling. -# Refer to the `Apache SSLUseStapling directive documentation`_ for details. -apache__ocsp_stapling_enabled: True - - # ]]] -# .. envvar:: apache__ocsp_stapling_cache [[[ -# -# Cache used to store OCSP responses which get included in the TLS handshake. -# Refer to the `Apache SSLStaplingCache directive documentation`_ for details. -apache__ocsp_stapling_cache: 'shmcb:${APACHE_RUN_DIR}/ocsp_scache(512000)' - - # ]]] -# .. envvar:: apache__ocsp_stapling_response_max_age [[[ -# -# This option sets the maximum allowable age ("freshness") when considering -# OCSP responses, in seconds. -# Refer to the `Apache SSLStaplingResponseMaxAge directive documentation`_ for details. -# The default update interval of `Let's Encrypt`_ is 7 days. -# Ref: `Is there a rate limit on OCSP requests? `_ -# Enforcing 30 days as default should be a good start compared to the -# Apache default which imposes no limit. -apache__ocsp_stapling_response_max_age: '{{ 30 * 24 * 3600 }}' - - # ]]] -# .. envvar:: apache__ocsp_stapling_force_url [[[ -# -# This directive overrides the URI of an OCSP responder as obtained from the -# authorityInfoAccess (AIA) extension of the certificate. One potential use is -# when a proxy is used for retrieving OCSP queries. -# Refer to the `Apache SSLStaplingForceURL directive documentation`_ for details. -apache__ocsp_stapling_force_url: False - - # ]]] -# .. envvar:: apache__ocsp_stapling_verify [[[ -# -# Verify OCSP responses from the server which requires chained intermediate and -# Root CA certificates. -# Note: Currently not implemented. -# Ref: https://github.com/debops/ansible-apache/issues/2 -apache__ocsp_stapling_verify: '{{ apache__ocsp_stapling_enabled | bool }}' - # ]]] - # ]]] # TLS ciphers and protocol versions [[[ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -485,7 +541,6 @@ apache__tls_protocols: [ 'All', '-SSLv2', '-SSLv3' ] apache__tls_cipher_suite_set_name: 'bettercrypto_org__set_b_pfs' # ]]] - # .. envvar:: apache__tls_cipher_suite_sets [[[ # # Dictionary of TLS cipher suites which can be selected from @@ -525,7 +580,6 @@ apache__tls_honor_cipher_order: 'on' # Whether compression is enabled or disabled on the TLS level. # Refer to the `Apache SSLCompression directive documentation`_ for details. apache__tls_compression: 'off' - # ]]] # ]]] # Key exchange (Diffie–Hellman) [[[ @@ -551,6 +605,53 @@ apache__tls_dhparam_file: '{{ ansible_local.dhparam[apache__tls_dhparam_set_name else "" }}' # ]]] # ]]] +# OCSP Stapling [[[ +# ~~~~~~~~~~~~~~~~~ + +# .. envvar:: apache__ocsp_stapling_enabled [[[ +# +# Enable or disable OCSP Stapling. +# Refer to the `Apache SSLUseStapling directive documentation`_ for details. +apache__ocsp_stapling_enabled: True + + # ]]] +# .. envvar:: apache__ocsp_stapling_cache [[[ +# +# Cache used to store OCSP responses which get included in the TLS handshake. +# Refer to the `Apache SSLStaplingCache directive documentation`_ for details. +apache__ocsp_stapling_cache: 'shmcb:${APACHE_RUN_DIR}/ocsp_scache(512000)' + + # ]]] +# .. envvar:: apache__ocsp_stapling_response_max_age [[[ +# +# This option sets the maximum allowable age ("freshness") when considering +# OCSP responses, in seconds. +# Refer to the `Apache SSLStaplingResponseMaxAge directive documentation`_ for details. +# The default update interval of `Let's Encrypt`_ is 7 days. +# Ref: `Is there a rate limit on OCSP requests? `_ +# Enforcing 30 days as default should be a good start compared to the +# Apache default which imposes no limit. +apache__ocsp_stapling_response_max_age: '{{ 30 * 24 * 3600 }}' + + # ]]] +# .. envvar:: apache__ocsp_stapling_force_url [[[ +# +# This directive overrides the URI of an OCSP responder as obtained from the +# authorityInfoAccess (AIA) extension of the certificate. One potential use is +# when a proxy is used for retrieving OCSP queries. +# Refer to the `Apache SSLStaplingForceURL directive documentation`_ for details. +apache__ocsp_stapling_force_url: False + + # ]]] +# .. envvar:: apache__ocsp_stapling_verify [[[ +# +# Verify OCSP responses from the server which requires chained intermediate and +# Root CA certificates. +# Note: Currently not implemented. +# Ref: https://github.com/debops/ansible-apache/issues/2 +apache__ocsp_stapling_verify: '{{ apache__ocsp_stapling_enabled | bool }}' + # ]]] + # ]]] # HTTPS related security headers [[[ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -577,11 +678,14 @@ apache__hsts_subdomains: True # ]]] # .. envvar:: apache__hsts_preload [[[ # -# Should the preload parameter be added to the HSTS header? +# Should the ``preload`` parameter be added to the HSTS header? # Refer to the `HSTS Preload List Submission`_ page to make use of this # feature. -apache__hsts_preload: True - +# It is disabled by default because setting this to ``True`` alone does +# nothing, it is just one requirement to get included in the preloading list. +# Please feel encouraged to get to know HSTS preloading and enable it when you +# are ready! +apache__hsts_preload: False # ]]] # ]]] # ]]] @@ -603,13 +707,13 @@ apache__http_frame_options: 'SAMEORIGIN' # ]]] # .. envvar:: apache__http_xss_protection [[[ # -# Refer to :ref:`item.http_xss_protection ` for details. +# Refer to :ref:`item.http_xss_protection ` for details. apache__http_xss_protection: '1; mode=block' # ]]] # .. envvar:: apache__http_referrer_policy [[[ # -# Refer to :ref:`item.http_referrer_policy ` for details. +# Refer to :ref:`item.http_referrer_policy ` for details. apache__http_referrer_policy: 'no-referrer' # ]]] @@ -650,9 +754,18 @@ apache__vhosts: [] # Default virtual host which will receive all requests which don’t match other virtual hosts. # Refer to the `Apache virtual host matching documentation`_ for details. apache__default_vhost: - name: '000-default' + name: '{{ apache__default_vhost_name }}' + filename: '000-default' root: '/var/www/html' + # ]]] +# .. envvar:: apache__default_vhost_name [[[ +# +# Default virtual host name. +# Ideally, this a FQDN for which a valid certificate is present so that Apache +# does not complain about a certificate subject mismatch. +apache__default_vhost_name: 'default.{{ apache__domain }}' + # ]]] # .. envvar:: apache__group_vhosts [[[ # @@ -689,6 +802,7 @@ apache__role_vhosts: Divert the package provided `default-ssl` site file away, we will not need it :) - '{{ apache__default_vhost }}' + - '{{ apache__status_vhost }}' # ]]] # .. envvar:: apache__dependent_vhosts [[[ @@ -728,7 +842,6 @@ apache__vhost_allow_override: 'None' # The default ``Options`` to use for virtual hosts. # Refer to the `Apache Options directive documentation`_ for details. apache__vhost_options: [ '+FollowSymLinks' ] - # ]]] # ]]] # Logging [[[ @@ -739,6 +852,7 @@ apache__vhost_options: [ '+FollowSymLinks' ] # The default log level to use. # Refer to the `Apache LogLevel directive documentation`_ for details. apache__log_level: 'warn' + # ]]] # .. envvar:: apache__access_log_format [[[ # @@ -747,6 +861,102 @@ apache__log_level: 'warn' apache__access_log_format: 'combined' # ]]] # ]]] +# Apache Status [[[ +# ----------------- + +# Refer to the `Apache mod_status documentation`_ for details. + +# .. envvar:: apache__status_enabled [[[ +# +# Should the Apache server status be enabled by loading the required modules? +apache__status_enabled: False + + # ]]] +# .. envvar:: apache__status_vhost_enabled [[[ +# +# Should the Apache server status page be accessible using a independent +# virtual host bound to localhost? +apache__status_vhost_enabled: '{{ apache__status_enabled }}' + + # ]]] +# .. envvar:: apache__status_for_vhost_enabled [[[ +# +# Should the Apache server status page be enabled in all virtual hosts? +# +# Note that even when this option evaluates to ``False``, the hardcoded +# ``/server-status`` URL path is not fully neutralized. That is because the `Apache +# SetHandler directive`_ is set by the Apache Debian package in server config +# context. All access granted by package defaults is of course revoked by this +# Ansible role, again in server config context. But this means that for any +# virtual host, a request against ``/server-status`` (regardless of the value +# of :envvar:`apache__status_location`) will be answered with a 403 Forbidden. +# If that causes a problem, the role could be changed to not enable the default +# module configuration and load the module directly from server config context. +# Or maybe someone has a workaround which does not involve changing the package +# module defaults. +# +# Refer to :ref:`item.status_enabled ` for +# how to overwrite this for a virtual host. +apache__status_for_vhost_enabled: False + + # ]]] +# .. envvar:: apache__status_location [[[ +# +# The ``Location`` or URL path by which the Apache server status should be +# accessible. +# Refer to :ref:`item.status_location ` for +# how to overwrite this for a virtual host. +apache__status_location: '/server-status' + + # ]]] +# .. envvar:: apache__status_allow_localhost [[[ +# +# Allow access to the Apache server status using the ``Require local`` +# directive (refer to the `Apache host Require directive documentation`_). +# Refer to :ref:`item.status_allow_localhost ` for +# how to overwrite this for a virtual host. +apache__status_allow_localhost: False + + # ]]] +# .. envvar:: apache__status_directives [[[ +# +# Additional directives included into the ``Location`` sections for the Apache +# server status configuration. Can be used to customize access for example. +# Refer to :ref:`item.status_directives ` for +# how to overwrite this for a virtual host. +apache__status_directives: '' + + # ]]] +# .. envvar:: apache__status_extended_enabled [[[ +# +# This option tracks additional data per worker about the currently executing +# request and creates a utilization summary. +# Refer to the `Apache ExtendedStatus directive documentation`_ for details. +# Note that this setting cannot be changed during a graceful restart. You will +# need to restart Apache yourself for a change to take effect! +apache__status_extended_enabled: '{{ apache__status_enabled|bool }}' + + # ]]] +# .. envvar:: apache__status_vhost_name [[[ +# +# Virtual host name for providing the Apache server status. +apache__status_vhost_name: + - 'localhost' + + # ]]] +# .. envvar:: apache__status_vhost [[[ +# +# Optional virtual host for providing the Apache server status. +apache__status_vhost: + name: '{{ apache__status_vhost_name }}' + filename: 'debops.apache-status' + status_enabled: True + status_allow_localhost: True + listen_http: [ 'localhost:80' ] + https_enabled: False + enabled: '{{ apache__status_vhost_enabled|bool }}' + # ]]] + # ]]] # Configuration for other Ansible roles [[[ # ----------------------------------------- @@ -763,7 +973,7 @@ apache__ferm__dependent_rules: by_role: 'debops.apache' name: 'http_https' multiport: True - + rule_state: '{{ apache__deploy_state }}' # ]]] # ]]] # ]]] diff --git a/docs/ansible-integration.rst b/docs/ansible-integration.rst index 454a38e..dbb7c30 100644 --- a/docs/ansible-integration.rst +++ b/docs/ansible-integration.rst @@ -8,9 +8,6 @@ Design goals * Try not to modify/replace configuration files which are maintained by Debian. In particular the :file:`/etc/apache2/apache2.conf` is not altered. -* The ``IfVersion`` directive is not used to keep the number of enabled modules - as minimum as possible. Instead the configuration is generated for the - currently detected Apache version. * Most variables which directly correspond to a Apache directive are not masked or otherwise changed (for example using ``True``, ``False`` for directives which expect ``on``, ``off`` is *not* supported). @@ -21,12 +18,18 @@ Design goals special variable ``omit`` (use in Jinja: ``{{ omit }}``) is intended to be used when the directive should be omitted (not written to the Apache configuration at all). +* Apache is not restarted by the role because that would require to close + established connections. Some configuration options require a restart to take + effect. The documentation for those options should give a hint about it. You + should test your settings with a test system and do a restart in production + manually when required. + Optionally, it should be possible to allow restarts using inventory variables. Alternative roles ----------------- -Has `Ansible Galaxy`_ an impressive number of Ansible roles for Apache to your +`Ansible Galaxy`_ has an impressive number of Ansible roles for Apache at your disposal. A few of them have been checked out before/while writing this role: * `geerlingguy.apache `_ @@ -34,5 +37,5 @@ disposal. A few of them have been checked out before/while writing this role: * And peeked at a few more. However, none of the already existing roles where found to be a suitable start for -Apache support in Debops so this role has been designed and written from scratch. +Apache support in DebOps so this role has been designed and written from scratch. Unfortunately, that workflow is not uncommon considering the quality requirements and standards of DebOps. diff --git a/docs/defaults-detailed.rst b/docs/defaults-detailed.rst index 5ff96d0..a660bd8 100644 --- a/docs/defaults-detailed.rst +++ b/docs/defaults-detailed.rst @@ -41,6 +41,7 @@ supported options: ``enabled`` Required, boolean. Defaults to ``True``. + Set to ``{{ omit }}`` not change the state of a module. Whether the module should be enabled or disabled in Apache. ``force`` @@ -98,8 +99,8 @@ supported options: Whether the module should be ``present`` or ``absent`` in the :file:`conf-available` directory. ``type`` - Optional, string. Specify name of the template to use to generate the virtual - host configuration. Templates can extend other templates. + Optional, string. + Refer to the following subsections for the supported type. Type: raw @@ -146,6 +147,16 @@ same filename as the snippet which is diverted away. Allows to specify a full file path where to divert the file to. Note that the ``item.divert_suffix`` is still in affect when using this option. + +Type: dont-create +~~~~~~~~~~~~~~~~~ + +This special type assumes the snippet file is already present and does not try +to create it. +This can be used to enable or disable snippet files managed by system packages +for example. + + Examples ~~~~~~~~ @@ -216,11 +227,13 @@ Common role options host configuration. Templates can extend other templates. -.. _apache__ref_vhosts_common_webserver_options: +.. _apache__ref_vhost_common_webserver_options: Common webserver options ~~~~~~~~~~~~~~~~~~~~~~~~ +.. _apache__ref_vhost_server_admin: + ``server_admin`` Optional, string. Defaults to :envvar:`apache__server_admin`. @@ -399,7 +412,7 @@ HTTP security headers determines the Content-Security-Policy header set in server responses. Refer to the `Content Security Policy Reference`_. -.. _apache__ref_vhosts_http_xss_protection: +.. _apache__ref_vhost_http_xss_protection: ``http_xss_protection`` Optional, string. Value of the ``X-XSS-Protection`` HTTP header field. Set to @@ -419,7 +432,7 @@ HTTP security headers “X-XSS-Protection”? `_. -.. _apache__ref_vhosts_http_referrer_policy: +.. _apache__ref_vhost_http_referrer_policy: ``http_referrer_policy`` Optional, string. Value of the ``Referrer-Policy`` HTTP header field. Set to @@ -428,6 +441,42 @@ HTTP security headers draft as of 2016-10-11 but it is already supported by the majority of web browsers. + +.. _apache__ref_vhost_apache_status: + +Apache status +~~~~~~~~~~~~~ + +.. _apache__ref_vhost_status_enabled: + +``status_enabled`` + Optional, boolean. Should the Apache server status be enabled? + Defaults to :envvar:`apache__status_enabled`. + +.. _apache__ref_vhost_status_location: + +``status_location`` + Optional, string. + The ``Location`` or URL path by which the Apache server status should be + accessible. + Defaults to :envvar:`apache__status_location`. + +.. _apache__ref_vhost_status_allow_localhost: + +``status_allow_localhost`` + Optional, boolean. + Allow access to the Apache server status using the ``Require local`` + directive. + Defaults to :envvar:`apache__status_allow_localhost`. + +.. _apache__ref_vhost_status_directives: + +``status_directives`` + Optional, string. + Additional directives included into the ``Location`` sections for the Apache + server status configuration. Can be used to customize access for example. + Defaults to :envvar:`apache__status_directives`. + Type: raw ~~~~~~~~~ diff --git a/docs/getting-started.rst b/docs/getting-started.rst index e49f1a5..a7114c6 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -1,11 +1,11 @@ Getting started =============== +.. include:: includes/all.rst + .. contents:: :local: -.. include:: includes/all.rst - Example inventory ----------------- diff --git a/docs/includes/role.rst b/docs/includes/role.rst index 3c72640..4570317 100644 --- a/docs/includes/role.rst +++ b/docs/includes/role.rst @@ -28,3 +28,14 @@ .. _Apache AllowOverride directive documentation: https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride .. _Apache Options directive documentation: https://httpd.apache.org/docs/2.4/mod/core.html#options .. _ModSecurity SecServerSignature directive documentation: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#secserversignature +.. _Apache MaxConnectionsPerChild directive documentation: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxconnectionsperchild +.. _Apache MaxRequestWorkers directive documentation: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxrequestworkers +.. _Apache mod_status documentation: https://httpd.apache.org/docs/current/mod/mod_status.html +.. _Apache mod_status: https://httpd.apache.org/docs/current/mod/mod_status.html +.. _Apache mod_version: https://httpd.apache.org/docs/current/mod/mod_version.html +.. _Apache IfVersion directive: https://httpd.apache.org/docs/current/mod/mod_version.html#ifversion +.. _Apache Location directive: https://httpd.apache.org/docs/current/mod/core.html#location +.. _Apache Location directives: https://httpd.apache.org/docs/current/mod/core.html#location +.. _Apache ExtendedStatus directive documentation: https://httpd.apache.org/docs/current/mod/core.html#extendedstatus +.. _Apache host Require directive documentation: https://httpd.apache.org/docs/current/mod/mod_authz_host.html#requiredirectives +.. _Apache SetHandler directive: https://httpd.apache.org/docs/current/mod/core.html#sethandler diff --git a/docs/introduction.rst b/docs/introduction.rst index f044738..bacadeb 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -3,7 +3,8 @@ Introduction .. include:: includes/all.rst -The ``debops.apache`` role allows you to setup and mange the `Apache HTTP Server`_. +The ``debops.apache`` role allows you to setup and manage the `Apache HTTP Server`_ +with version 2.4 and above. Installation diff --git a/docs/playbooks/apache.yml b/docs/playbooks/apache.yml index 0f47b1d..edd640d 100644 --- a/docs/playbooks/apache.yml +++ b/docs/playbooks/apache.yml @@ -11,7 +11,7 @@ roles: - role: debops.apache/env - tags: [ 'role::apache' ] + tags: [ 'role::apache', 'role::apache:env' ] - role: debops.ferm tags: [ 'role::ferm' ] diff --git a/handlers/main.yml b/handlers/main.yml index 109c06f..d9257c3 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -4,16 +4,18 @@ command: apache2ctl configtest notify: [ 'Reload apache' ] -- name: Test apache and restart - command: apache2ctl configtest - notify: [ 'Restart apache' ] +# - name: Test apache and restart +# command: apache2ctl configtest +# notify: [ 'Restart apache' ] - name: Reload apache service: name: '{{ apache__service_name }}' state: 'reloaded' -- name: Restart apache - service: - name: '{{ apache__service_name }}' - state: 'restarted' +## Listed here for completeness but not used. +## Refer to ../docs/ansible-integration.rst +# - name: Restart apache +# service: +# name: '{{ apache__service_name }}' +# state: 'restarted' diff --git a/meta/ansigenome.yml b/meta/ansigenome.yml index 581c3a2..21e7af0 100644 --- a/meta/ansigenome.yml +++ b/meta/ansigenome.yml @@ -16,6 +16,7 @@ ansigenome_info: github: 'ypid' synopsis: | - The ``debops.apache`` role allows you to setup and mange the [Apache HTTP Server]. + The ``debops.apache`` role allows you to setup and manage the [Apache HTTP Server] + with version 2.4 and above. [Apache HTTP Server]: https://en.wikipedia.org/wiki/Apache_HTTP_Server diff --git a/tasks/apache_module_state.yml b/tasks/apache_module_state.yml new file mode 100644 index 0000000..27ad944 --- /dev/null +++ b/tasks/apache_module_state.yml @@ -0,0 +1,16 @@ +--- +# vim: foldmarker=[[[,]]]:foldmethod=marker + +- name: Enable/disable Apache modules + apache2_module: + name: '{{ item.key }}' + state: '{{ (item.value.enabled + if (item.value is mapping) + else item.value) | bool | ternary("present", "absent") }}' + force: '{{ item.value.force|d(False) | bool }}' + notify: [ 'Test apache and reload' ] + when: (item.key in apache__tpl_available_modules + and item.value.enabled|d(True) != omit + and apache__deploy_state == "present") + with_dict: '{{ apache__combined_modules }}' + tags: [ 'role::apache:modules' ] diff --git a/tasks/main.yml b/tasks/main.yml index 8779672..710f053 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -11,7 +11,6 @@ - '{{ apache__dependent_packages }}' # Manage Apache modules [[[1 - - name: Get list of available modules find: file_type: 'file' @@ -25,17 +24,7 @@ apache__tpl_available_modules: '{{ apache__register_mods_available.files|d({}) | map(attribute="path") | map("replace", apache__config_path + "/mods-available/", "") | map("regex_replace", "\.load$", "") | list }}' tags: [ 'role::apache:modules' ] -- name: Enable/disable Apache modules - apache2_module: - name: '{{ item.key }}' - state: '{{ (item.value.enabled - if (item.value is mapping) - else item.value) | bool | ternary("present", "absent") }}' - force: '{{ item.value.force|d(False) | bool }}' - notify: [ 'Test apache and reload' ] - when: (item.key in apache__tpl_available_modules) - with_dict: '{{ apache__combined_modules }}' - tags: [ 'role::apache:modules' ] +- include: apache_module_state.yml # Manage Apache configuration snippets [[[1 - name: Divert conf-available configuration @@ -65,7 +54,7 @@ group: 'root' mode: '0644' when: (item.value.state|d("present") != "absent" and - (item.value.type|d("default") not in ["divert"] or item.value.raw|d())) + (item.value.type|d("default") not in ["divert", "dont-create"] or item.value.raw|d())) with_dict: '{{ apache__combined_snippets }}' notify: [ 'Test apache and reload' ] @@ -135,3 +124,15 @@ when: (item.type|d(apache__vhost_type) not in ["divert"]) with_flattened: '{{ apache__combined_vhosts }}' tags: [ 'role::apache:vhosts' ] + + +# Manage Apache modules, part 2 [[[1 +- name: Detect if the rewrite module has been used in the active configuration + shell: grep --ignore-case '^\s*RewriteEngine On' {{ apache__config_path | quote }}/sites-enabled/* {{ apache__config_path | quote }}/conf-enabled/* + register: apache__register_mod_rewrite_used + always_run: True + failed_when: apache__register_mod_rewrite_used.rc not in [ 0, 1 ] + changed_when: False + when: apache__register_mod_rewrite_used is undefined + +- include: apache_module_state.yml diff --git a/templates/etc/ansible/facts.d/apache.fact.j2 b/templates/etc/ansible/facts.d/apache.fact.j2 index f0b2cd5..80b8893 100644 --- a/templates/etc/ansible/facts.d/apache.fact.j2 +++ b/templates/etc/ansible/facts.d/apache.fact.j2 @@ -10,6 +10,8 @@ import re output = loads('''{{ ({ "enabled": (apache__deploy_state == "present"), "user": apache__user, + "use_if_version": apache__config_use_if_version, + "min_version": apache__config_min_version, }) | to_nice_json }}''') try: @@ -20,4 +22,8 @@ try: except: pass +if output['use_if_version']: + if output['min_version'] == 'current_major_minor': + output['min_version'] = '.'.join(output['version'].split('.')[:2]) + print(dumps(output, sort_keys=True, indent=2)) diff --git a/templates/etc/apache2/conf-available/local-debops_apache.conf.j2 b/templates/etc/apache2/conf-available/local-debops_apache.conf.j2 index 1056516..11c1835 100644 --- a/templates/etc/apache2/conf-available/local-debops_apache.conf.j2 +++ b/templates/etc/apache2/conf-available/local-debops_apache.conf.j2 @@ -9,6 +9,11 @@ # It is probably not good practice to change that in server context anyway. #} +MaxConnectionsPerChild {{ apache__mpm_max_connections_per_child | quote }} + +ExtendedStatus {{ apache__status_extended_enabled|bool | ternary("On", "Off") }} + + {% for module_name, value in apache__combined_modules|dictsort %} {% if value is mapping and 'config' in value %} @@ -25,6 +30,8 @@ LogLevel {{ apache__log_level }} {{ apache__tpl_macros.get_common_headers(item) | indent(4) }} +{# Don’t use apache__combined_modules because of heavy use of template macros. #} + {{ apache__tpl_macros.get_default_tls_directives(item.value|d({})) }} {% if debops__tpl_macros.get_openssl_version()|version_compare("0.9.8h", ">=") %} @@ -33,4 +40,5 @@ SSLStaplingResponseMaxAge {{ apache__ocsp_stapling_response_max_age|string }} {% if apache__ocsp_stapling_force_url %} SSLStaplingForceURL {{ apache__ocsp_stapling_force_url | quote }} {% endif %} + {% endif %} diff --git a/templates/etc/apache2/sites-available/apache__tpl_macros.j2 b/templates/etc/apache2/sites-available/apache__tpl_macros.j2 index beb5bed..2dacea1 100644 --- a/templates/etc/apache2/sites-available/apache__tpl_macros.j2 +++ b/templates/etc/apache2/sites-available/apache__tpl_macros.j2 @@ -2,6 +2,65 @@ #} {% import 'debops__tpl_macros.j2' as debops__tpl_macros with context %} +{% macro get_min_version_wrapped(content, version, compare_operator) %}{# [[[ #} +{# Examples: + +{{ get_min_version_wrapped('# 2.3.0 directive', "2.3", ">=") }} +{{ get_min_version_wrapped('# 2.4.0 directive', "2.4", ">=") }} +{{ get_min_version_wrapped('# 2.4.1 directive', "2.4.1", ">=") }} +{{ get_min_version_wrapped('# 2.5.0 directive', "2.5", ">=") }} + +#} +{% set version = '==' if (version == '=') else version %} +{% set apache__tpl_compare_operator_includes_equal = True if (compare_operator in ['>=', '<=', '==']) else False %} +{% if (version | version_compare(debops__tpl_macros.get_apache_min_version(), compare_operator)) + or (version | version_compare(debops__tpl_macros.get_apache_min_version(), ">")) %} +{% if apache__tpl_compare_operator_includes_equal and (version | version_compare(debops__tpl_macros.get_apache_min_version(), "==")) %} +{{ content -}} +{% else %} + + {{ debops__tpl_macros.indent(content, 4) }} + +{% endif %} +{% endif %} +{% endmacro %}{# ]]] #} + +{% macro get_version_wrapped(content, version, compare_operator, fallback_content=False) %}{# [[[ #} +{# This macro has not been extensivly tested yet. If it contains bugs please try to debug it if you need it. + +Examples: + +{{ get_version_wrapped('# 2.3.0 directive', "2.3", ">=", '# Prior to 2.3 directive') }} +{{ get_version_wrapped('# 2.4.0 directive', "2.4", ">=", '# Prior to 2.4 directive') }} +{{ get_version_wrapped('# 2.4.1 directive', "2.4.1", ">=", '# Prior to 2.4.1 directive') }} +{{ get_version_wrapped('# 2.5.0 directive', "2.5", ">=", '# Prior to 2.5 directive') }} + +#} +{% set version = '==' if (version == '=') else version %} +{% set apache__tpl_xor_compare_operator_map = {} %} +{% set apache__tpl_xor_compare_operator_list = [ + ('==', '!='), + ('>=', '<'), + ('<=', '>'), +] %} +{% for compare_operator, xor_compare_operator in apache__tpl_xor_compare_operator_list %} +{% set _ = apache__tpl_xor_compare_operator_map.update({ compare_operator: xor_compare_operator }) %} +{% set _ = apache__tpl_xor_compare_operator_map.update({ xor_compare_operator: compare_operator }) %} +{% endfor %} +{% if apache__config_use_if_version|bool %} +{{ get_min_version_wrapped(content, version, compare_operator) -}} +{% if fallback_content != False %} +{{ get_min_version_wrapped(fallback_content, version, apache__tpl_xor_compare_operator_map[compare_operator]) -}} +{% endif %} +{% else %} +{% if debops__tpl_macros.get_apache_version() | version_compare(version, compare_operator) %} +{{ content -}} +{% elif fallback_content != False %} +{{ fallback_content -}} +{% endif %} +{% endif %} +{% endmacro %}{# ]]] #} + {% macro get_server_name_aliases(name_item) %}{# [[[ #} {% set apache__tpl_names = debops__tpl_macros.get_yaml_list_for_elem(name_item) | from_yaml %} {% if not apache__tpl_names %} @@ -47,6 +106,58 @@ CustomLog ${APACHE_LOG_DIR}/{{ sanitized_name }}_access.log {{ apache__access_lo ErrorLog ${APACHE_LOG_DIR}/{{ sanitized_name }}_error.log {% endmacro %}{# ]]] #} +{% macro get_server_status_directives(item, enabled) %}{# [[[ #} +{% if enabled|bool %} + + SetHandler server-status +{% if item.status_allow_localhost|d(apache__status_allow_localhost) | bool %} + Require local +{% endif %} +{% if item.status_directives|d(apache__status_directives) %} + {{ item.status_directives|d(apache__status_directives) }} +{% elif not (item.status_allow_localhost|d(apache__status_allow_localhost) | bool) %} + Require all denied +{% endif %} + +{% endif %} +{% endmacro %}{# ]]] #} + +{% macro get_vhost_content_directives(item, mode='https', https_enabled=True) %}{# [[[ #} +{% set apache__tpl_use_redirect_module = 'alias' %} +{% set apache__tpl_status_enabled = item.status_enabled|d(apache__status_for_vhost_enabled) | bool %} +{{ get_server_status_directives(item, apache__tpl_status_enabled) -}} +{% if apache__tpl_status_enabled|bool and ( + (mode == 'http' and (item.redirect_http|d() or item.redirect_to_https|d(https_enabled) | bool)) or + (mode == 'https' and item.redirect_https|d()) + ) %} +RewriteEngine On +RewriteRule "^{{ item.status_location|d(apache__status_location) }}" "-" [L] +{% set apache__tpl_use_redirect_module = 'rewrite' %} +{% endif %} +{% if mode == 'http' and item.redirect_http|d() %} +{{ get_redirect(item.redirect_http_code|d(307), "/", item.redirect_http, apache__tpl_use_redirect_module) }} +{% elif mode == 'http' and item.redirect_to_https|d(https_enabled) | bool %} +{{ get_redirect(item.redirect_to_https_with_code|d("301"), "/", "https://" + (debops__tpl_macros.get_yaml_list_for_elem(item.name) | from_yaml)[0], apache__tpl_use_redirect_module) }} +{% elif mode == 'https' and item.redirect_https|d() %} +{{ get_redirect(item.redirect_https_code|d(307), "/", item.redirect_https, apache__tpl_use_redirect_module) }} +{% else %} +{{ get_content_directives(item) }} +{% endif %} +{% endmacro %}{# ]]] #} + +{% macro get_document_root_directives(item) %}{# [[[ #} +Options {{ debops__tpl_macros.get_yaml_list_for_elem(item.options|d(apache__vhost_options))|from_yaml | join(" ") }} +AllowOverride {{ debops__tpl_macros.get_yaml_list_for_elem(item.allow_override|d(apache__vhost_allow_override))|from_yaml | join(" ") }} + +{{ get_version_wrapped('Require all granted', "2.4", ">=", +'Order allow,deny +Allow from all') -}} +{% if item.root_directives|d() %} + +{{ item.root_directives }} +{% endif %} +{% endmacro %}{# ]]] #} + {% macro get_content_directives(item) %}{# [[[ #} {% if item.include|d() %} {% for include_file in debops__tpl_macros.get_yaml_list_for_elem(item.include)|from_yaml %} @@ -65,20 +176,7 @@ DocumentRoot {{ item.root|d(item.document_root) | quote }} {{ get_alias(item.alias, item.root|d(item.document_root)) }} {%- endif %} - Options {{ debops__tpl_macros.get_yaml_list_for_elem(item.options|d(apache__vhost_options))|from_yaml | join(" ") }} - AllowOverride {{ debops__tpl_macros.get_yaml_list_for_elem(item.allow_override|d(apache__vhost_allow_override))|from_yaml | join(" ") }} - -{% if debops__tpl_macros.get_apache_version() | version_compare("2.4", ">=") %} - Require all granted -{% else %} - Order allow,deny - Allow from all -{% endif %} -{% if item.root_directives|d() %} - - {{ item.root_directives | indent(4) }} -{% endif %} - + {{ debops__tpl_macros.indent(get_document_root_directives(item), 4) }} {% endif %} {% if item.raw_content|d() %} @@ -89,7 +187,7 @@ DocumentRoot {{ item.root|d(item.document_root) | quote }} {% macro get_default_tls_directives(item) %}{# [[[ #} {# Included in server context to provide sane defaults (there might be vhosts -# not controled by this template) and virtual host context to ensure those +# not controled by this template) and in virtual host context to ensure those # settings are appliend and to allow per-vhost changes. # Refer to Applied-Crypto-Hardening_bettercrypto/src/configuration/Webservers/Apache/default-ssl for details. #} @@ -164,8 +262,17 @@ Header always set X-Clacks-Overhead "GNU Terry Pratchett" {% endif %} {% endmacro %}{# ]]] #} -{% macro get_redirect(code, from, to) %}{# [[[ #} -Redirect {{ code|string }} "{{ from }}" "{{ to + ("/" if (to[-1] != "/") else "") }}" +{% macro get_redirect(code, from, to, module) %}{# [[[ #} +{# Prefer the alias module but support the use of the rewrite module in case +other rewrite rules are used in the same context because the rewrite rules are +handled before all the directives from the alias module. +#} +{% set to = to + ("/" if (to[-1] != "/") else "") %} +{% if module == 'alias' %} +Redirect {{ code|string }} "{{ from }}" "{{ to }}" +{% elif module == 'rewrite' %} +RewriteRule "^{{ from }}?(.*)" "{{ to }}$1" [L,R={{ code }},NE] +{% endif %} {% endmacro %}{# ]]] #} {% macro get_alias(url_path, fs_directory) %}{# [[[ #} diff --git a/templates/etc/apache2/sites-available/debops__tpl_macros.j2 b/templates/etc/apache2/sites-available/debops__tpl_macros.j2 index 4dbbde6..f2c6f9a 100644 --- a/templates/etc/apache2/sites-available/debops__tpl_macros.j2 +++ b/templates/etc/apache2/sites-available/debops__tpl_macros.j2 @@ -1,12 +1,14 @@ {# vim: foldmarker=[[[,]]]:foldmethod=marker -# Copyright [[[ # Commonly used set of macros in DebOps. # It can be included in repositories as needed. -# Changes to this file should go upstream: FIXME +# Changes to this file should go upstream: https://github.com/debops/debops-playbooks/blob/master/templates/debops__tpl_macros.j2 +# +# Copyright [[[ +# ============= # -# Copyright (C) 2014-2016 Maciej Delmanowski -# Copyright (C) 2015-2016 Robin Schneider -# Copyright (C) 2014-2016 DebOps https://debops.org/ +# Copyright (C) 2014-2017 Maciej Delmanowski +# Copyright (C) 2015-2017 Robin Schneider +# Copyright (C) 2014-2017 DebOps https://debops.org/ # # This file is part of DebOps. # @@ -21,6 +23,27 @@ # # You should have received a copy of the GNU General Public License # along with DebOps. If not, see https://www.gnu.org/licenses/. +# +# ]]] +# +# Usage [[[ +# ========= +# +# Copy the template file into your ./templates/ path of a role where it fits +# best. You can/might need to use symlinks to make the macros available from +# different paths in your ./templates/ hierarchy. +# +# Make sure to retain the filename of this file so that automatic updates of +# this file can be implemented. +# +# To use the macros in your own template, this file needs to be included like so: +# +# {% import 'debops__tpl_macros.j2' as debops__tpl_macros with context %} +# +# Then you can start using the macros like this: +# +# {{ debops__tpl_macros.indent(some_content, 4) }} +# # ]]] #} {% macro get_yaml_list_for_elem(list_or_elem) %}{# [[[ #} @@ -50,7 +73,14 @@ {{ ansible_local.apache.version if (ansible_local|d() and ansible_local.apache|d() and ansible_local.apache.version|d()) - else "2.4.0" }} + else "2.4.0" -}} +{% endmacro %}{# ]]] #} + +{% macro get_apache_min_version() %}{# [[[ #} +{{ ansible_local.apache.min_version + if (ansible_local|d() and ansible_local.apache|d() and + ansible_local.apache.min_version|d()) + else "2.4.0" -}} {% endmacro %}{# ]]] #} {% macro get_openssl_version() %}{# [[[ #} @@ -66,3 +96,13 @@ ansible_local.pki.gnutls_version|d()) else "0.0.0" }} {% endmacro %}{# ]]] #} + +{% macro indent(content, width=4, indentfirst=False) %}{# [[[ #} +{# Fixed version of the `indent` filter which does not insert trailing spaces on empty lines. +## Note that you can not use this macro like a filter but have to use it like a regular macro. +## Example: {{ debops__tpl_macros.indent(some_content, 4) }} +## +## Python re.sub seems to default to re.MULTILINE in Ansible. +#} +{{ content | indent(width, indentfirst) | regex_replace("[ \\t\\r\\f\\v]+(\\n|$)", "\\1") -}} +{% endmacro %}{# ]]] #} diff --git a/templates/etc/apache2/sites-available/default.conf.j2 b/templates/etc/apache2/sites-available/default.conf.j2 index 6279bfb..d3de1f2 100644 --- a/templates/etc/apache2/sites-available/default.conf.j2 +++ b/templates/etc/apache2/sites-available/default.conf.j2 @@ -2,44 +2,36 @@ # vim: foldmarker=[[[,]]]:foldmethod=marker {% import 'debops__tpl_macros.j2' as debops__tpl_macros with context %} {% import 'apache__tpl_macros.j2' as apache__tpl_macros with context %} +{% set apache__tpl_vhost_http_enabled = True if (apache__tpl_macros.get_listen_sockets(item.listen_http|d([]), apache__http_listen)) else False %} +{% set apache__tpl_vhost_https_enabled = True if (item.https_enabled|d(apache__https_enabled)|bool and apache__tpl_macros.get_listen_sockets(item.listen_https|d([]), apache__https_listen)) else False %} {{ apache__tpl_macros.get_header_comments(item) }} -{% if apache__tpl_macros.get_listen_sockets(item.listen_http|d([]), apache__http_listen) %} +{% if apache__tpl_vhost_http_enabled|bool %} # Virtual host handling HTTP [[[ - {{ apache__tpl_macros.get_server_directives(item) | indent(4) }} + {{ debops__tpl_macros.indent(apache__tpl_macros.get_server_directives(item), 4) }} -{% if item.redirect_http|d() %} - {{ apache__tpl_macros.get_redirect( item.redirect_http_code|d(307), "/", item.redirect_http) | indent(4) }} -{% elif item.redirect_to_https|d(True) | bool %} - Redirect {{ item.redirect_to_https_with_code|d("301") }} "/" "https://{{ (debops__tpl_macros.get_yaml_list_for_elem(item.name) | from_yaml)[0] }}/" -{% else %} - {{ apache__tpl_macros.get_content_directives(item) | indent(4) }} -{% endif %} + {{ debops__tpl_macros.indent(apache__tpl_macros.get_vhost_content_directives(item, mode='http', https_enabled=apache__tpl_vhost_https_enabled), 4) }} # ]]] {% endif %} -{% if apache__https_enabled|bool and apache__tpl_macros.get_listen_sockets(item.listen_https|d([]), apache__https_listen) %} +{% if apache__tpl_vhost_https_enabled|bool %} # Virtual host handling HTTPS [[[ + - {{ apache__tpl_macros.get_server_directives(item) | indent(4) }} - + {{ debops__tpl_macros.indent(apache__tpl_macros.get_server_directives(item), 4) }} - {{ apache__tpl_macros.get_https_directives(item) | indent(4) }} + {{ debops__tpl_macros.indent(apache__tpl_macros.get_https_directives(item), 4) }} + {{ debops__tpl_macros.indent(apache__tpl_macros.get_http_security_headers(item), 4) }} + {{ debops__tpl_macros.indent(apache__tpl_macros.get_common_headers(item), 4) }} - {{ apache__tpl_macros.get_http_security_headers(item) | indent(4) }} - {{ apache__tpl_macros.get_common_headers(item) | indent(4) }} - -{% if item.redirect_https|d() %} - {{ apache__tpl_macros.get_redirect( item.redirect_https_code|d(307), "/", item.redirect_https) | indent(4) }} -{% else %} - {{ apache__tpl_macros.get_content_directives(item) | indent(4) }} -{% endif %} + {{ debops__tpl_macros.indent(apache__tpl_macros.get_vhost_content_directives(item, mode='https'), 4) }} + # ]]] {% endif %}