From 2295c62326dfb3dd3cc682c8d827daccb295dac2 Mon Sep 17 00:00:00 2001
From: Chris Croome <chris@webarchitects.co.uk>
Date: Sat, 29 Apr 2023 12:27:08 +0100
Subject: [PATCH] Ansible lint updates

---
 .ansible-lint             |   5 --
 defaults/main.yml         |  13 ++++
 meta/argument_specs.yml   | 159 ++++++++++++++++++++++++++++++++++++++
 tasks/a2conf.yml          |  15 +++-
 tasks/a2conf_checks.yml   |  23 ++++--
 tasks/a2mod.yml           |  33 +++++---
 tasks/a2mod_checks.yml    |  23 ++++--
 tasks/a2site.yml          |  17 +++-
 tasks/a2site_checks.yml   |  23 ++++--
 tasks/checks.yml          |  17 +++-
 tasks/cloudflare.yml      |  19 +++--
 tasks/config.yml          |  41 ++++++----
 tasks/local_facts.yml     |   9 +++
 tasks/main.yml            |  55 ++++++++-----
 tasks/mc3.yml             |  17 +++-
 tasks/md.yml              |  23 ++++--
 tasks/md_status.yml       |  31 +++++---
 tasks/mpm.yml             |  49 +++++++-----
 tasks/suexec.yml          |  13 +++-
 tasks/verify.yml          |  33 ++++++++
 tasks/webarch.yml         |  17 +++-
 templates/webarch.conf.j2 |  32 ++++----
 vars/main.yml             |  14 ++++
 23 files changed, 527 insertions(+), 154 deletions(-)
 create mode 100644 meta/argument_specs.yml
 create mode 100644 tasks/verify.yml
 create mode 100644 vars/main.yml

diff --git a/.ansible-lint b/.ansible-lint
index 91a81ee..e8cf9ab 100644
--- a/.ansible-lint
+++ b/.ansible-lint
@@ -10,12 +10,7 @@
 ---
 # https://ansible-lint.readthedocs.io/rules/
 skip_list:
-  - fqcn[action-core]
-  - fqcn[action]
-  - jinja[spacing]
   - key-order[task]
-  - name[casing]
-  - name[template]
   - no-changed-when
   - no-handler
   - package-latest
diff --git a/defaults/main.yml b/defaults/main.yml
index daccedb..f106fde 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 apache_user: www-data
 apache_group: www-data
@@ -171,4 +180,8 @@ apache_md_private_keys:
 # Specify a version from here https://github.com/icing/mod_md/releases
 # Use latest for the latest release or default for the packaged version
 apache_md_version: latest
+apache_md_renew_window: 33%
+apache_mpm_max_connections_per_child: 10000
+apache_mpm_max_request_workers: 128
+apache_verify: true
 ...
diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml
new file mode 100644
index 0000000..fd6de8e
--- /dev/null
+++ b/meta/argument_specs.yml
@@ -0,0 +1,159 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
+---
+argument_specs:
+  main:
+    author: Chris Croome
+    description: An Ansible role for installing and configurinag the Apache HTTP server.
+    short_description: The main entry point for the Apache role.
+    options:
+      apache_a2query:
+        type: str
+        required: true
+        description: The path for /usr/sbin/a2query.
+      apache_chroot_dir:
+        type: str
+        required: false
+        description: The directory to chroot Apache into when it is set to be chrooted.
+      apache_chroot:
+        type: bool
+        required: false
+        description: Chroot Apache.
+      apache_conf_disabled:
+        type: list
+        elements: str
+        required: true
+        description: A list of Apache conf that should be disabled.
+      apache_conf_enabled:
+        type: list
+        elements: str
+        required: true
+        description: A list of Apache conf that should be enabled.
+      apache_dhparam_path:
+        type: str
+        required: true
+        description: The path to the dhparam file.
+      apache_dhparam_size:
+        type: int
+        required: true
+        description: The size for the dhparam.
+      apache_disable_dot:
+        type: int
+        required: false
+        description: Deny access to file and directory names that start with a dot.
+      apache_disable_root:
+        type: int
+        required: false
+        description: Deny access to the root files system.
+      apache_document_root:
+        type: str
+        required: true
+        description: The default DocumentRoot.
+      apache_group:
+        type: str
+        required: true
+        description: The group that the Apache process should run as.
+      apache_localhost_port:
+        type: int
+        required: true
+        description: The port that Apache should listen on the localhost.
+      apache_md_private_keys:
+        type: list
+        elements: str
+        description: A list of of key tryes for MDPrivateKeys.
+        choices:
+          - rsa3072
+          - secp256r1
+          - secp384r1
+      apache_md_renew_window:
+        type: str
+        required: false
+        description: Apache MDRenewWindow.
+      apache_md_version:
+        type: str
+        required: false
+        description: The version of mod_md to install.
+      apache_mods_disabled:
+        type: list
+        elements: str
+        required: true
+        description: Apache mods that should be disabled.
+      apache_mods_enabled:
+        type: list
+        elements: str
+        required: true
+        description: Apache mods that should be enabled.
+      apache_mpm_max_connections_per_child:
+        type: int
+        required: false
+        description: Apache MPM MaxConnectionsPerChild.
+      apache_mpm_max_request_workers:
+        type: int
+        required: false
+        description: Apache MPM MaxRequestWorkers.
+      apache_packages_present:
+        type: list
+        elements: str
+        required: false
+        description: A list of Apache packages that should be present.
+      apache_server_admin:
+        type: str
+        required: true
+        description: An email address for ServerAdmin and MDContactEmail.
+      apache_server_tokens:
+        type: str
+        required: true
+        description: What information should be returned inn the Server HTTP response Header.
+        choices:
+          - Full
+          - Major
+          - Minimal
+          - Minor
+          - OS
+          - Prod
+      apache_sites_disabled:
+        type: list
+        elements: str
+        required: true
+        description: A list of Apache sites that should be disabled.
+      apache_sites_enabled:
+        type: list
+        elements: str
+        required: true
+        description: A list of Apache sites that should be enabled.
+      apache_suexec:
+        type: bool
+        required: false
+        description: Install Apache suEXEC.
+      apache_timeout:
+        type: int
+        required: true
+        description: Apache Timeout value.
+      apache_tls1_2_cipher_suites:
+        type: str
+        required: true
+        description: A list of colon seperate TLSv1.2 ciphers for SSLCipherSuite.
+      apache_tls1_3_cipher_suites:
+        type: str
+        required: true
+        description: A list of colon seperate TLSv1.3 ciphers for SSLCipherSuite.
+      apache_ulimit:
+        type: int
+        required: true
+        description: The maximun number of files Apache can open, used for the APACHE_ULIMIT_MAX_FILES env var.
+      apache_user:
+        type: str
+        required: true
+        description: The user that the Apache process should run as.
+      apache_verify:
+        type: bool
+        required: false
+        description: Verify all variables that start with apache_.
+...
diff --git a/tasks/a2conf.yml b/tasks/a2conf.yml
index 0bc3f31..d00a9c0 100644
--- a/tasks/a2conf.yml
+++ b/tasks/a2conf.yml
@@ -1,12 +1,21 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Disable and enable Apache conf
   block:
 
     - name: Check loaded conf
