diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 72d373ba4672e319e24ca07274c2a0f86bf5f370..e321653c0314db3cc42980ccaac4ce98c64df165 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,3 +1,19 @@
+.pre-deploy-uber-space-setup: &pre-deploy-uber-space-setup
+  - apk add rsync openssh-client
+  - eval $(ssh-agent -s)
+  - echo "$CI_DEPLOYMENT_PRIVATE_KEY" | tr -d '\r' | ssh-add -
+  - mkdir -p ~/.ssh
+  - chmod 700 ~/.ssh
+  - echo "$UBERSPACE_KNOWN_HOST" >> ~/.ssh/known_hosts
+
+workflow:
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
+      when: never
+    - if: '$CI_COMMIT_BRANCH'
+    - if: '$CI_COMMIT_TAG'
+
 stages:
   - lint
   - build
@@ -36,21 +52,23 @@ build:
       - dist/
     expire_in: 30 days
 
-upload:
+upload:latest:
+  stage: upload
+  image: $CI_REGISTRY/alpine:latest
+  rules:
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+  before_script:
+    - *pre-deploy-uber-space-setup
+  script:
+    - rsync -Lvz -e "ssh -o CheckHostIP=no" ./dist/submission-api.yaml fitko@dorado.uberspace.de:schema.fitko.de/fit-connect/submission-api/latest/
+
+upload:release:
   stage: upload
   image: $CI_REGISTRY/alpine:latest
-  only:
-    refs:
-      - tags
-    variables:
-      - $CI_COMMIT_TAG
+  rules:
+    - if: $CI_COMMIT_TAG
   before_script:
-    - apk add rsync openssh-client
-    - eval $(ssh-agent -s)
-    - echo "$CI_DEPLOYMENT_PRIVATE_KEY" | tr -d '\r' | ssh-add -
-    - mkdir -p ~/.ssh
-    - chmod 700 ~/.ssh
-    - echo "$UBERSPACE_KNOWN_HOST" >> ~/.ssh/known_hosts
+    - *pre-deploy-uber-space-setup
   script:
     - sed -i "s,API_VERSION,$CI_COMMIT_TAG,g" dist/submission-api.yaml
     - rsync -Lvz -e "ssh -o CheckHostIP=no" ./dist/submission-api.yaml fitko@dorado.uberspace.de:schema.fitko.de/fit-connect/submission-api/$CI_COMMIT_TAG/