diff --git a/tasks/apt.yml b/tasks/apt.yml
index f9f130c0f6f9cf62e8b251e5f3027bd1ba54afec..78a7acdb7e3bf746649c3bef10a8bf17534d196c 100644
--- a/tasks/apt.yml
+++ b/tasks/apt.yml
@@ -9,139 +9,278 @@
 # You should have received a copy of the GNU General Public License along with the Webarchitects Icinga Ansible role. If not, see <https://www.gnu.org/licenses/>.
 ---
 # https://icinga.com/docs/icinga2/latest/doc/02-installation/#debianubunturaspbian-repositories
-- name: Icinga Debian apt repo enabled
+- name: Icinga Debian / Ubuntu apt repo configuration
   block:
 
-    - name: Legacy Icinga apt configuration absent
-      ansible.builtin.file:
-        path: "{{ icinga_legacy_apt_path }}"
-        state: absent
-      loop:
-        - /etc/apt/sources.list.d/icinga.list
-        - /usr/share/keyrings/icinga.gpg
-        - /usr/local/share/keyrings/icinga-archive-keyring.gpg
-      loop_control:
-        loop_var: icinga_legacy_apt_path
-
-    - name: Apt Keyrings directory present
-      ansible.builtin.file:
-        path: /etc/apt/keyrings
-        state: directory
-        mode: "0755"
-        owner: root
-        group: root
-
-    - name: Icinga gpg ascii armored key present
-      ansible.builtin.get_url:
-        url: "{{ icinga_gpg_url }}"
-        checksum: "{{ icinga_gpg_checksum }}"
-        dest: /root/icinga.asc
-        mode: "0644"
-        owner: root
-        group: root
-      register: icinga_tmp_asc_file
-
-    - name: Stat Icinga2 gpg ascii armored file
-      ansible.builtin.stat:
-        path: /root/icinga.asc
-      register: icinga_asc_file
+    - name: Python3 Debian present for deb822 module
+      ansible.builtin.apt:
+        pkg: python3-debian
+        state: present
 
-    - name: Check gpg key when it exists
+    - name: Apt GPG configuration for supported Debian and Ubuntu distros
       block:
 
-        - name: Stat Icinga gpg dearmored file
-          ansible.builtin.stat:
-            path: /etc/apt/keyrings/icinga.gpg
-          register: icinga_gpg_file
-
-        - name: Icinga gpg key dearmored
-          ansible.builtin.shell: |-
-            set -e -o pipefail
-            gpg --dearmor < /root/icinga.asc > /etc/apt/keyrings/icinga.gpg
-            chmod 644 /etc/apt/keyrings/icinga.gpg
-          args:
-            executable: "{{ ansible_local.bash.path }}"
-          when: ( icinga_tmp_asc_file.changed | bool ) or ( not icinga_gpg_file.stat.exists | bool )
-
-        - name: Stat Icinga gpg dearmored file
+        - name: "Icinga GPG package present {{ icinga_archive_keyring_deb_url |  ansible.builtin.urlsplit('path') | ansible.builtin.regex_replace('^[/]') }}"
+          ansible.builtin.apt:
+            deb: "{{ icinga_archive_keyring_deb_url }}"
+            state: present
+
+        - name: Stat /usr/share/keyrings/icinga-archive-keyring.gpg
           ansible.builtin.stat:
-            path: /etc/apt/keyrings/icinga.gpg
-          register: icinga_gpg_file
-
-        - name: Debug disto
-          ansible.builtin.debug:
-            var: ansible_distribution
-            verbosity: 2
-
-        - name: Debug disto version
-          ansible.builtin.debug:
-            var: ansible_distribution_version
-            verbosity: 2
-
-        - name: Icinga gpg key check command
-          ansible.builtin.command: >
-            gpg --with-colons
-            {% if ansible_local.gpg.version is version('2.2.12', '<') %}
-            --with-fingerprint --with-subkey-fingerprint
-            {% else %}
-            --show-keys
-            {% endif %}
-            /etc/apt/keyrings/icinga.gpg
-          when: ( icinga_gpg_file.stat.exists | bool )
-          check_mode: false
-          changed_when: false
-          register: icinga_gpg
-
-        - name: Icinga gpg key check first fingerprint on Debian 10 and older
-          ansible.builtin.assert:
-            that:
-              - icinga_fpr in icinga_gpg.stdout
-            quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
-          when:
-            - ansible_loop.first | bool
-            - ansible_distribution == "Debian"
-            - ansible_distribution_version is version('10', '<')
-          loop: "{{ icinga_gpg_fingerprints }}"
-          loop_control:
-            extended: true
-            loop_var: icinga_fpr
+            path: /usr/share/keyrings/icinga-archive-keyring.gpg
+          register: icinga_archive_keyring_pub_key
 