-      include_tasks: a2conf_checks.yml
+      ansible.builtin.include_tasks: a2conf_checks.yml
 
     - name: Apache conf disabled
-      command: "a2disconf {{ conf }}"
+      ansible.builtin.command: "a2disconf {{ conf }}"
       args:
         removes: "/etc/apache2/conf-enabled/{{ conf }}.conf"
       when:
@@ -19,7 +28,7 @@
         label: "{{ conf }}"
 
     - name: Apache conf enabled
-      command: "a2enconf {{ conf }}"
+      ansible.builtin.command: "a2enconf {{ conf }}"
       args:
         creates: "/etc/apache2/conf-enabled/{{ conf }}.conf"
       when:
diff --git a/tasks/a2conf_checks.yml b/tasks/a2conf_checks.yml
index 2129299..1befd72 100644
--- a/tasks/a2conf_checks.yml
+++ b/tasks/a2conf_checks.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Check Apache conf
   block:
@@ -6,7 +15,7 @@
       block:
 
         - name: Register the loaded conf
-          command: a2query -c
+          ansible.builtin.command: a2query -c
           check_mode: false
           changed_when: false
           register: apache_conf_check
@@ -14,7 +23,7 @@
       rescue:
 
         - name: No conf enabled
-          set_fact:
+          ansible.builtin.set_fact:
             apache_conf_loaded: []
           when: '"No conf matches" in apache_conf_check.stderr'
 
@@ -22,17 +31,17 @@
       block:
 
         - name: Debug the loaded conf
-          debug:
+          ansible.builtin.debug:
             var: apache_conf_check.stdout_lines
             verbosity: 2
 
         - name: Set apache_conf_loaded to an empty array
-          set_fact:
+          ansible.builtin.set_fact:
             apache_conf_loaded: []
 
         - name: Set an array of the loaded conf
-          set_fact:
-            apache_conf_loaded: "{{ apache_conf_loaded | default([]) + [ line.split(' ')[0] ] }}"
+          ansible.builtin.set_fact:
+            apache_conf_loaded: "{{ apache_conf_loaded | default([]) + [line.split(' ')[0]] }}"
           loop: "{{ apache_conf_check.stdout_lines }}"
           loop_control:
             loop_var: line
@@ -43,7 +52,7 @@
         - apache_conf_check.stderr | length == 0
 
     - name: Debug loaded conf
-      debug:
+      ansible.builtin.debug:
         var: apache_conf_loaded
         verbosity: 1
 
diff --git a/tasks/a2mod.yml b/tasks/a2mod.yml
index 21e4e55..9f515b8 100644
--- a/tasks/a2mod.yml
+++ b/tasks/a2mod.yml
@@ -1,6 +1,15 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Check loaded modules
-  include_tasks: a2mod_checks.yml
+  ansible.builtin.include_tasks: a2mod_checks.yml
   tags:
     - apache
 
@@ -8,7 +17,7 @@
   block:
 
     - name: Apache ITK MPM package absent
-      apt:
+      ansible.builtin.apt:
         pkg:
           - libapache2-mpm-itk
         state: absent
@@ -16,7 +25,7 @@
       when: '"mpm_itk" in apache_mods_disabled'
 
     - name: Apache FastCGI absent
-      apt:
+      ansible.builtin.apt:
         pkg:
           - libapache2-mod-fcgid
         state: absent
@@ -24,15 +33,15 @@
       when: '"fcgid" in apache_mods_disabled'
 
     - name: Apache suEXEC package absent
-      apt:
+      ansible.builtin.apt:
         pkg:
           - apache2-suexec-pristine
         state: absent
         update_cache: false
       when: '"suexec" in apache_mods_disabled'
 
-    - name: "Apache {{ apache_phpfpm_mod }} package absent"
-      apt:
+    - name: "Apache package absent {{ apache_phpfpm_mod }}"
+      ansible.builtin.apt:
         pkg:
           - "libapache2-mod-php{{ apache_php_version }}"
         state: absent
@@ -40,7 +49,7 @@
       when: ( apache_php ) and ( "apache_phpfpm_mod" in apache_mods_disabled )
 
     - name: Disable modules
-      apache2_module:
+      community.general.apache2_module:
         name: "{{ mod }}"
         state: absent
       when: mod in apache_modules_loaded
@@ -59,7 +68,7 @@
   block:
 
     - name: Apache ITK MPM package present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - libapache2-mpm-itk
         state: present
@@ -67,7 +76,7 @@
       when: '"mpm_itk" in apache_mods_enabled'
 
     - name: Apache Suexec package present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - apache2-suexec-pristine
         state: present
@@ -75,7 +84,7 @@
       when: '"suexec" in apache_mods_enabled'
 
     - name: Apache FastCGI package present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - libapache2-mod-fcgid
         state: present
@@ -83,7 +92,7 @@
       when: '"fcgid" in apache_mods_enabled'
 
     - name: Apache mod_php package present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - "libapache2-mod-php{{ apache_php_version }}"
         state: present
