diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 40a76ec34a783515a03f773d3b0aeb34f002b088..2dc098c2ac47385da009120a3307968100c0383b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -33,15 +33,15 @@ ci-test-image:
       - Dockerfile
       - requirements.txt
       - .gitlab/ci_templates/kaniko.yml
+  script:
+    - *debug_information
   extends:
     - .kaniko_build
-    - .debug_information
 
 create-vps:
   stage: create-vps
   script:
-    - echo "hostname $HOSTNAME, subdomain $SUBDOMAIN, domain $DOMAIN, FQDN $FQDN";
-    - ls clusters/${HOSTNAME} || echo "directory clusters/${HOSTNAME} not found"
+    - *debug_information
     # Creates the VPS only if an old VPS for this branch is not re-usable
     - sh .gitlab/ci_scripts/create_vps.sh
   artifacts:
@@ -59,7 +59,6 @@ create-vps:
       - openappstack/**/*
   extends:
     - .ssh_setup
-    - .debug_information
   # Cache the cluster secrets so the next job can use it too
   cache:
     paths:
@@ -69,6 +68,7 @@ create-vps:
 setup-openappstack:
   stage: setup-cluster
   script:
+    - *debug_information
     # Copy inventory files to ansible folder for use in install-apps step
     - chmod 700 ansible
     - cp clusters/${CI_COMMIT_REF_SLUG}/inventory.yml ansible/
@@ -94,7 +94,6 @@ setup-openappstack:
       - openappstack/**/*
   extends:
     - .ssh_setup
-    - .debug_information
   # Cache the cluster secrets so the next job can use them
   cache:
     paths:
@@ -104,6 +103,7 @@ setup-openappstack:
 test-helmreleases:
   stage: wait-for-deployments
   script:
+    - *debug_information
     - cd ansible/
     - export KUBECONFIG="${PWD}/../clusters/${HOSTNAME}/secrets/kube_config_cluster.yml"
     - pytest -v -s -m 'helmreleases' --connection=ansible --ansible-inventory=${CLUSTER_DIR}/inventory.yml --hosts='ansible://*' --reruns 120 --reruns-delay 10
@@ -117,11 +117,11 @@ test-helmreleases:
       - openappstack/**/*
   extends:
     - .ssh_setup
-    - .debug_information
 
 testinfra:
   stage: health-test
   script:
+    - *debug_information
     - cd ansible/
     - pytest -v -m 'testinfra' --connection=ansible --ansible-inventory=${CLUSTER_DIR}/inventory.yml --hosts='ansible://*'
   only:
@@ -133,12 +133,12 @@ testinfra:
       - openappstack/**/*
   extends:
     - .ssh_setup
-    - .debug_information
 
 certs:
   stage: health-test
   allow_failure: true
   script:
+    - *debug_information
     - cd ansible/
     - pytest -s -m 'certs' --connection=ansible --ansible-inventory=${CLUSTER_DIR}/inventory.yml --hosts='ansible://*'
   only:
@@ -150,12 +150,12 @@ certs:
       - openappstack/**/*
   extends:
     - .ssh_setup
-    - .debug_information
 
 prometheus-alerts:
   stage: health-test
   allow_failure: true
   script:
+    - *debug_information
     - cd test/
     - pytest -s -m 'prometheus' --connection=ansible --ansible-inventory=${CLUSTER_DIR}/inventory.yml --hosts='ansible://*'
   only:
@@ -166,11 +166,11 @@ prometheus-alerts:
       - test/**/*
   extends:
     - .ssh_setup
-    - .debug_information
 
 behave-nextcloud:
   stage: integration-test
   script:
+    - *debug_information
     # Run the behave tests for NextCloud.
     - python3 -m openappstack $HOSTNAME test --behave-headless --behave-tags nextcloud || python3 -m openappstack $HOSTNAME test --behave-headless --behave-rerun-failing --behave-tags nextcloud
   artifacts:
@@ -188,11 +188,11 @@ behave-nextcloud:
       - openappstack/**/*
   extends:
     - .ssh_setup
-    - .debug_information
 
 behave-wordpress:
   stage: integration-test
   script:
+    - *debug_information
     # Run behave tests against wordpress
     - python3 -m openappstack $HOSTNAME test --behave-headless --behave-tags wordpress || python3 -m openappstack $HOSTNAME test --behave-headless --behave-rerun-failing --behave-tags wordpress
   artifacts:
@@ -213,6 +213,7 @@ behave-wordpress:
 behave-rocketchat:
   stage: integration-test
   script:
