diff --git a/.yamllint b/.yamllint
index 7c0f15cf782b192e2b80d4eadb9dcbf92b4553bf..8d489a5cb564ae9d7dad9860acb4c39613467d2c 100644
--- a/.yamllint
+++ b/.yamllint
@@ -1,7 +1,5 @@
 ---
-# based on documentation available at
-# https://yamllint.readthedocs.io/en/stable/rules.html
-
+# Based on ansible-lint config
 extends: default
 
 rules:
@@ -11,13 +9,29 @@ rules:
   brackets:
     max-spaces-inside: 1
     level: error
+  colons:
+    max-spaces-after: -1
+    level: error
+  commas:
+    max-spaces-after: -1
+    level: error
   comments:
-    min-spaces-from-content: 4
+    min-spaces-from-content: 1 # prettier compatibility
   comments-indentation: disable
-  document-end: disable
-  document-start:
-    level: warning
-  octal-values:
-    forbid-explicit-octal: false
+  document-start: disable
+  empty-lines:
+    max: 3
+    level: error
+  hyphens:
+    level: error
+  indentation: disable
+  key-duplicates: enable
   line-length: disable
-  truthy: enable
+  new-line-at-end-of-file: disable
+  new-lines:
+    type: unix
+  octal-values:
+    forbid-implicit-octal: true    # yamllint defaults to false
+    forbid-explicit-octal: true    # yamllint defaults to false
+  trailing-spaces: disable
+  truthy: disable
diff --git a/molecule/resources/playbooks/converge.yml b/molecule/resources/playbooks/converge.yml
index e311775851ec52158a32b8d58950982168666c1b..c2d7deafbbc804739c275600ee711132d7bbd5f0 100644
--- a/molecule/resources/playbooks/converge.yml
+++ b/molecule/resources/playbooks/converge.yml
@@ -9,7 +9,7 @@
       become: true
       when: ansible_os_family == "Debian"
     - name: update yum cache
-      ansible.builtin.yum:
+      ansible.builtin.dnf:
         update_cache: true
       become: true
       when: ansible_os_family == "RedHat"
diff --git a/molecule/virtualbox_centos7/molecule.yml b/molecule/virtualbox_alma8/molecule.yml
similarity index 85%
rename from molecule/virtualbox_centos7/molecule.yml
rename to molecule/virtualbox_alma8/molecule.yml
index 3bc6b4a6f0a8d2eca171e9b173da7046f1172c0c..f11ab876a0f0c3b947409a34fc10876170a32b19 100644
--- a/molecule/virtualbox_centos7/molecule.yml
+++ b/molecule/virtualbox_alma8/molecule.yml
@@ -4,16 +4,12 @@ dependency:
   enabled: false
 driver:
   name: vagrant
-lint: |
-  set -e
-  yamllint .
-  ansible-lint -x no-loop-var-prefix,command-instead-of-module,package-latest
 platforms:
   # Check out the documentation at
   # https://github.com/ansible-community/molecule-vagrant#documentation
   # for more platform parameters.
   - name: vm-runner
-    box: centos/7
+    box: almalinux/8
     memory: 1024
     # List of raw Vagrant `config` options.
     # provider_raw_config_args:
@@ -29,7 +25,7 @@ provisioner:
     defaults:
       # https://stackoverflow.com/questions/57435811/ansible-molecule-pass-multiple-vault-ids
       # vault_identity_list: "@$HOME/.ansible/roles/lza_install_common.pass, @$HOME/.ansible/roles/passfile_1.pass"
-      vault_identity_list: "../lza_install_common.pass"
+      vault_identity_list: "../../../lza_install_common.pass"
   vvv: false
   playbooks:
     # create: ../resources/playbooks/create.yml