@@ -91,7 +100,7 @@
       when: ( apache_php ) and ( "apache_phpfpm_mod" in apache_mods_enabled )
 
     - name: Apache modules enabled
-      apache2_module:
+      community.general.apache2_module:
         name: "{{ mod }}"
         state: present
       when: mod not in apache_modules_loaded
diff --git a/tasks/a2mod_checks.yml b/tasks/a2mod_checks.yml
index c07a219..f1d710a 100644
--- a/tasks/a2mod_checks.yml
+++ b/tasks/a2mod_checks.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Apache module checks
   block:
@@ -6,7 +15,7 @@
       block:
 
         - name: Register the loaded modules
-          command: a2query -m
+          ansible.builtin.command: a2query -m
           check_mode: false
           changed_when: false
           register: apache_modules_check
@@ -14,7 +23,7 @@
       rescue:
 
         - name: No mod enabled
-          set_fact:
+          ansible.builtin.set_fact:
             apache_modules_loaded: []
           when: ( "No module matches" in apache_modules_check.stderr )
 
@@ -22,17 +31,17 @@
       block:
 
         - name: Debug the loaded modules
-          debug:
+          ansible.builtin.debug:
             var: apache_modules_check.stdout_lines
             verbosity: 2
 
         - name: Set apache_modules_loaded to an empty array
-          set_fact:
+          ansible.builtin.set_fact:
             apache_modules_loaded: []
 
         - name: Set an array of the loaded modules
-          set_fact:
-            apache_modules_loaded: "{{ apache_modules_loaded + [ line.split(' ')[0] ] }}"
+          ansible.builtin.set_fact:
+            apache_modules_loaded: "{{ apache_modules_loaded + [line.split(' ')[0]] }}"
           loop: "{{ apache_modules_check.stdout_lines }}"
           loop_control:
             loop_var: line
@@ -43,7 +52,7 @@
         - apache_modules_check.stderr | length == 0
 
     - name: Debug loaded modules
-      debug:
+      ansible.builtin.debug:
         var: apache_modules_loaded
         verbosity: 1
 
diff --git a/tasks/a2site.yml b/tasks/a2site.yml
index 8a34037..96ca595 100644
--- a/tasks/a2site.yml
+++ b/tasks/a2site.yml
@@ -1,12 +1,21 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Apache sites checked, disabled and enabled
   block:
 
     - name: Check loaded sites
-      include_tasks: a2site_checks.yml
+      ansible.builtin.include_tasks: a2site_checks.yml
 
     - name: Apache sites disabled
-      command: "a2dissite {{ site }}"
+      ansible.builtin.command: "a2dissite {{ site }}"
       args:
         removes: "/etc/apache2/sites-enabled/{{ site }}.conf"
       when:
@@ -22,7 +31,7 @@
       block:
 
         - name: Apache sites enabled
-          command: "a2ensite {{ site }}"
+          ansible.builtin.command: "a2ensite {{ site }}"
           args:
             creates: "/etc/apache2/sites-enabled/{{ site }}.conf"
           when:
@@ -37,7 +46,7 @@
       rescue:
 
         - name: Site enable failed
-          debug:
+          ansible.builtin.debug:
             msg: Enabing an Apache site failed, check that the files exists in /etc/apache2/sites-available
 
   tags:
diff --git a/tasks/a2site_checks.yml b/tasks/a2site_checks.yml
index 8d8e7c2..df47eb0 100644
--- a/tasks/a2site_checks.yml
+++ b/tasks/a2site_checks.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Apache sites checked
   block:
@@ -6,7 +15,7 @@
       block:
 
         - name: Register the loaded sites
-          command: a2query -s
+          ansible.builtin.command: a2query -s
           check_mode: false
           changed_when: false
           register: apache_sites_check
@@ -14,7 +23,7 @@
       rescue:
 
         - name: No sites enabled
-          set_fact:
+          ansible.builtin.set_fact:
             apache_sites_loaded: []
           when: ( "No site matches" in apache_sites_check.stderr )
 
@@ -22,17 +31,17 @@
       block:
 
         - name: Debug the loaded sites
-          debug:
+          ansible.builtin.debug:
             var: apache_sites_check.stdout_lines
             verbosity: 2
 
         - name: Set apache_sites_loaded to an empty array
-          set_fact:
+          ansible.builtin.set_fact:
             apache_sites_loaded: []
 
         - name: Set an array of the loaded sites
-          set_fact:
-            apache_sites_loaded: "{{ apache_sites_loaded | default([]) + [ line.split(' ')[0] ] }}"
+          ansible.builtin.set_fact:
+            apache_sites_loaded: "{{ apache_sites_loaded | default([]) + [line.split(' ')[0]] }}"
           when: apache_sites_check.stdout is defined
           loop: "{{ apache_sites_check.stdout_lines }}"
           loop_control:
@@ -44,7 +53,7 @@
         - apache_sites_check.stderr | length == 0
 
     - name: Debug loaded sites
-      debug:
+      ansible.builtin.debug:
         var: apache_sites_loaded
         verbosity: 1
 
diff --git a/tasks/checks.yml b/tasks/checks.yml
index 190aa74..fcf745d 100644
--- a/tasks/checks.yml
+++ b/tasks/checks.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Check that mistakes haven't been made in the variables and arrays
   block:
@@ -41,7 +50,7 @@
           - apache_sites_enabled | unique | count == apache_sites_enabled | count
           - apache_sites_disabled | unique | count == apache_sites_disabled | count
 
-    - name: apache_mods_enabled and apache_mods_disabled array checks
+    - name: Check apache_mods_enabled and apache_mods_disabled arrays
       block:
 
         - name: Debug apache_mods_enabled array
@@ -74,7 +83,7 @@
         - ( apache_mods_enabled is defined ) and ( apache_mods_enabled[0] is defined )
         - ( apache_mods_disabled is defined ) and ( apache_mods_disabled[0] is defined )
 
-    - name: apache_conf_enabled and apache_conf_disabled array checks
+    - name: Check apache_conf_enabled and apache_conf_disabled arrays
       block:
 
         - name: Debug apache_conf_enabled arrays
