Published on: May 22, 2025
5 min read
Learn the best practices, advanced techniques, and upcoming features that improve the efficiency of your DevSecOps workflow.
As a GitLab product manager, I'm excited to share insights on securing and optimizing your Maven repository. We're passionate about providing a complete DevSecOps platform, and the Maven repository is part of this ecosystem. Explore best practices, advanced techniques, and upcoming features that will transform your Maven workflow.
Securing your software supply chain is more critical than ever so let's dive into strategies to fortify your Maven packages in GitLab.
Personal access tokens: Use PATs for fine-grained access control.
For example:
mvn deploy -s settings.xml
Where settings.xml
contains:
<settings>
<servers>
<server>
<id>gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Private-Token</name>
<value>${env.GITLAB_PERSONAL_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>
Deploy tokens: Ideal for CI/CD pipelines. Generate these in your GitLab project settings and use them in your .gitlab-ci.yml
.
deploy:
script:
- 'mvn deploy -s ci_settings.xml'
variables:
MAVEN_CLI_OPTS: "-s ci_settings.xml --batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
only:
- main
The corresponding ci_settings.xml
file:
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<servers>
<server>
<id>gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Deploy-Token</name>
<value>${env.CI_DEPLOY_PASSWORD}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>
In this setup:
CI_DEPLOY_PASSWORD
should be set as a CI/CD variable in your GitLab project settings containing the deploy token.<id>
should match the repository ID in your project's pom.xml
file.Token rotation: Implement a token rotation policy using GitLab's API. For example, you could create a scheduled pipeline that rotates tokens monthly:
rotate_tokens:
script:
- curl --request POST "https://gitlab.example.com/api/v4/projects/${CI_PROJECT_ID}/deploy_tokens" --header "PRIVATE-TOKEN: ${ADMIN_TOKEN}" --form "name=maven-deploy-${CI_PIPELINE_ID}" --form "scopes[]=read_registry" --form "scopes[]=write_registry"
only:
- schedules
Dependency Scanning: Enable it in your .gitlab-ci.yml
.
include:
- template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
DS_JAVA_VERSION: 11
Container Scanning: If you're containerizing your Maven applications.
include:
- template: Security/Container-Scanning.gitlab-ci.yml
variables:
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
License Compliance: Ensure all dependencies comply with your project's licensing requirements.
include:
- template: Security/License-Scanning.gitlab-ci.yml
CI/CD variables: Store sensitive information securely.
variables:
MAVEN_REPO_USER: ${CI_DEPLOY_USER}
MAVEN_REPO_PASS: ${CI_DEPLOY_PASSWORD}
Masked variables: Prevent exposure in job logs. Set these in your GitLab CI/CD settings.
Protected branches and tags: Configure these in your GitLab project settings to control who can trigger package publishing.
Use the Maven GPG plugin to sign your artifacts.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Store your GPG key securely using GitLab CI/CD variables.
Efficiency is crucial when working with large projects or numerous dependencies. Here are advanced techniques to optimize your Maven package usage in GitLab.
Use the <dependencyManagement>
section in your parent POM.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Structure your project with a parent POM and multiple modules:
my-project/
├── pom.xml
├── module1/
│ └── pom.xml
├── module2/
│ └── pom.xml
└── module3/
└── pom.xml
Use Maven's reactor to build modules in the optimal order:
mvn clean install
Use Maven's parallel build feature:
mvn -T 4C clean install
In .gitlab-ci.yml
, use caching to speed up builds:
cache:
paths:
- .m2/repository
build:
script:
- mvn clean package -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
Implement incremental builds:
build:
script:
- mvn clean install -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -am -amd -fae
Use the Gradle Enterprise Maven Extension for build caching:
<build>
<plugins>
<plugin>
<groupId>com.gradle</groupId>
<artifactId>gradle-enterprise-maven-plugin</artifactId>
<version>1.9</version>
<configuration>
<gradleEnterprise>
<server>https://ge.example.com</server>
<allowUntrusted>false</allowUntrusted>
</gradleEnterprise>
</configuration>
</plugin>
</plugins>
</build>
I'm thrilled to announce the launch of our beta program for the upcoming Maven virtual registry feature. This addition to our package ecosystem will change how you manage Maven repositories in GitLab.
settings.xml
:<settings>
<servers>
<server>
<id>gitlab-maven</id>
<configuration>
<httpHeaders>
<property>
<name>Private-Token</name>
<value>${env.GITLAB_TOKEN}</value>
</property>
</httpHeaders>
</configuration>
</server>
</servers>
</settings>
Authentication options:
Personal access token: Use Private-Token
as the name and ${env.GITLAB_TOKEN}
as the value.
Group deploy token: Use Deploy-Token
as the name and ${env.GITLAB_DEPLOY_TOKEN}
as the value.
Group access token: Use Private-Token
as the name and ${env.GITLAB_ACCESS_TOKEN}
as the value.
CI job token: Use Job-Token
as the name and ${CI_JOB_TOKEN}
as the value.
Configure the virtual registry in your pom.xml
.
Option 1: As an additional registry:
<repositories>
<repository>
<id>gitlab-maven</id>
<url>https://gitlab.example.com/api/v4/virtual_registries/packages/maven/<virtual registry id></url>
</repository>
</repositories>
Option 2: As a replacement for Maven Central (in your settings.xml
):
<mirrors>
<mirror>
<id>gitlab-maven</id>
<name>GitLab virtual registry for Maven Central</name>
<url>https://gitlab.example.com/api/v4/virtual_registries/packages/maven/<virtual registry id></url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
# For personal access tokens
export GITLAB_TOKEN=your_personal_access_token
# For group deploy tokens
export GITLAB_DEPLOY_TOKEN=your_deploy_token
# For group access tokens
export GITLAB_ACCESS_TOKEN=your_access_token
# Then run Maven commands normally
mvn package
We're actively seeking participants for our beta program. As a beta tester, you'll have the opportunity to:
To join the beta program or learn more about the Maven Virtual Registry, please visit the GitLab Maven Virtual Registry Beta Program (Note: This is a placeholder link).
At GitLab, we're committed to providing cutting-edge tools for secure, efficient, and scalable software development. The Maven Virtual Registry is just one example of how we're continuously innovating to meet the evolving needs of developers and platform engineers.
Implementing the security measures and optimization techniques discussed in this post and leveraging upcoming features like the Maven Virtual Registry can improve your Maven workflow within GitLab.
We're excited about the future of package management in GitLab and can't wait to see how you'll use these features to take your development process to the next level. Stay tuned for more updates and happy coding!