diff --git a/molecule/virtualbox_rocky8/molecule.yml b/molecule/virtualbox_rocky8/molecule.yml
deleted file mode 100644
index ca7f4479e7c2ed85af6f3d1229e997ea03948ea0..0000000000000000000000000000000000000000
--- a/molecule/virtualbox_rocky8/molecule.yml
+++ /dev/null
@@ -1,41 +0,0 @@
----
-dependency:
-  name: galaxy
-  enabled: false
-driver:
-  name: vagrant
-lint: |
-  set -e
-  yamllint .
-  ansible-lint -x no-loop-var-prefix,command-instead-of-module,package-latest
-platforms:
-  # Check out the documentation at
-  # https://github.com/ansible-community/molecule-vagrant#documentation
-  # for more platform parameters.
-  - name: vm-runner
-    box: rockylinux/8
-    memory: 1024
-    # List of raw Vagrant `config` options.
-    # provider_raw_config_args:
-    #   - "customize [ 'modifyvm', :id, '--natdnshostresolver1', 'on' ]"
-    # Dictionary of `config` options.
-    config_options:
-      ssh.keep_alive: true
-      ssh.remote_user: "'lza'"
-provisioner:
-  name: ansible
-  log: true
-  config_options:
-    defaults:
-      # https://stackoverflow.com/questions/57435811/ansible-molecule-pass-multiple-vault-ids
-      # vault_identity_list: "@$HOME/.ansible/roles/lza_install_common.pass, @$HOME/.ansible/roles/passfile_1.pass"
-      vault_identity_list: "../lza_install_common.pass"
-  vvv: false
-  playbooks:
-    # create: ../resources/playbooks/create.yml
-    # destroy: ../resources/playbooks/destroy.yml
-    converge: ../resources/playbooks/converge.yml
-    # prepare: ../resources/playbooks/prepare.yml
-    verify: ../resources/playbooks/verify.yml
-verifier:
-  name: ansible
diff --git a/tasks/configure_autoupdate.yml b/tasks/configure_autoupdate.yml
index 834cdb746d73694399cef0b67628e667a276e114..fcfca2c22f110447a7e1f1047e3ab373c386a766 100644
--- a/tasks/configure_autoupdate.yml
+++ b/tasks/configure_autoupdate.yml
@@ -67,22 +67,30 @@
           line: 'Unattended-Upgrade::Remove-Unused-Dependencies "false";'
 
 # based on: https://access.redhat.com/solutions/2823901
+# based on: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-software-packages_configuring-basic-system-settings#automating-software-updates_updating-software-packages
 - name: Install & configurate autoupdate (RedHat)
   when: ansible_os_family == "RedHat"
   block:
     - name: include vars yum-cron.yml
       ansible.builtin.include_vars: "yum-cron.yml"
 
+    - name: purge yum-cron
+      ansible.builtin.dnf:
+        name: "yum-cron"
+        state: absent
+    - name: remove config file for yum-cron, as it's not used any more from RHEL 8 onwards
+      ansible.builtin.file:
+        path: "/etc/yum/yum-cron.conf"
+        state: absent
+
     - name: Install autoupdate packages (RedHat)
-      ansible.builtin.yum:
-        name: [
-          'yum-cron'
-        ]
+      ansible.builtin.dnf:
+        name: 'dnf-automatic'
         state: present
-    - name: configure yum-cron
+    - name: configure dnf-automatic
       ansible.builtin.template:
-        src: "etc/yum/yum-cron.conf.j2"
-        dest: "/etc/yum/yum-cron.conf"
+        src: "etc/dnf/automatic.conf.j2"
+        dest: "/etc/dnf/automatic.conf"
         owner: "root"
         group: "root"
         mode: "0644"
diff --git a/tasks/configure_package_repositories.yml b/tasks/configure_package_repositories.yml
index 04f7e8ccd5a576e0850576cbbb6e0dd35a717ded..5f2b0b4f7040606f2e869c99edb0298eba36cb5d 100644
--- a/tasks/configure_package_repositories.yml
+++ b/tasks/configure_package_repositories.yml
@@ -39,29 +39,35 @@
         install packages from the newly configured repo)
       ansible.builtin.meta: flush_handlers
 