@@ -108,7 +117,7 @@
         - ( apache_conf_enabled is defined ) and ( apache_conf_enabled[0] is defined )
         - ( apache_conf_disabled is defined ) and ( apache_conf_disabled[0] is defined )
 
-    - name: apache_sites_enabled and apache_sites_disabled array checks
+    - name: Check apache_sites_enabled and apache_sites_disabled arrays
       block:
 
         - name: Debug apache_sites_enabled arrays
@@ -214,7 +223,7 @@
           register: apache_update_alternatives_query_php
 
         - name: Set a fact for the default version of PHP
-          ansible.builtin.ansible.builtin.set_fact:
+          ansible.builtin.set_fact:
             apache_php_version: "{{ apache_update_alternatives_query_php.stdout | string | community.general.jc('update_alt_q') | community.general.json_query('default') | regex_replace('^/usr/bin/php') }}"
 
         - name: Set facts for the PHP FPM module and conf names
diff --git a/tasks/cloudflare.yml b/tasks/cloudflare.yml
index 2c0bf16..98504a2 100644
--- a/tasks/cloudflare.yml
+++ b/tasks/cloudflare.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Generate Cloudflare config
   block:
 
     - name: Download Cloudflare IPv4 list
-      get_url:
+      ansible.builtin.get_url:
         url: "https://www.cloudflare.com/ips-v4"
         dest: "/root/cloudflare_ips_v4.txt"
         owner: root
@@ -12,21 +21,21 @@
         force: true
 
     - name: Slurp Cloudflare IPv4 list
-      slurp:
+      ansible.builtin.slurp:
         src: "/root/cloudflare_ips_v4.txt"
       register: "apache_cloudflare_ips_v4_b64encoded"
 
     - name: Create an array from the Cloudflare IP lists
-      set_fact:
+      ansible.builtin.set_fact:
         apache_cloudflare_ips: "{{ ( apache_cloudflare_ips_v4_b64encoded['content'] | b64decode | trim ).split('\n') }}"
 
     - name: Debug Cloudflare IP array
-      debug:
+      ansible.builtin.debug:
         msg: "apache_cloudflare_ips: {{ apache_cloudflare_ips }}"
         verbosity: 2
 
     - name: Apache Cloudflare config generated
-      template:
+      ansible.builtin.template:
         src: cloudflare.conf.j2
         dest: /etc/apache2/conf-available/cloudflare.conf
         owner: root
diff --git a/tasks/config.yml b/tasks/config.yml
index ed56fb9..13ac24e 100644
--- a/tasks/config.yml
+++ b/tasks/config.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Apache config available
   block:
 
     - name: Directories present
-      file:
+      ansible.builtin.file:
         path: "{{ path }}"
         state: directory
         owner: root
@@ -17,7 +26,7 @@
         label: "{{ path }}"
 
     - name: Custom Apache config in place
-      template:
+      ansible.builtin.template:
         src: "{{ file }}.j2"
         dest: "/etc/apache2/{{ file }}"
         owner: root
@@ -31,7 +40,7 @@
         label: "{{ file }}"
 
     - name: Custom Apache mods available in place
-      template:
+      ansible.builtin.template:
         src: "{{ file }}.j2"
         dest: "/etc/apache2/mods-available/{{ file }}"
         owner: root
@@ -47,7 +56,7 @@
         label: "{{ file }}"
 
     - name: Custom Apache conf available in place
-      template:
+      ansible.builtin.template:
         src: "{{ file }}.j2"
         dest: "/etc/apache2/conf-available/{{ file }}"
         owner: root
@@ -61,7 +70,7 @@
         label: "{{ file }}"
 
     - name: Conditional update 000-default.conf
-      template:
+      ansible.builtin.template:
         src: 000-default.conf.j2
         dest: /etc/apache2/sites-available/000-default.conf
         owner: root
@@ -70,7 +79,7 @@
       when: ( apache_sites_enabled is defined ) and ( "000-default" in apache_sites_enabled )
 
     - name: Conditional update default-ssl.conf
-      template:
+      ansible.builtin.template:
         src: default-ssl.conf.j2
         dest: /etc/apache2/sites-available/default-ssl.conf
         owner: root
@@ -79,7 +88,7 @@
       when: ( apache_sites_enabled is defined ) and ( "default-ssl" in apache_sites_enabled )
 
     - name: Apache localhost site available
-      template:
+      ansible.builtin.template:
         src: "templates/localhost.conf.j2"
         dest: "/etc/apache2/sites-available/localhost.conf"
         owner: root
@@ -87,15 +96,15 @@
         mode: "0644"
 
     - name: Conditionally include Webarchitects config
-      include_tasks: webarch.yml
+      ansible.builtin.include_tasks: webarch.yml
       when: ( apache_conf_enabled is defined ) and ( "webarch" in apache_conf_enabled )
 
     - name: Conditionally include mc3 config
-      include_tasks: mc3.yml
+      ansible.builtin.include_tasks: mc3.yml
       when: ( apache_conf_enabled is defined ) and ( "mc3" in apache_conf_enabled )
 
     - name: Apache localhost and localhost.d directories in place
-      file:
+      ansible.builtin.file:
         path: "{{ dir }}"
         state: directory
         owner: root
@@ -109,7 +118,7 @@
         label: "{{ dir }}"
 
     - name: Deny robots files in place
-      template:
+      ansible.builtin.template:
         src: robots.deny.txt.j2
         dest: /var/www/html/robots.deny.txt
         owner: root
@@ -117,7 +126,7 @@
         mode: "0644"
 
     - name: Expires and robots conf available
-      template:
+      ansible.builtin.template:
         src: "templates/{{ file }}.j2"
         dest: "/etc/apache2/conf-available/{{ file }}"
         owner: root
@@ -134,7 +143,7 @@
         label: "{{ file }}"
 
     - name: Apache mpm_prefork.conf in place
-      template:
+      ansible.builtin.template:
         src: templates/mpm_prefork.conf.j2
         dest: /etc/apache2/mods-available/mpm_prefork.conf
         owner: root
@@ -143,7 +152,7 @@
       when: ( "mpm_itk" in apache_mods_enabled ) or ( "mpm_prefork" in apache_mods_enabled )
 
     - name: Apache ratelimit conf present