-        - name: Icinga gpg key check first fingerprint on Ubuntu 18.04 and older
+        - name: "The GPG key provided by the Icinga GPG package is required {{ icinga_archive_keyring_deb_url |  ansible.builtin.urlsplit('path') | ansible.builtin.regex_replace('^[/]') }}"
           ansible.builtin.assert:
             that:
-              - icinga_fpr in icinga_gpg.stdout
-            quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
-          when:
-            - ansible_loop.first | bool
-            - ansible_distribution == "Ubuntu"
-            - ansible_distribution_version is version('18.04', '<=')
-          loop: "{{ icinga_gpg_fingerprints }}"
+              - icinga_archive_keyring_pub_key.stat.exists | bool
+            quiet: "{% if ansible_check_mode or ansible_verbosity >= 1 %}false{% else %}true{% endif %}"
+            fail_msg: >-
+              The GPG key provided by {{ icinga_archive_keyring_deb_url }} is required to configure the Icinga apt repo.
+
+        - name: Configure the Icinga apt repo when the GPG public key is present
+          block:
+
+            - name: Stat Icinga repository sources file
+              ansible.builtin.stat:
+                path: /etc/apt/sources.list.d/icinga.sources
+              register: icinga_sources_path
+
+            - name: Read and backup Icinga repository sources file
+              block:
+
+                - name: Slurp /etc/apt/sources.list.d/icinga.sources
+                  ansible.builtin.slurp:
+                    src: /etc/apt/sources.list.d/icinga.sources
+                  register: icinga_sources_contents_b64encoded
+
+                - name: Decode the base64 encoded version of /etc/apt/sources.list.d/icinga.sources
+                  ansible.builtin.set_fact:
+                    icinga_sources_contents: "{{ icinga_sources_contents_b64encoded['content'] | ansible.builtin.b64decode | community.general.jc('ini') }}"
+
+                - name: Print the contents of /etc/apt/sources.list.d/icinga.sources
+                  ansible.builtin.debug:
+                    var: icinga_sources_contents
+                    verbosity: "{% if ansible_check_mode | bool %}0{% else %}1{% endif %}"
+
+                - name: Set a fact for the prior Icinga repository sources file contents
+                  ansible.builtin.set_fact:
+                    icinga_sources_contents_prior: "{{ icinga_sources_contents }}"
+                  when: icinga_sources_contents is defined
+
+                - name: Check Icinga repository sources file present
+                  ansible.builtin.deb822_repository:
+                    allow_downgrade_to_insecure: false
+                    allow_insecure: false
+                    allow_weak: false
+                    architectures: "{{ ansible_facts.ansible_local.dpkg.arch }}"
+                    check_date: true
+                    check_valid_until: true
+                    components: main
+                    enabled: true
+                    name: icinga
+                    pdiffs: true
+                    signed_by: /usr/share/keyrings/icinga-archive-keyring.gpg
+                    suites: "icinga-{{ ansible_facts.distribution_release }}"
+                    types: deb
+                    uris: "https://packages.icinga.com/{{ ansible_distribution | lower }}"
+                  check_mode: true
+                  changed_when: false
+                  register: icinga_sources_check
+
+                - name: Debug proposed icinga_sources_check.repo
+                  ansible.builtin.debug:
+                    var: icinga_sources_check.repo
+                    verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"
+
+                - name: Backup old Icinga sources file
+                  ansible.builtin.command:
+                    cmd: >-
+                      mv
+                      /etc/apt/sources.list.d/icinga.sources
+                      /etc/apt/sources.list.d/.icinga.sources.{{ icinga_date_timestamp }}.ansible.save
+                  args:
+                    creates: "/etc/apt/sources.list.d/.icinga.sources.{{ icinga_date_timestamp }}.ansible.save"
+                    removes: /etc/apt/sources.list.d/icinga.sources
+                  vars:
+                    icinga_date_timestamp: "{{ ansible_facts.date_time.iso8601_basic_short }}"
+                  when: icinga_sources_contents_prior != icinga_sources_check.repo | string | community.general.jc('ini')
+
+              when: icinga_sources_path.stat.exists | bool
+
+            - name: Icinga repository sources file present
+              ansible.builtin.deb822_repository:
+                allow_downgrade_to_insecure: false
+                allow_insecure: false
+                allow_weak: false
+                architectures: "{{ ansible_facts.ansible_local.dpkg.arch }}"
+                check_date: true
+                check_valid_until: true
+                components: main
+                enabled: true
+                name: icinga
+                pdiffs: true
+                signed_by: /usr/share/keyrings/icinga-archive-keyring.gpg
+                suites: "icinga-{{ ansible_facts.distribution_release }}"
+                types: deb
+                uris: "https://packages.icinga.com/{{ ansible_distribution | lower }}"
+              register: icinga_sources
+
+          when: icinga_archive_keyring_pub_key.stat.exists | bool
+
+        - name: Legacy Icinga apt configuration absent
+          ansible.builtin.file:
+            path: "{{ icinga_legacy_apt_path }}"
+            state: absent
+          loop:
+            - /etc/apt/keyrings/icinga.gpg
+            - /etc/apt/sources.list.d/icinga.list
+            - /usr/local/share/keyrings/icinga-archive-keyring.gpg
+            - /usr/share/keyrings/icinga.gpg
           loop_control:
-            extended: true
-            loop_var: icinga_fpr
+            loop_var: icinga_legacy_apt_path
 
-        - name: Icinga gpg key check all fingerprints
-          ansible.builtin.assert:
-            that:
-              - icinga_fpr in icinga_gpg.stdout
-            quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
-          when: >
-            ( ( ansible_distribution == "Debian" ) and ( ansible_distribution_version is version('10', '>=') ) ) or
-            ( ( ansible_distribution == "Ubuntu" ) and ( ansible_distribution_version is version('18.04', '>') ) )
-          loop: "{{ icinga_gpg_fingerprints }}"
+      when: ansible_facts.distribution_release in icinga_distros
+
+    - name: Apt GPG configuration for unsupported Debian and Ubuntu distros
+      block:
+
+        - name: EOL Distribution Versions
+          ansible.builtin.fail:
+            msg: "TODO see Required Actions for Users of EOL Distribution Versions https://icinga.com/blog/2024/08/26/icinga-package-repository-key-rotation-2024/"
+
+        - name: Legacy Icinga apt configuration absent
+          ansible.builtin.file:
+            path: "{{ icinga_legacy_apt_path }}"
+            state: absent
+          loop:
+            - /etc/apt/sources.list.d/icinga.list
+            - /usr/share/keyrings/icinga.gpg
+            - /usr/local/share/keyrings/icinga-archive-keyring.gpg
           loop_control:
-            loop_var: icinga_fpr
+            loop_var: icinga_legacy_apt_path
 
-      when: icinga_asc_file.stat.exists | bool
+        - name: Apt Keyrings directory present
+          ansible.builtin.file:
+            path: /etc/apt/keyrings
+            state: directory
+            mode: "0755"
+            owner: root
+            group: root
 