-- name: add custom repositories
-  when: ansible_os_family == "RedHat"
-  ansible.builtin.yum_repository:
-    name: "{{ item.name }}"
-    description: "{{ item.description }}"
-    baseurl: "{{ item.baseurl }}"
-    gpgcheck: "{{ item.gpgcheck | default('true') }}"
-    gpgkey: "{{ item.gpgkey | default(omit) }}"
-  loop:
-    - name: "epel"
-      description: EPEL YUM repo
-      baseurl: "https://download.fedoraproject.org/pub/epel/{{ ansible_distribution_major_version }}/x86_64/"
-      gpgkey: "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-{{ ansible_distribution_major_version }}"
-    - name: "slub"
-      description: SLUB YUM repo
-      baseurl: "https://sdvrhelrepo.slub-dresden.de/"
-      gpgcheck: "false"
-  notify: update package cache
-
-- name: >
-    remove legacy repo configuration to avoid double configuration for SLUB repo
-  ansible.builtin.file:
-    path: "/etc/yum.repos.d/SLUB.repo"
-    state: absent
-  when: ansible_os_family == "RedHat"
+- name: configure RHEL repositories
+  when:
+    - ansible_os_family == "RedHat"
+    - "ansible_distribution_major_version is version('8', '==')"
   notify: update package cache
+  block:
+    - name: add SLUB DNF repo
+      ansible.builtin.yum_repository:
+        name: "{{ item.name }}"
+        description: "{{ item.description }}"
+        baseurl: "{{ item.baseurl }}"
+        gpgcheck: "{{ item.gpgcheck | default('true') }}"
+        gpgkey: "{{ item.gpgkey | default(omit) }}"
+      loop:
+        - name: "slub"
+          description: SLUB DNF repo
+          baseurl: "https://sdvrhelrepo.slub-dresden.de/"
+          gpgcheck: "false"
+    # https://docs.fedoraproject.org/en-US/epel/getting-started/#_rhel_8
+#    - name: enable powertools repo in dnf config-manager to install EPEL
+#      community.general.dnf_config_manager:
+#        name: [ "powertools" ]
+    - name: install EPEL-release
+      ansible.builtin.dnf:
+        name: "epel-release"
+#        name: "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm"
+        disable_gpg_check: true
+    - name: >
+        remove legacy repo configuration to avoid double configuration for SLUB repo
+      ansible.builtin.file:
+        path: "/etc/yum.repos.d/SLUB.repo"
+        state: absent
diff --git a/tasks/install_packages.yml b/tasks/install_packages.yml
index d637e6317a1c8b747ad9003fc63f5834c6831a54..3ff8cd4d9a29f333ac8550b4ddc88f6aef7d6de0 100644
--- a/tasks/install_packages.yml
+++ b/tasks/install_packages.yml
@@ -5,17 +5,18 @@
     update_cache: true
   when: ansible_os_family == "Debian"
 
-# Äquivalent von yum update
+# Äquivalent von dnf update
 - name: update packages (RedHat)
   when: ansible_os_family == "RedHat"
   block:
-    - name: yum update
-      ansible.builtin.yum:
+    - name: dnf update
+      ansible.builtin.dnf:
         update_cache: true
-        name: '*'
+#        name: '*'
         state: present
-    - name: yum autoremove
-      ansible.builtin.yum:
+        disable_gpg_check: true
+    - name: dnf autoremove
+      ansible.builtin.dnf:
         autoremove: true
 
 - name: uninstall packages
@@ -55,7 +56,6 @@
       'net-tools',
       'nload',
       'nmon',
-      'ntp',
       'parted',
       'psmisc',
       'pv',
@@ -108,7 +108,7 @@
 
 # Installation RedHat-spezifische Pakete
 - name: Installation RedHat-spezifische Pakete