-      template:
+      ansible.builtin.template:
         src: templates/ratelimit.conf.j2
         dest: /etc/apache2/mods-available/ratelimit.conf
         owner: root
@@ -152,14 +161,14 @@
       when: '"ratelimit" in apache_mods_enabled'
 
     - name: Cloudflare config available
-      include_tasks: cloudflare.yml
+      ansible.builtin.include_tasks: cloudflare.yml
       when: ( "remoteip" in apache_mods_enabled )
 
     - name: Conditionally provision a Let's Encrypt cert using acmesh role
       block:
 
         - name: "Provision a Let's Encrypt cert for {{ inventory_hostname }}"
-          include_role:
+          ansible.builtin.include_role:
             name: acmesh
             tasks_from: letsencrypt
           vars:
diff --git a/tasks/local_facts.yml b/tasks/local_facts.yml
index 7f2ccff..307b97f 100644
--- a/tasks/local_facts.yml
+++ b/tasks/local_facts.yml
@@ -1,3 +1,12 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Ansible local facts
   block:
diff --git a/tasks/main.yml b/tasks/main.yml
index dfd287f..3dda2a1 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,9 +1,24 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Install and configure Apache
   block:
 
+    - name: Verify variables that start with apache_
+      ansible.builtin.include_tasks: verify.yml
+      when:
+        - apache_verify is defined
+        - apache_verify | bool
+
     - name: Apache present from buster-backports
-      apt:
+      ansible.builtin.apt:
         pkg:
           - apache2
         state: latest
@@ -13,7 +28,7 @@
       when: ansible_distribution_release == "buster"
 
     - name: Apache present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - apache2
         state: present
@@ -22,20 +37,20 @@
       when: ansible_distribution_release != "buster"
 
     - name: Additional packages present
-      apt:
+      ansible.builtin.apt:
         pkg: "{{ apache_packages_present }}"
         state: present
         update_cache: false
       when: ( apache_packages_present is defined ) and ( apache_packages_present != [] )
 
     - name: Include local facts tasks
-      include_tasks: local_facts.yml
+      ansible.builtin.include_tasks: local_facts.yml
 
     - name: Include Apache checks
-      include_tasks: checks.yml
+      ansible.builtin.include_tasks: checks.yml
 
     - name: Apache DocumentRoot present
-      file:
+      ansible.builtin.file:
         path: "{{ apache_document_root }}"
         state: directory
         mode: "0755"
@@ -43,27 +58,27 @@
         group: root
 
     - name: Apache DH parameters file present
-      openssl_dhparam:
+      community.crypto.openssl_dhparam:
         path: "{{ apache_dhparam_path }}"
         size: "{{ apache_dhparam_size }}"
 
     - name: Include suEXEC tasks
-      include_tasks: suexec.yml
+      ansible.builtin.include_tasks: suexec.yml
       when: ( apache_suexec is defined ) and ( apache_suexec )
 
     - name: Install specific version of mod_md
-      include_tasks: md.yml
+      ansible.builtin.include_tasks: md.yml
       when: ( "md" in apache_mods_enabled ) and ( apache_md_version is defined ) and ( apache_md_version != "default" )
 
     - name: Include MPM switching tasks
-      include_tasks: mpm.yml
+      ansible.builtin.include_tasks: mpm.yml
       when: ( apache_mpm_loaded not in apache_mods_enabled ) or ( apache_mpm_loaded | length == 0 )
 
     - name: Apache config available
-      include_tasks: config.yml
+      ansible.builtin.include_tasks: config.yml
 
     - name: Apache envars in place
-      template:
+      ansible.builtin.template:
         src: templates/envvars.j2
         dest: /etc/apache2/envvars
         mode: "0755"
@@ -71,41 +86,41 @@
         group: root
 
     - name: Apache modules disabled and enabled
-      include_tasks: a2mod.yml
+      ansible.builtin.include_tasks: a2mod.yml
       when: ( apache_mods_disabled is defined ) or ( apache_mods_enabled is defined )
 
     - name: Apache conf disabled and enabled
-      include_tasks: a2conf.yml
+      ansible.builtin.include_tasks: a2conf.yml
       when: ( apache_sites_disabled is defined ) or ( apache_conf_enabled is defined )
 
     - name: Apache sites disabled and enabled
-      include_tasks: a2site.yml
+      ansible.builtin.include_tasks: a2site.yml
       when: ( apache_sites_disabled is defined ) or ( apache_sites_enabled is defined )
 
     - name: Apache enabled for systemd servers
-      systemd:
+      ansible.builtin.systemd:
         name: apache2
         enabled: true
       when: ansible_distribution_release != "stretch"
 
     - name: Apache configtest
-      command: apache2ctl configtest
+      ansible.builtin.command: apache2ctl configtest
       register: apache_configtest
       failed_when: apache_configtest.rc is not regex('^0|1$')
       check_mode: false
 
     - name: Print the apache2ctl configtest standard error
-      debug:
+      ansible.builtin.debug:
         msg: "{{ apache_configtest.stderr }}"
         verbosity: 1
 
     - name: Fail if Apache configtest is not OK
-      fail:
+      ansible.builtin.fail:
         msg: "{{ apache_configtest.stdout_lines }}"
       when: ( "Syntax OK" not in apache_configtest.stderr ) or ( apache_configtest.rc == 1 )
 
     - name: Apache restarted
-      service:
+      ansible.builtin.service:
         name: apache2
         state: restarted
       when: ( "Syntax OK" in apache_configtest.stderr ) or ( apache_configtest.rc == 0 )
diff --git a/tasks/mc3.yml b/tasks/mc3.yml
index 16aa83a..b73a937 100644
--- a/tasks/mc3.yml
+++ b/tasks/mc3.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Config for mc3.coop
   block:
 
-    - name: mc3 templates present
-      git:
+    - name: Template present for mc3.coop
+      ansible.builtin.git:
         repo: https://git.coop/mc3coop/ssh-templates.git
         dest: /var/www/mc3
         version: master
@@ -12,12 +21,12 @@
         force: true
 
     - name: Debian default /var/www/html/index.html absent
