diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b154fe2b95a374ad9549675c272f055d151baa80..e53b1a6f49b681b26e3dfcc2bafc9fbabcfada60 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,3 +1,9 @@
+stages:
+  - build
+  - deploy
+  - test
+  - cleanup
+
 ci_test_image:
   stage: build
   variables:
@@ -43,19 +49,38 @@ bootstrap:
     - eval $(ssh-agent -s)
     - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
     - ANSIBLE_HOST_KEY_CHECKING=False python3 -u ./ci-bootstrap.py --create_droplet
-    # Run testinfra tests
-    - py.test -v --ansible-inventory=./inventory.yml --connection=ssh --hosts='ansible://*'
     # Wait for proper LE cert to get served
     - timeout -t 1200 sh -c 'while ! curl --cacert ./letsencrypt_fakelerootx1.pem -s https://auth.ci-${CI_JOB_ID}.ci.openappstack.net/auth/ > /dev/null; do date; echo "Waiting for LE cert..."; sleep 5; done'
-    # Run behave tests
-    - cd behave/
-    - behave -D keycloak.admin.url=https://auth.ci-${CI_JOB_ID}.ci.openappstack.net/auth/admin/master/console/ -D keycloak.admin.password=$(cat ../secrets/keycloak_admin_password)
-    # Remove droplet after successful tests
-    - cd ..
-    - python3 -c "import cosmos; cosmos.terminate_droplets_by_name(\"^ci-${CI_JOB_ID}\$\")"
   artifacts:
     paths:
     - ansible/rke.log
+    expire_in: 1 month
+    when: always
+
+testinfra:
+  stage: test
+  image: docker.greenhost.net/openappstack/bootstrap/bootstrap-ci
+  script:
+    - cd test/
+    - py.test -v --ansible-inventory=./inventory.yml --connection=ssh --hosts='ansible://*'
+
+behave:
+  stage: test
+  image: docker.greenhost.net/openappstack/bootstrap/bootstrap-ci
+  script:
+    # Run behave tests
+    - cd test/behave/
+    - behave -D keycloak.admin.url=https://auth.ci-${CI_JOB_ID}.ci.openappstack.net/auth/admin/master/console/ -D keycloak.admin.password=$(cat ./secrets/keycloak_admin_password)
+  artifacts:
+    paths:
     - test/behave/screenshots/
     expire_in: 1 month
     when: always
+
+terminate:
+  stage: cleanup
+  image: docker.greenhost.net/openappstack/bootstrap/bootstrap-ci
+  script:
+    # Remove droplet after successful tests
+    - cd test/
+    - python3 -c "import cosmos; cosmos.terminate_droplets_by_name(\"^ci-${CI_JOB_ID}\$\")"