-  ansible.builtin.yum:
+  ansible.builtin.dnf:
     name: [
       'bind-utils',
       'csh',
@@ -117,11 +117,9 @@
       'iputils',
       'kernel-doc',
       'libcgroup-tools',
-      'libselinux-python',
       'libselinux-python3',
       'lvm2',
       'lzip',
-      'lziprecover',
       'neovim',
       'nfs-utils',
       'perf',
@@ -137,7 +135,7 @@
       'vim-enhanced',
       'vim-filesystem',
       'vim-trailing-whitespace',
-      'yum-utils'
+      'dnf-utils'
     ]
     state: present
   environment:
diff --git a/tasks/main.yml b/tasks/main.yml
index 895b16326891cae92b67ff8401ec4d53709b0544..1212bfeb5cf51f87de65e7421927521ea701147f 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -25,7 +25,7 @@
 
 - name: SLUB-lokales Debian-Repository hinzufügen
   ansible.builtin.import_tasks: "configure_package_repositories.yml"
-  tags: [apt, yum, packages]
+  tags: [apt, dnf, packages]
 
 - name: NTP-Client
   ansible.builtin.import_tasks: "migrate_ntpd_to_esxi_timesync.yml"
@@ -36,7 +36,7 @@
 
 - name: Systempakete installieren
   ansible.builtin.import_tasks: "install_packages.yml"
-  tags: [apt, yum, packages]
+  tags: [apt, dnf, packages]
 
 - name: HotAdd-Scripte für VMware installieren
   ansible.builtin.import_tasks: "install_hotadd_scripts.yml"
@@ -53,7 +53,7 @@
 
 - name: Autoupdate konfigurieren
   ansible.builtin.import_tasks: "configure_autoupdate.yml"
-  tags: [apt, yum, packages]
+  tags: [apt, dnf, packages]
 
 - name: Konfigurationsdateien einspielen - SSH-Login
   ansible.builtin.import_tasks: "configure_ssh_login.yml"
