diff --git a/.CI/README b/.CI/README
new file mode 100644
index 0000000000000000000000000000000000000000..457c6ee3ebf080e149a211a73db41acbc55f2af4
--- /dev/null
+++ b/.CI/README
@@ -0,0 +1 @@
+A directory for Continuous Integration tooling.
\ No newline at end of file
diff --git a/.CI/maven-settings.xml b/.CI/maven-settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4bef3be4d6a8da9244f6db0993412f0d7428102d
--- /dev/null
+++ b/.CI/maven-settings.xml
@@ -0,0 +1,63 @@
+<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+          xsi:schemalocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+    <mirrors>
+        <!-- mirror
+        | Specifies a repository mirror site to use instead of a given repository. The repository that
+        | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
+        | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
+        |
+        <mirror>
+        <id>mirrorId</id>
+        <mirrorOf>repositoryId</mirrorOf>
+        <name>Human Readable Name for this Mirror.</name>
+        <url>http://my.repository.com/repo/path</url>
+        </mirror>
+        -->
+        <mirror>
+            <id>Nexus-Rugged</id>
+            <name>Maven Repository Manager</name>
+            <!-- Share the same Nexus repository as Orekit -->
+            <url>https://packages.rugged.org/repository/maven-public/</url>
+            <mirrorOf>*</mirrorOf>
+        </mirror>
+    </mirrors>
+    <servers>
+        <server>
+            <id>ci-releases</id>
+            <username>${env.NEXUS_USERNAME}</username>
+            <password>${env.NEXUS_PASSWORD}</password>
+        </server>
+        <server>
+            <id>ci-snapshots</id>
+            <username>${env.NEXUS_USERNAME}</username>
+            <password>${env.NEXUS_PASSWORD}</password>
+        </server>
+        <server>
+            <id>website</id>
+            <privateKey>${user.home}/.ssh/id_website</privateKey>
+        </server>
+    </servers>
+    <profiles>
+        <profile>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <repositories>
+                <repository>
+                    <id>Nexus-Rugged</id>
+                    <name>Nexus Public Repository</name>
+                    <!-- Share the same Nexus repository as Orekit -->
+                    <url>https://packages.orekit.org/repository/maven-public/</url>
+                    <releases>
+                        <enabled>true</enabled>
+                    </releases>
+                    <snapshots>
+                        <enabled>true</enabled>
+                        <updatePolicy>always</updatePolicy>
+                    </snapshots>
+                </repository>
+            </repositories>
+        </profile>
+    </profiles>
+</settings>
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c7c79b498e2e7812da283ad2976ae3201f95c75f
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,78 @@
+stages:
+- verify
+- deploy
+
+default:
+  # Default image
+  image: registry.orekit.org/orekit/ci-utils/maven:3.3.9-jdk-8
+  # Cache downloaded dependencies and plugins between builds.
+  # To keep cache across branches add 'key: "$CI_JOB_REF_NAME"'
+  cache:
+    paths:
+      - .m2/repository
+
+variables:
+  # This will supress any download for dependencies and plugins or upload messages which would clutter the console log.
+  # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
+  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
+  # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
+  # when running from the command line.
+  # `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
+  MAVEN_CLI_OPTS: "-s .CI/maven-settings.xml --batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
+
+verify:
+  stage: verify
+  script:
+    - mvn $MAVEN_CLI_OPTS verify site
+    - mvn $MAVEN_CLI_OPTS sonar:sonar -Dsonar.login=${SONAR_TOKEN} -Dsonar.branch.name=${CI_COMMIT_REF_NAME}
+  artifacts:
+    paths:
+      - target/*.jar
+      - target/site
+    reports:
+      junit:
+        - target/surefire-reports/*.xml
+
+# On main branches (develop, release-*, master)
+# the produced artifacts are deployed on the Nexus of the project
+# (https://packages.orekit.org/)
+deploy:artifacts:
+  stage: deploy
+  script:
+    - mvn $MAVEN_CLI_OPTS javadoc:jar source:jar deploy -DskipTests=true -Pci-deploy
+  artifacts:
+    paths:
+      - target/*.jar
+  only:
+    - develop@orekit/rugged
+    - /^release-[.0-9]+$/@orekit/rugged
+    - master@orekit/rugged
+
+
+deploy:site:
+  stage: deploy
+  before_script:
+  ##
+  ## Create the SSH directory and give it the right permissions
+  ##
+  - mkdir -p ~/.ssh
+  - chmod 700 ~/.ssh
+
+  ##
+  ## We're using tr to fix line endings which makes ed25519 keys work
+  ## without extra base64 encoding.
+  ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
+  ##
+  - echo "$SSH_SECRET_KEY" > ~/.ssh/id_website
+  - chmod 700 ~/.ssh/id_website
+  
+  ##
+  ## Add known hosts
+  ##
+  - cp $SSH_KNOWN_HOSTS ~/.ssh/known_hosts
+  script:
+  - mvn $MAVEN_CLI_OPTS site:deploy
+  only:
+  - master@orekit/rugged
+  - /^release-[.0-9]+$/@orekit/rugged
+  - develop@orekit/rugged