-      file:
+      ansible.builtin.file:
         path: /var/www/html/index.html
         state: absent
 
     - name: WSH Apache config in place
-      template:
+      ansible.builtin.template:
         src: templates/mc3.conf.j2
         dest: /etc/apache2/conf-available/mc3.conf
         owner: root
diff --git a/tasks/md.yml b/tasks/md.yml
index fdcad16..9153493 100644
--- a/tasks/md.yml
+++ b/tasks/md.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Install mod_md from https://github.com/icing/mod_md
   block:
 
     - name: Requirements present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - apache2-dev
           - apache2-ssl-dev
@@ -15,7 +24,7 @@
       block:
 
         - name: Use a HEAD request to get the latest redirect URL
-          uri:
+          ansible.builtin.uri:
             url: https://github.com/icing/mod_md/releases/latest
             method: HEAD
             status_code: 302
@@ -25,13 +34,13 @@
           register: apache_md_latest_headers
 
         - name: Set a fact for the latest version of Apache mod_md
-          set_fact:
+          ansible.builtin.set_fact:
             apache_md_version: "{{ apache_md_latest_headers.location | urlsplit('path') | basename }}"
 
       when: apache_md_version == "latest"
 
     - name: Source code present
-      git:
+      ansible.builtin.git:
         repo: https://github.com/icing/mod_md.git
         dest: /usr/local/src/mod_md
         version: "{{ apache_md_version }}"
@@ -44,17 +53,17 @@
       block:
 
         - name: Buildconf mod_md
-          command: ./buildconf
+          ansible.builtin.command: ./buildconf
           args:
             chdir: /usr/local/src/mod_md
 
         - name: Configure mod_md
-          command: ./configure --with-apxs=/usr/bin/apxs --enable-werror
+          ansible.builtin.command: ./configure --with-apxs=/usr/bin/apxs --enable-werror
           args:
             chdir: /usr/local/src/mod_md
 
         - name: Make install mod_md
-          make:
+          community.general.make:
             chdir: /usr/local/src/mod_md
             target: install
 
diff --git a/tasks/md_status.yml b/tasks/md_status.yml
index b1b94c5..eae8a38 100644
--- a/tasks/md_status.yml
+++ b/tasks/md_status.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Check the status of a mod_md cert
   block:
 
     - name: "Query the status for {{ apache_mdomain }}"
-      uri:
+      ansible.builtin.uri:
         url: "http://localhost/md-status/{{ apache_mdomain }}"
         return_content: true
         status_code:
@@ -13,17 +22,17 @@
       register: apache_mdomain_status
 
     - name: "Debug the mdomain status for {{ apache_mdomain }}"
-      debug:
+      ansible.builtin.debug:
         var: apache_mdomain_status.json
         verbosity: 1
       when: apache_mdomain_status.json is defined
 
     - name: Set apache_md_certs_present to an empty array
-      set_fact:
+      ansible.builtin.set_fact:
         apache_md_certs_present: []
 
     - name: "Set a fact for the mdomain RSA status for {{ apache_mdomain_status }}"
-      set_fact:
+      ansible.builtin.set_fact:
         apache_md_certs_present: "{{ apache_md_certs_present }} + [ 'rsa3072' ]"
       when:
         - ( apache_md_private_keys is defined )
@@ -36,7 +45,7 @@
         - ( apache_mdomain_status.json.cert.rsa.ocsp.renewal.finished )
 
     - name: "Set a fact for the mdomain EC status for {{ apache_mdomain_status }}"
-      set_fact:
+      ansible.builtin.set_fact:
         apache_md_certs_present: "{{ apache_md_certs_present }} + [ 'secp384r1' ]"
       when:
         - ( apache_md_private_keys is defined )
@@ -49,27 +58,27 @@
         - ( apache_mdomain_status.json.cert.secp384r1.ocsp.renewal.finished )
 
     - name: Debug apache_md_private_keys array
-      debug:
+      ansible.builtin.debug:
         var: apache_md_private_keys
         verbosity: 1
 
     - name: Debug apache_md_certs_present array
-      debug:
+      ansible.builtin.debug:
         var: apache_md_certs_present
         verbosity: 1
 
     - name: Debug the difference between apache_md_private_keys and apache_md_certs_present
-      debug:
+      ansible.builtin.debug:
         msg:
-          - "{{ apache_md_private_keys | difference(apache_md_certs_present ) }}"
+          - "{{ apache_md_private_keys | difference(apache_md_certs_present) }}"
 
     - name: Set a fact to indicate the key and cert status is good
-      set_fact:
+      ansible.builtin.set_fact:
         apache_md_certs: true
       when: apache_md_private_keys | difference(apache_md_certs_present ) == []
 
     - name: Set a fact to indicate the key and cert status is bad
-      set_fact:
+      ansible.builtin.set_fact:
         apache_md_certs: false
       when: apache_md_private_keys | difference(apache_md_certs_present ) != []
 
diff --git a/tasks/mpm.yml b/tasks/mpm.yml
index e9a2776..faca389 100644
--- a/tasks/mpm.yml
+++ b/tasks/mpm.yml
@@ -1,19 +1,28 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Enable Apache mpm_event if mpm_prefork or no MPM loaded
   block:
 
     - name: Include Apache checks
-      include_tasks: checks.yml
+      ansible.builtin.include_tasks: checks.yml
 
     - name: Debug Apache modules loaded
-      debug:
+      ansible.builtin.debug:
         msg: "Apache modules loaded: {{ apache_modules_loaded }}"
         verbosity: 1
       when:
         - ( apache_modules_loaded is defined ) and ( apache_modules_loaded | length > 0 )
 
     - name: "Disable Apache module {{ apache_phpfpm_mod }}"
-      apache2_module:
+      community.general.apache2_module:
         name: "{{ apache_phpfpm_mod }}"
         state: absent
       when:
@@ -21,27 +30,27 @@
         - ( apache_phpfpm_mod is defined ) and ( apache_phpfpm_mod in apache_modules_loaded )
 
     - name: Disable Apache module mpm_itk
