diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 78f4fa997ff2af36189b5392cf0fab7162c38d4f..3dae7d132a3b4b1bd46ecda643f4a2471c136532 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,132 +34,55 @@ build:
   stage: build
   allow_failure: false
   image:
-      name: docker/compose:1.24.0
-      entrypoint: ["/bin/sh", "-c"]
-
-  services:
-    # Link another container, which provides the docker daemon. The daemon
-    # from the other container is exposed via http port 2375.
-    - name: docker:18.09.7-dind
-      alias: docker-in-docker
-
-  tags:
-    # Use docker-machine (virtualbox) runner to run containers in priviliged
-    # mode
-    - dind
+    name: gcr.io/kaniko-project/executor:v1.14.0-debug
+    entrypoint: [""]
 
   dependencies:
     - jsbuild
 
-  variables:
-    # Tell docker client where it can find the daemon
-    DOCKER_HOST: tcp://docker-in-docker:2375/
-    GIT_SUBMODULE_STRATEGY: recursive
-
-  script:
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml build
-    - echo "${CI_REGISTRY_PASSWORD}" | docker login -u ${CI_REGISTRY_USER} --password-stdin ${CI_REGISTRY}
-    - test $FORCE_RECREATE && docker rm -f $(docker ps -q) || true
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml push
-    - ./ci/tag_latest.sh
-
-container-test:
-  stage: deploy
-  image:
-      name: docker/compose:1.24.0
-      entrypoint: ["/bin/sh", "-c"]
-
-  services:
-    # Link another container, which provides the docker daemon. The daemon
-    # from the other container is exposed via http port 2375.
-    - name: docker:18.09.7-dind
-      alias: docker-in-docker
-
-  tags:
-    # Use docker-machine (virtualbox) runner to run containers in priviliged
-    # mode
-    - dind
-
-  variables:
-    # Tell docker client where it can find the daemon
-    DOCKER_HOST: tcp://docker-in-docker:2375/
-    DB_PASSWORD: ${STAGING_DB_PASSWORD}
-    SUPER_USERNAME: ${STAGING_USERNAME}
-    SUPER_EMAIL: ${STAGING_EMAIL}
-    SUPER_PASSWORD: ${STAGING_PASSWORD}
-    SECRET_KEY: ${STAGING_SECRET_KEY}
-    STAGING: 1
+  rules:
+    - if: $CI_COMMIT_TAG
 
   script:
-    - echo "${CI_REGISTRY_PASSWORD}" | docker login -u ${CI_REGISTRY_USER} --password-stdin ${CI_REGISTRY}
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml pull -q
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d database
-    - sleep 10
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml exec -T database bash -c "until pg_isready; do sleep 10; echo Waiting for database; done"
-    - sleep 30
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml run keys bash -c "python manage.py compress && python manage.py test"
+    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+    - /kaniko/executor
+      --context "${CI_PROJECT_DIR}/app"
+      --dockerfile "${CI_PROJECT_DIR}/app/Dockerfile"
+      --destination "${CI_REGISTRY_IMAGE}/keys:${CI_COMMIT_TAG}"
 
-.deploy: &deploy_template
+.deploy:
   stage: deploy
-  tags:
-    - wasenweiler.sit-servers.net
   image:
-      name: docker/compose:1.24.0
-      entrypoint: ["/bin/sh", "-c"]
+    name: alpine/k8s:1.28.2
   script:
-    - export DOCKER_CERT_PATH=`pwd`/.remote
-    - export DOCKER_TLS_VERIFY=1
-    - echo "${CI_REGISTRY_PASSWORD}" | docker login -u ${CI_REGISTRY_USER} --password-stdin ${CI_REGISTRY}
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml pull -q
-    - docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d
-    - sleep 10
-    - docker-compose restart webserver
-
-deploy_staging:
-  # Deploy the current image to the production machine.
-  <<: *deploy_template
-
-  variables:
-    DOCKER_HOST: tcp://keys.preview.sauerburger.com:8376/
-    DB_PASSWORD: ${STAGING_DB_PASSWORD}
-    SUPER_USERNAME: ${STAGING_USERNAME}
-    SUPER_EMAIL: ${STAGING_EMAIL}
-    SUPER_PASSWORD: ${STAGING_PASSWORD}
-    SECRET_KEY: ${STAGING_SECRET_KEY}
-    STAGING: 1
-
-  before_script:
-    - mkdir -p .remote
-    - cp "${STAGING_TLS_CA}" .remote/ca.pem
-    - cp "${STAGING_TLS_KEY}" .remote/key.pem
-    - cp "${STAGING_TLS_CERT}" .remote/cert.pem
-
-  environment:
-    name: Staging Environment
-    url: https://keys.preview.sauerburger.com/
-
-deploy_production:
-  # Deploy the current image to the production machine.
-  <<: *deploy_template
-
-  when: manual
-  variables:
-    DOCKER_HOST: tcp://keys.sauerburger.com:8376/
-    DB_PASSWORD: ${PRODUCTION_DB_PASSWORD}
-    SUPER_USERNAME: ${PRODUCTION_USERNAME}
-    SUPER_EMAIL: ${PRODUCTION_EMAIL}
-    SUPER_PASSWORD: ${PRODUCTION_PASSWORD}
-    SECRET_KEY: ${PRODUCTION_SECRET_KEY}
-    PRODUCTION: 1
-
-  only:
-    - master
-  before_script:
-    - mkdir -p .remote
-    - cp "${PRODUCTION_TLS_CA}" .remote/ca.pem
-    - cp "${PRODUCTION_TLS_KEY}" .remote/key.pem
-    - cp "${PRODUCTION_TLS_CERT}" .remote/cert.pem
-
-  environment:
-    name: Production Environment
-    url: https://keys.sauerburger.com/
+    - kubectl config use-context frank/sauerburger-keys:keys-agent
+    - |
+      helm upgrade \
+        --install \
+        --namespace "${NAMESPACE}" \
+        --create-namespace \
+        --atomic --wait \
+        --timeout 15m0s \
+        --set "backend.tag=${CI_COMMIT_TAG}" \
+        --set "ingress.host=${HOST}" \
+        keys chart
+  rules:
+    - if: $CI_COMMIT_TAG
+
+# deploy_staging:
+#   extends: .deploy
+#   variables:
+#     HOST: keys.preview.sauerburger.com
+# 		NAMESPACE: keys-staging
+#   environment:
+#     name: Staging Environment
+#     url: https://keys.preview.sauerburger.com/
+#
+# deploy_production:
+#   extends: .deploy
+#   variables:
+#     HOST: keys.sauerburger.com
+# 		NAMESPACE: keys
+#   environment:
+#     name: Production Environment
+#     url: https://keys.sauerburger.com/
diff --git a/ci/tag_latest.sh b/ci/tag_latest.sh
deleted file mode 100755
index 3671130c5bbd883afa26a8452767b626241b8f64..0000000000000000000000000000000000000000
--- a/ci/tag_latest.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-for image in app webserver
-do
-  docker tag ${CI_REGISTRY_IMAGE}/${image}:${CI_COMMIT_SHA} ${CI_REGISTRY_IMAGE}/${image}:latest
-  docker push ${CI_REGISTRY_IMAGE}/${image}:latest
-done