diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5dbf3a8dd3b95d49850859a3a4cfc680d154a152..8912b39d17c54a5df0b851c59b10d1bed9ce8fc4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,6 @@
 ---
 include:
-  - local: 'images/**/.gitlab-ci.yaml'
+  - local: 'images/.utils/gitlab-ci.yaml'
   - local: 'charts/**/.gitlab-ci.yaml'
 stages:
   - release
diff --git a/images/dovecot/.gitlab-ci.yaml b/images/.utils/gitlab-ci.yaml
similarity index 62%
rename from images/dovecot/.gitlab-ci.yaml
rename to images/.utils/gitlab-ci.yaml
index 3035ad642805d5bfe90003c7455e44179caed144..6c0537c39c077c30ca4b719982f5ad95d20c999c 100644
--- a/images/dovecot/.gitlab-ci.yaml
+++ b/images/.utils/gitlab-ci.yaml
@@ -1,45 +1,56 @@
-dovecot-container-build:
+.container-matrix:
+  parallel:
+    matrix:
+      - IMAGE:
+          - dovecot
+          - postfix
+
+
+container-build:
   stage: build
   image: quay.io/sheogorath/build-ah-engine:2.0.0
+  extends: .container-matrix
   before_script:
     - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
     - |
-      cd images/dovecot
+      cd images/${IMAGE}
       source .release
       podman build --pull \
-      --label "org.opencontainers.image.source=$CI_PROJECT_URL/-/tree/$CI_COMMIT_SHA/images/dovecot" \
+      --label "org.opencontainers.image.source=$CI_PROJECT_URL/-/tree/$CI_COMMIT_SHA/images/${IMAGE}" \
       --label "org.opencontainers.image.revision=$CI_COMMIT_SHA" \
       --label "org.opencontainers.image.created=$(date --rfc-3339 ns)" \
-      --label "org.opencontainers.image.title=dovecot" \
-      -t "quay.io/shivering-isles/dovecot:${release}" \
+      --label "org.opencontainers.image.title=${IMAGE}" \
+      -t "quay.io/shivering-isles/${IMAGE}:${release}" \
       --format docker \
       .
     - podman push "quay.io/shivering-isles/dovecot:${release}"
   rules:
     - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
       changes:
-        - images/dovecot/.release
+        - images/${IMAGE}/.release
 
-dovecot-container-build-dev:
+container-build-dev:
   stage: build
   image: quay.io/sheogorath/build-ah-engine:2.0.0
+  extends: .container-matrix
   before_script:
     - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
     - |
-      cd images/dovecot
+      cd images/${IMAGE}
       podman build --pull \
-      --label "org.opencontainers.image.source=$CI_PROJECT_URL/-/tree/$CI_COMMIT_SHA/images/dovecot" \
+      --label "org.opencontainers.image.source=$CI_PROJECT_URL/-/tree/$CI_COMMIT_SHA/images/${IMAGE}" \
       --label "org.opencontainers.image.revision=$CI_COMMIT_SHA" \
       --label "org.opencontainers.image.created=$(date --rfc-3339 ns)" \
-      --label "org.opencontainers.image.title=$CI_PROJECT_TITLE" \
+      --label "org.opencontainers.image.title=${IMAGE}" \
       --label "quay.expires-after=12w" \
-      -t "quay.io/shivering-isles/dovecot:${CI_COMMIT_SHORT_SHA}" \
+      -t "quay.io/shivering-isles/${IMAGE}:${CI_COMMIT_SHORT_SHA}" \
       --format docker \
       .
-    - podman push "quay.io/shivering-isles/dovecot:${CI_COMMIT_SHORT_SHA}"
+    - podman push "quay.io/shivering-isles/${IMAGE}:${CI_COMMIT_SHORT_SHA}"
   rules:
     - if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
       changes:
-        - images/dovecot/
+        - images/${IMAGE}/*
+        - images/.utils/*
diff --git a/images/postfix/.gitlab-ci.yaml b/images/postfix/.gitlab-ci.yaml
deleted file mode 100644
index 19fa03737e0bebabfd42bbee7a7a5843c511a73d..0000000000000000000000000000000000000000
--- a/images/postfix/.gitlab-ci.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
-postfix-container-build:
-  stage: build
-  image: quay.io/sheogorath/build-ah-engine:2.0.0
-  before_script:
-    - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
-  script:
-    - |
-      cd images/postfix
-      source .release
-      podman build --pull \
-      --label "org.opencontainers.image.source=$CI_PROJECT_URL/-/tree/$CI_COMMIT_SHA/images/postfix" \
-      --label "org.opencontainers.image.revision=$CI_COMMIT_SHA" \
-      --label "org.opencontainers.image.created=$(date --rfc-3339 ns)" \
-      --label "org.opencontainers.image.title=$CI_PROJECT_TITLE" \
-      -t "quay.io/shivering-isles/postfix:${release}" \
-      --format docker \
-      .
-    - podman push "quay.io/shivering-isles/postfix:${release}"
-  rules:
-    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
-      changes:
-        - images/postfix/.release
-
-postfix-container-build-dev:
-  stage: build
-  image: quay.io/sheogorath/build-ah-engine:2.0.0
-  before_script:
-    - podman login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
-  script:
-    - |
-      cd images/postfix
-      podman build --pull \
-      --label "org.opencontainers.image.source=$CI_PROJECT_URL/-/tree/$CI_COMMIT_SHA/images/postfix" \
-      --label "org.opencontainers.image.revision=$CI_COMMIT_SHA" \
-      --label "org.opencontainers.image.created=$(date --rfc-3339 ns)" \
-      --label "org.opencontainers.image.title=$CI_PROJECT_TITLE" \
-      --label "quay.expires-after=12w" \
-      -t "quay.io/shivering-isles/postfix:${CI_COMMIT_SHORT_SHA}" \
-      --format docker \
-      .
-    - podman push "quay.io/shivering-isles/postfix:${CI_COMMIT_SHORT_SHA}"
-  rules:
-    - if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"'
-      changes:
-        - images/postfix/