diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b7e24209df4473d06484036f4062d35fe3d0f347
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,71 @@
+image: maven:3.9.9-eclipse-temurin-21-alpine
+
+variables:
+  MAVEN_DEPLOY_CLI_OPTS: "--no-transfer-progress -DskipTests"
+  MAVEN_CLI_OPTS: >-
+    -s .m2/ci_settings.xml --batch-mode
+    -Dmaven.plugin.validation=brief
+  DOCKER_HOST: tcp://docker:2375
+  DOCKER_TLS_CERTDIR: ""
+  DOCKER_DRIVER: overlay2
+
+services:
+  - docker:dind
+
+cache:
+  paths:
+    - .m2/repository/
+    - target/
+
+stages:
+  - build
+  - test
+  - publish
+
+build:
+  stage: build
+  script:
+    - mvn clean compile $MAVEN_CLI_OPTS
+  artifacts:
+    paths:
+      - target/*.jar
+
+test:
+  stage: test
+  script:
+    - mvn test $MAVEN_CLI_OPTS
+
+verify:
+  stage: test
+  script:
+    - mvn verify $MAVEN_CLI_OPTS
+
+push-snapshot-image-gitlab:
+  stage: publish
+  script:
+    - mvn deploy -Pgitlab-deploy $MAVEN_DEPLOY_CLI_OPTS $MAVEN_CLI_OPTS
+  only:
+    - main
+
+push-snapshot-image-nexus:
+  stage: publish
+  script:
+    - mvn deploy -Pnexus-deploy $MAVEN_DEPLOY_CLI_OPTS $MAVEN_CLI_OPTS
+  only:
+    - main
+
+push-release-image-gitlab:
+  stage: publish
+  script:
+    - mvn versions:set -DnewVersion=${CI_COMMIT_TAG}
+    - mvn deploy -Pgitlab-deploy $MAVEN_DEPLOY_CLI_OPTS $MAVEN_CLI_OPTS
+  rules:
+    - if: $CI_COMMIT_TAG
+
+push-release-image-nexus:
+  stage: publish
+  script:
+    - mvn versions:set -DnewVersion=${CI_COMMIT_TAG}
+    - mvn mvn deploy -Pnexus-deploy $MAVEN_DEPLOY_CLI_OPTS $MAVEN_CLI_OPTS
+  rules:
+    - if: $CI_COMMIT_TAG
diff --git a/.m2/ci_settings.xml b/.m2/ci_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..06b0cb517d6b244915cb2e8a44a717a77176d09e
--- /dev/null
+++ b/.m2/ci_settings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 http://maven.apache.org/xsd/settings-1.2.0.xsd"
+          xmlns="http://maven.apache.org/SETTINGS/1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <localRepository>.m2/repository</localRepository>
+
+    <servers>
+        <server>
+            <id>ozg-nexus</id>
+            <username>${env.NEXUS_USER}</username>
+            <password>${env.NEXUS_PASSWORD}</password>
+        </server>
+        <server>
+            <id>ozg-snapshots-nexus</id>
+            <username>${env.NEXUS_USER}</username>
+            <password>${env.NEXUS_PASSWORD}</password>
+        </server>
+        <server>
+            <id>codesh-gitlab-maven</id>
+            <configuration>
+                <httpHeaders>
+                    <property>
+                        <name>Job-Token</name>
+                        <value>${CI_JOB_TOKEN}</value>
+                    </property>
+                </httpHeaders>
+            </configuration>
+        </server>
+    </servers>
+    <profiles>
+        <profile>
+            <id>ci-default</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <repositories>
+                <repository>
+                    <id>codesh-gitlab-maven</id>
+                    <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
+                </repository>
+                <repository>
+                    <id>ozg-nexus</id>
+                    <name>ozg-releases</name>
+                    <url>https://nexus.ozg-sh.de/repository/ozg-releases/</url>
+                </repository>
+                <repository>
+                    <id>ozg-snapshots-nexus</id>
+                    <name>ozg-snapshots</name>
+                    <url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url>
+                    <snapshots>
+                        <enabled>true</enabled>
+                    </snapshots>
+                </repository>
+            </repositories>
+        </profile>
+    </profiles>
+</settings>