-    - name: Icinga repo apt sources file present
-      ansible.builtin.template:
-        src: icinga.sources.j2
-        dest: /etc/apt/sources.list.d/icinga.sources
-        mode: "0644"
-        owner: root
-        group: root
-      register: icinga_sources
+        - name: Icinga gpg ascii armored key present
+          ansible.builtin.get_url:
+            url: "{{ icinga_gpg_url }}"
+            checksum: "{{ icinga_gpg_checksum }}"
+            dest: /root/icinga.asc
+            mode: "0644"
+            owner: root
+            group: root
+          register: icinga_tmp_asc_file
+
+        - name: Stat Icinga2 gpg ascii armored file
+          ansible.builtin.stat:
+            path: /root/icinga.asc
+          register: icinga_asc_file
+
+        - name: Check gpg key when it exists
+          block:
+
+            - name: Stat Icinga gpg dearmored file
+              ansible.builtin.stat:
+                path: /etc/apt/keyrings/icinga.gpg
+              register: icinga_gpg_file
+
+            - name: Icinga gpg key dearmored
+              ansible.builtin.shell: |-
+                set -e -o pipefail
+                gpg --dearmor < /root/icinga.asc > /etc/apt/keyrings/icinga.gpg
+                chmod 644 /etc/apt/keyrings/icinga.gpg
+              args:
+                executable: "{{ ansible_local.bash.path }}"
+              when: ( icinga_tmp_asc_file.changed | bool ) or ( not icinga_gpg_file.stat.exists | bool )
+
+            - name: Stat Icinga gpg dearmored file
+              ansible.builtin.stat:
+                path: /etc/apt/keyrings/icinga.gpg
+              register: icinga_gpg_file
+
+            - name: Debug disto
+              ansible.builtin.debug:
+                var: ansible_distribution
+                verbosity: 2
+
+            - name: Debug disto version
+              ansible.builtin.debug:
+                var: ansible_distribution_version
+                verbosity: 2
+
+            - name: Icinga gpg key check command
+              ansible.builtin.command: >
+                gpg --with-colons
+                {% if ansible_local.gpg.version is version('2.2.12', '<') %}
+                --with-fingerprint --with-subkey-fingerprint
+                {% else %}
+                --show-keys
+                {% endif %}
+                /etc/apt/keyrings/icinga.gpg
+              when: ( icinga_gpg_file.stat.exists | bool )
+              check_mode: false
+              changed_when: false
+              register: icinga_gpg
+
+            - name: Icinga gpg key check first fingerprint on Debian 10 and older
+              ansible.builtin.assert:
+                that:
+                  - icinga_fpr in icinga_gpg.stdout
+                quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
+              when:
+                - ansible_loop.first | bool
+                - ansible_distribution == "Debian"
+                - ansible_distribution_version is version('10', '<')
+              loop: "{{ icinga_gpg_fingerprints }}"
+              loop_control:
+                extended: true
+                loop_var: icinga_fpr
+
+            - name: Icinga gpg key check first fingerprint on Ubuntu 18.04 and older
+              ansible.builtin.assert:
+                that:
+                  - icinga_fpr in icinga_gpg.stdout
+                quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
+              when:
+                - ansible_loop.first | bool
+                - ansible_distribution == "Ubuntu"
+                - ansible_distribution_version is version('18.04', '<=')
+              loop: "{{ icinga_gpg_fingerprints }}"
+              loop_control:
+                extended: true
+                loop_var: icinga_fpr
+
+            - name: Icinga gpg key check all fingerprints
+              ansible.builtin.assert:
+                that:
+                  - icinga_fpr in icinga_gpg.stdout
+                quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
+              when: >
+                ( ( ansible_distribution == "Debian" ) and ( ansible_distribution_version is version('10', '>=') ) ) or
+                ( ( ansible_distribution == "Ubuntu" ) and ( ansible_distribution_version is version('18.04', '>') ) )
+              loop: "{{ icinga_gpg_fingerprints }}"
+              loop_control:
+                loop_var: icinga_fpr
+
+          when: icinga_asc_file.stat.exists | bool
+
+        - name: Icinga repo apt sources file present
+          ansible.builtin.template:
+            src: icinga.sources.j2
+            dest: /etc/apt/sources.list.d/icinga.sources
+            mode: "0644"
+            owner: root
+            group: root
+          register: icinga_sources
+
+      when: ansible_facts.distribution_release not in icinga_distros
 
     - name: Icinga apt prefs file present
       ansible.builtin.template:
diff --git a/tasks/install.yml b/tasks/install.yml
index 287189aa6e33ef69715765e508725d9e6bcb7143..e9534acceab8cc9bd9550fa8e07d811def5e28ed 100644
--- a/tasks/install.yml
+++ b/tasks/install.yml
@@ -45,7 +45,7 @@
         pkg:
           - monitoring-plugins-systemd
         state: present
-      when: ansible_distribution_release is regex('^bookworm|trixie|jessie$')
+      when: ansible_distribution_release is regex('^bookworm|jessie|noble|trixie$')
 
     - name: Check if /usr/lib/nagios/plugins/check_systemd exists
       ansible.builtin.stat:
@@ -78,6 +78,7 @@
     - name: Icinga package present from packages.icinga.com
       ansible.builtin.apt:
         pkg:
+          - icinga-archive-keyring
           - icinga2
           - icinga2-bin
           - icinga2-common
diff --git a/vars/main.yml b/vars/main.yml
index 73296f67f31ec1e6e7f9c040946ba4bbe72f434b..c8ae682513c54348f028236f90cd2a8b98476a52 100644
--- a/vars/main.yml
+++ b/vars/main.yml
@@ -12,6 +12,18 @@
 icingavarnames: "{{ q('varnames', '^icinga_') | sort }}"
 icingahostvars: "{{ dict(icingavarnames | list | zip(q('vars', *icingavarnames))) }}"
 
+# Icinga distros
+# https://icinga.com/subscriptions/support-matrix/
+icinga_distros:
+  - bookworm
+  - bullseye
+  - focal
+  - jammy
+  - noble
+# https://packages.icinga.com/debian/README.html
+# https://packages.icinga.com/ubuntu/README.html
+icinga_archive_keyring_deb_url: "https://packages.icinga.com/icinga-archive-keyring_latest+{{ ansible_facts.distribution | lower }}{{ ansible_facts.distribution_major_version }}.deb"
+
 # JMESPath query to check existing IPv4 rule
 icinga_iptables_ipv4_query: "[?chain == 'INPUT'].rules | [0] | [?source == '{{ icinga_master_node }}'] | [0] | options"