-      apache2_module:
+      community.general.apache2_module:
         name: mpm_itk
         state: absent
       when: ( apache_mpm_loaded is defined ) and ( apache_mpm_loaded == "mpm_itk" )
 
     - name: Disable Apache module mpm_prefork
-      apache2_module:
+      community.general.apache2_module:
         name: mpm_prefork
         state: absent
         ignore_configcheck: true
       when: ( apache_mpm_loaded is defined ) and ( apache_mpm_loaded == "mpm_prefork" )
 
     - name: "Enable Apache mpm_event"
-      apache2_module:
+      community.general.apache2_module:
         name: mpm_event
         state: present
         ignore_configcheck: true
       register: apache_mpm_event_enabled
 
     - name: Restart Apache if the MPM has changed
-      service:
+      ansible.builtin.service:
         name: apache2
         state: restarted
       when: apache_mpm_event_enabled.changed
@@ -56,21 +65,21 @@
   block:
 
     - name: "Disable Apache module mpm_event"
-      apache2_module:
+      community.general.apache2_module:
         name: mpm_event
         state: absent
         ignore_configcheck: true
       when: ( apache_mpm_loaded is defined ) and  ( apache_mpm_loaded == "mpm_event" )
 
     - name: "Enable Apache mpm_prefork"
-      apache2_module:
+      community.general.apache2_module:
         name: mpm_prefork
         state: present
         ignore_configcheck: true
       register: apache_mpm_prefork_enabled
 
     - name: Restart Apache if the MPM has changed
-      service:
+      ansible.builtin.service:
         name: apache2
         state: restarted
       when: apache_mpm_prefork_enabled.changed
@@ -85,23 +94,23 @@
   block:
 
     - name: Check the enabled MPM
-      command: a2query -M
+      ansible.builtin.command: a2query -M
       check_mode: false
       changed_when: false
       register: apache_mpm_check
 
     - name: Debug the enabled MPM
-      debug:
+      ansible.builtin.debug:
         msg: "{{ apache_mpm_check.stdout }}"
         verbosity: 2
 
     - name: Set a fact for the enabled MPM
-      set_fact:
+      ansible.builtin.set_fact:
         apache_mpm_loaded: "mpm_{{ apache_mpm_check.stdout | trim }}"
       when: apache_mpm_check.stdout != "invalid"
 
     - name: Fail if no Apache MPM loaded
-      fail:
+      ansible.builtin.fail:
         msg: "No Apache MPM loaded"
       when: apache_mpm_check.stdout == "invalid"
 
@@ -115,7 +124,7 @@
       block:
 
         - name: Register the loaded modules
-          command: a2query -m
+          ansible.builtin.command: a2query -m
           check_mode: false
           changed_when: false
           register: apache_modules_check
@@ -123,19 +132,19 @@
       rescue:
 
         - name: No mod enabled
-          set_fact:
+          ansible.builtin.set_fact:
             apache_modules_loaded: []
           when: '"No module matches" in apache_modules_check.stderr'
 
     - name: Debug the loaded modules
-      debug:
+      ansible.builtin.debug:
         var: apache_modules_check.stdout_lines
         verbosity: 2
       when: apache_modules_check.stdout is defined
 
     - name: Set an array of the loaded modules
-      set_fact:
-        apache_modules_loaded: "{{ apache_modules_loaded | default([]) + [ line.split(' ')[0] ] }}"
+      ansible.builtin.set_fact:
+        apache_modules_loaded: "{{ apache_modules_loaded | default([]) + [line.split(' ')[0]] }}"
       when: apache_modules_check.stdout is defined
       loop: "{{ apache_modules_check.stdout_lines }}"
       loop_control:
@@ -143,7 +152,7 @@
         label: "{{ line }}"
 
     - name: Debug loaded modules
-      debug:
+      ansible.builtin.debug:
         var: apache_modules_loaded
         verbosity: 2
       when: apache_modules_loaded is defined
diff --git a/tasks/suexec.yml b/tasks/suexec.yml
index 2ab1fc5..0f8c23c 100644
--- a/tasks/suexec.yml
+++ b/tasks/suexec.yml
@@ -1,15 +1,24 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Install and configure Apache suEXEC
   block:
 
     - name: Apache suEXEC package present
-      apt:
+      ansible.builtin.apt:
         pkg:
           - apache2-suexec-custom
         state: present
 
     - name: Apache suEXEC config directory only readable by root
-      file:
+      ansible.builtin.file:
         path: /etc/apache2/suexec
         state: directory
         mode: "0700"
diff --git a/tasks/verify.yml b/tasks/verify.yml
new file mode 100644
index 0000000..7b6230f
--- /dev/null
+++ b/tasks/verify.yml
@@ -0,0 +1,33 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
+---
+- name: Verify variables starting with apache_
+  block:
+
+    - name: Debug the hostvars variable names that start with apache_
+      ansible.builtin.debug:
+        var: apachevarnames
+        verbosity: "{% if ansible_check_mode | bool %}3{% else %}4{% endif %}"
+
+    - name: Debug the hostvars variable names that start with apache_
+      ansible.builtin.debug:
+        var: apachehostvars
+        verbosity: "{% if ansible_check_mode | bool %}3{% else %}4{% endif %}"
+
+    - name: Check apache_ variables using meta/argument_specs.yml
+      ansible.builtin.validate_argument_spec:
+        argument_spec: "{{ (lookup('ansible.builtin.file', 'meta/argument_specs.yml') | from_yaml)['argument_specs']['main']['options'] }}"
+        provided_arguments: "{{ apachehostvars }}"
+
+
+  when: apache_verify | bool
+  tags:
+    - apache
+...
diff --git a/tasks/webarch.yml b/tasks/webarch.yml
index 65ac24d..a60e578 100644
--- a/tasks/webarch.yml
+++ b/tasks/webarch.yml
@@ -1,9 +1,18 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 - name: Config for webarch.coop
   block:
 
     - name: Webarchitects templates present
-      git:
+      ansible.builtin.git:
         repo: https://git.coop/webarch/website-templates.git
         dest: /var/www/wsh
         version: master
@@ -12,18 +21,18 @@
         force: true
 
     - name: Debian default /var/www/html/index.html absent