diff --git a/templates/etc/dnf/automatic.conf.j2 b/templates/etc/dnf/automatic.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..9d67b08f03fcbd0ac4db299a0560771a8f8a39d7
--- /dev/null
+++ b/templates/etc/dnf/automatic.conf.j2
@@ -0,0 +1,89 @@
+[commands]
+#  What kind of upgrade to perform:
+# default                            = all available upgrades
+# security                           = only the security upgrades
+upgrade_type = default
+random_sleep = 0
+
+# Maximum time in seconds to wait until the system is on-line and able to
+# connect to remote repositories.
+network_online_timeout = 60
+
+# To just receive updates use dnf-automatic-notifyonly.timer
+
+# Whether updates should be downloaded when they are available, by
+# dnf-automatic.timer. notifyonly.timer, download.timer and
+# install.timer override this setting.
+download_updates = yes
+
+# Whether updates should be applied when they are available, by
+# dnf-automatic.timer. notifyonly.timer, download.timer and
+# install.timer override this setting.
+# apply_updates = no    # DEFAULT
+apply_updates = yes
+
+
+[emitters]
+# Name to use for this system in messages that are emitted.  Default is the
+# hostname.
+# system_name = my-host
+
+# How to send messages.  Valid options are stdio, email and motd.  If
+# emit_via includes stdio, messages will be sent to stdout; this is useful
+# to have cron send the messages.  If emit_via includes email, this
+# program will send email itself according to the configured options.
+# If emit_via includes motd, /etc/motd file will have the messages. if
+# emit_via includes command_email, then messages will be send via a shell
+# command compatible with sendmail.
+# Default is email,stdio.
+# If emit_via is None or left blank, no messages will be sent.
+# emit_via = email    # DEFAULT
+emit_via = email
+
+
+[email]
+# The address to send email messages from.
+# email_from = root@example.com    # DEFAULT
+email_from = {{ ansible_hostname }}@slub-dresden.de
+
+# List of addresses to send messages to.
+email_to = root
+
+# Name of the host to connect to to send email messages.
+email_host = localhost
+
+
+[command]
+# The shell command to execute. This is a Python format string, as used in
+# str.format(). The format function will pass a shell-quoted argument called
+# `body`.
+# command_format = "cat"
+
+# The contents of stdin to pass to the command. It is a format string with the
+# same arguments as `command_format`.
+# stdin_format = "{body}"
+
+
+[command_email]
+# The shell command to use to send email. This is a Python format string,
+# as used in str.format(). The format function will pass shell-quoted arguments
+# called body, subject, email_from, email_to.
+# command_format = "mail -Ssendwait -s {subject} -r {email_from} {email_to}"
+
+# The contents of stdin to pass to the command. It is a format string with the
+# same arguments as `command_format`.
+# stdin_format = "{body}"
+
+# The address to send email messages from.
+# email_from = root@example.com    # DEFAULT
+email_from = {{ ansible_hostname }}@slub-dresden.de
+
+# List of addresses to send messages to.
+email_to = root
+
+
+[base]
+# This section overrides dnf.conf
+
+# Use this to filter DNF core messages
+debuglevel = 1
diff --git a/templates/etc/yum/yum-cron.conf.j2 b/templates/etc/yum/yum-cron.conf.j2
deleted file mode 100644
index c062e64d6683271aa49cc6f157bb5ebace44d053..0000000000000000000000000000000000000000
--- a/templates/etc/yum/yum-cron.conf.j2
+++ /dev/null
@@ -1,81 +0,0 @@
-[commands]
-#  What kind of update to use:
-# default                            = yum upgrade
-# security                           = yum --security upgrade
-# security-severity:Critical         = yum --sec-severity=Critical upgrade
-# minimal                            = yum --bugfix update-minimal
-# minimal-security                   = yum --security update-minimal
-# minimal-security-severity:Critical =  --sec-severity=Critical update-minimal
-update_cmd = {{ update_cmd }}
-
-# Whether a message should be emitted when updates are available,
-# were downloaded, or applied.
-update_messages = {{ update_messages }}
-
-# Whether updates should be downloaded when they are available.
-download_updates = {{ download_updates  }}
-
-# Whether updates should be applied when they are available.  Note
-# that download_updates must also be yes for the update to be applied.
-apply_updates = {{ apply_updates }}
-
-# Maximum amout of time to randomly sleep, in minutes.  The program
-# will sleep for a random amount of time between 0 and random_sleep
-# minutes before running.  This is useful for e.g. staggering the
-# times that multiple systems will access update servers.  If
-# random_sleep is 0 or negative, the program will run immediately.
-# 6*60 = 360
-random_sleep = {{ random_sleep }}
-
-
-[emitters]
-# Name to use for this system in messages that are emitted.  If
-# system_name is None, the hostname will be used.
-system_name = None
-
-# How to send messages.  Valid options are stdio and email.  If
-# emit_via includes stdio, messages will be sent to stdout; this is useful
-# to have cron send the messages.  If emit_via includes email, this
-# program will send email itself according to the configured options.
-# If emit_via is None or left blank, no messages will be sent.
-emit_via = stdio
-
-# The width, in characters, that messages that are emitted should be
-# formatted to.
-output_width = 80
-
-
-[email]
-# The address to send email messages from.
-# NOTE: 'localhost' will be replaced with the value of system_name.
-email_from = root@localhost
-
-# List of addresses to send messages to.
-email_to = root
-
-# Name of the host to connect to to send email messages.
-email_host = localhost
-
-
-[groups]
-# NOTE: This only works when group_command != objects, which is now the default
-# List of groups to update
-group_list = None
-
-# The types of group packages to install
-group_package_types = mandatory, default
-
-[base]
-# This section overrides yum.conf
-
-# Use this to filter Yum core messages
-# -4: critical
-# -3: critical+errors
-# -2: critical+errors+warnings (default)
-debuglevel = -2
-
-# skip_broken = True
-mdpolicy = group:main
-
-# Uncomment to auto-import new gpg keys (dangerous)
-# assumeyes = True