+    - *debug_information
     # Run behave tests against Rocket.Chat
     - python3 -m openappstack $HOSTNAME test --behave-headless --behave-tags rocketchat || python3 -m openappstack $HOSTNAME test --behave-headless --behave-rerun-failing --behave-tags rocketchat
   artifacts:
@@ -233,6 +234,7 @@ behave-rocketchat:
 behave-grafana:
   stage: integration-test
   script:
+    - *debug_information
     # Run behave tests against Grafana
     - python3 -m openappstack $HOSTNAME test --behave-headless --behave-tags grafana || python3 -m openappstack $HOSTNAME test --behave-headless --behave-rerun-failing --behave-tags grafana
   artifacts:
@@ -248,8 +250,6 @@ behave-grafana:
       - test/**/*
       - openappstack/**/*
   extends: .ssh_setup
-  extends:
-    - .debug_information
 
 terminate-mr-droplet-after-merge:
   stage: cleanup
@@ -257,26 +257,27 @@ terminate-mr-droplet-after-merge:
     - echo "We leave MR droplets running even when the pipeline is successful \
       to be able to investigate a MR. We need to terminate them when the MR \
       is merged into master."
-  script: |
-    if [ "$(git show -s --pretty=%p HEAD | wc -w)" -gt 1 ]
-    then
-      commit_message="$(git show -s --format=%s)"
-      tmp="${commit_message#*\'}"
-      merged_branch="${tmp%%\'*}"
-      echo "Current HEAD is a merge commit, removing droplet from related merge request branch name '#${merged_branch}'."
-      python3 -c "import greenhost_cloud; greenhost_cloud.terminate_droplets_by_name(\"^${merged_branch}\.\")"
-    else
-      echo "Current HEAD is NOT a merge commit, nothing to do."
-    fi
+  script:
+    - *debug_information
+    - |
+      if [ "$(git show -s --pretty=%p HEAD | wc -w)" -gt 1 ]
+      then
+        commit_message="$(git show -s --format=%s)"
+        tmp="${commit_message#*\'}"
+        merged_branch="${tmp%%\'*}"
+        echo "Current HEAD is a merge commit, removing droplet from related merge request branch name '#${merged_branch}'."
+        python3 -c "import greenhost_cloud; greenhost_cloud.terminate_droplets_by_name(\"^${merged_branch}\.\")"
+      else
+        echo "Current HEAD is NOT a merge commit, nothing to do."
+      fi
   only:
     refs:
       - master
-  extends:
-    - .debug_information
 
 terminate-old-droplets:
   stage: cleanup
   script:
+    - *debug_information
     - echo "Terminate droplets 5 days after creation. Branches that exist longer than 5 days will get a new droplet when CI runs again."
     - python3 -c "import greenhost_cloud; greenhost_cloud.terminate_droplets_by_name('\d+-.*', 5)"
   only:
@@ -286,8 +287,6 @@ terminate-old-droplets:
       - flux/**/*
       - test/**/*
       - openappstack/**/*
-  extends:
-    - .debug_information
 
 # We need one job that run every time (without any `only:` limitation).
 # This works around a Gitlab bug: if no job runs at all due to
@@ -296,6 +295,5 @@ terminate-old-droplets:
 gitlab-merge-workaround:
   stage: cleanup
   script:
+    - *debug_information
     - echo "That went well"
-  extends:
-    - .debug_information
diff --git a/.gitlab/ci_templates/debug_information.yml b/.gitlab/ci_templates/debug_information.yml
index 5d96750c5960ac7ad5fca52ec9edb822cdd48ec1..c8e89aff01746ab02f5e7364061b75ec5aef1e8f 100644
--- a/.gitlab/ci_templates/debug_information.yml
+++ b/.gitlab/ci_templates/debug_information.yml
@@ -1,5 +1,9 @@
-.debug_information:
-  before_script:
+# We don't use a `before_script` definition here because `extend` doesn't merge
+# `before_script` but rather overwrites it.
+# So we rather use [yaml anchors for script](https://docs.gitlab.com/ce/ci/yaml/README.html#yaml-anchors-for-script)
+# here.
+
+.debug_information: &debug_information
   - |
     echo "Env vars:"
     echo
@@ -12,4 +16,6 @@
     echo "KANIKO_BUILD_IMAGENAME:    $KANIKO_BUILD_IMAGENAME"
     echo "SSH_KEY_ID:                $SSH_KEY_ID"
     echo
-    [ -d $CLUSTER_DIR ] && find $CLUSTER_DIR
+    [ -d $CLUSTER_DIR ] && find $CLUSTER_DIR || echo "directory ${CLUSTER_DIR} not found"
+    echo
+    echo