-      file:
+      ansible.builtin.file:
         path: /var/www/html/index.html
         state: absent
 
     - name: "Check the mdomain status for {{ inventory_hostname }}"
-      include_tasks: md_status.yml
+      ansible.builtin.include_tasks: md_status.yml
       vars:
         apache_mdomain: "{{ inventory_hostname }}"
       when: ( "md" in apache_mods_enabled )
 
     - name: WSH Apache config in place
-      template:
+      ansible.builtin.template:
         src: templates/webarch.conf.j2
         dest: /etc/apache2/conf-available/webarch.conf
         trim_blocks: false
diff --git a/templates/webarch.conf.j2 b/templates/webarch.conf.j2
index cac9282..d46d99c 100644
--- a/templates/webarch.conf.j2
+++ b/templates/webarch.conf.j2
@@ -11,7 +11,7 @@ LogFormat "%I %O" bandwidth
 Protocols h2 h2c http/1.1 acme-tls/1
 ProtocolsHonorOrder On
 {% elif apache_mods_enabled is defined and "http2" in apache_mods_enabled and "md" not in apache_mods_enabled %}
-Protocols h2 h2c http/1.1 
+Protocols h2 h2c http/1.1
 ProtocolsHonorOrder Off
 {% endif %}
 # Let's Encrypt
@@ -23,7 +23,7 @@ Alias /wsh.shtml /var/www/wsh/wsh.shtml
 Alias /icons /usr/share/apache2/icons
 # env vars for the default index page, wsh.shtml
 {% if apache_conf_enabled is defined and "phpmyadmin" in apache_conf_enabled %}
-SetEnv PHPMYADMIN_DOMAIN "{{ inventory_hostname }}" 
+SetEnv PHPMYADMIN_DOMAIN "{{ inventory_hostname }}"
 SetEnv PHPMYADMIN_PATH "/phpmyadmin/"
 {% elif phpmyadmin_domain is defined %}
 SetEnv PHPMYADMIN_DOMAIN "{{ phpmyadmin_domain }}"
@@ -41,7 +41,7 @@ SetEnv SITE_TITLE "Webarchitects Shared Hosting"
 SetEnv STATIC_DIR "/wsh/"
 SetEnv STATIC_TOP "top.shtml"
 SetEnv STATIC_BOT "bot.shtml"
-# default page title 
+# default page title
 SetEnv PAGE_TITLE "Directory Listing"
 SetEnv PAGE_DESC  ""
 <Directory "/">
@@ -50,14 +50,14 @@ SetEnv PAGE_DESC  ""
   Require all denied
 </Directory>
 <Directory "/var/www/wsh">
-  Options IncludesNoExec 
+  Options IncludesNoExec
   DirectoryIndex wsh.shtml
   AddOutputFilter Includes shtml
-  SSILegacyExprParser on 
-  SSILastModified on 
+  SSILegacyExprParser on
+  SSILastModified on
   HeaderName /wsh/top.shtml
   ReadmeName /wsh/bot.shtml
-  IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* 
+  IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=*
   IndexOptions Charset=UTF-8 SuppressHTMLPreamble XHTML TrackModified IconsAreLinks
   IndexOptions SuppressDescription
   AllowOverride None
@@ -91,16 +91,16 @@ SetEnv PAGE_DESC  ""
 </Directory>
 <Directory "/var/www/html/.well-known">
   Options None
-  AllowOverride None 
+  AllowOverride None
   ForceType text/plain
 </Directory>
 <Directory "/home/*/sites/*">
   DirectoryIndex wsh.shtml
   AddOutputFilter Includes shtml
-  SSILegacyExprParser on 
+  SSILegacyExprParser on
   HeaderName /wsh/top.shtml
   ReadmeName /wsh/bot.shtml
-  IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* 
+  IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=*
   IndexOptions Charset=UTF-8 SuppressHTMLPreamble XHTML TrackModified IconsAreLinks
   IndexOptions SuppressDescription
 </Directory>
@@ -124,13 +124,13 @@ ErrorDocument 506 /wsh/506.shtml
 
 # The default virtual host for port 80
 <VirtualHost *:80>
-  ServerName {{ inventory_hostname }} 
+  ServerName {{ inventory_hostname }}
   ServerAlias www.{{ inventory_hostname }}
   <IfModule mpm_itk_module>
-    AssignUserID www-data www-data 
+    AssignUserID www-data www-data
   </IfModule>
   <IfModule suexec_module>
-    SuexecUserGroup www-data www-data 
+    SuexecUserGroup www-data www-data
   </IfModule>
   ServerAdmin support@webarch.net
   {%- if matomo_domain is defined %}
@@ -178,13 +178,13 @@ ErrorDocument 506 /wsh/506.shtml
 # The default virtual host for port 443
 <IfModule ssl_module>
 <VirtualHost *:443>
-  ServerName {{ inventory_hostname }} 
+  ServerName {{ inventory_hostname }}
   ServerAlias www.{{ inventory_hostname }}
   <IfModule mpm_itk_module>
-    AssignUserID www-data www-data 
+    AssignUserID www-data www-data
   </IfModule>
   <IfModule suexec_module>
-    SuexecUserGroup www-data www-data 
+    SuexecUserGroup www-data www-data
   </IfModule>
   ServerAdmin "{{ apache_server_admin }}"
   {%- if matomo_domain is defined %}
diff --git a/vars/main.yml b/vars/main.yml
new file mode 100644
index 0000000..1b90f30
--- /dev/null
+++ b/vars/main.yml
@@ -0,0 +1,14 @@
+# Copyright 2018-2023 Chris Croome
+#
+# This file is part of the Webarchitects Apache Ansible role.
+#
+# The Webarchitects Apache Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+#
+# The Webarchitects Apache Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with the Webarchitects Apache Ansible role. If not, see <https://www.gnu.org/licenses/>.
+---
+# https://docs.ansible.com/ansible/latest/playbook_guide/complex_data_manipulation.html
+apachevarnames: "{{ q('varnames', '^apache_') | sort }}"
+apachehostvars: "{{ dict(apachevarnames | list | zip(q('vars', *apachevarnames))) }}"
+...
-- 
GitLab