Integrating Nexus Repository with CI/CD Pipelines: GitHub Actions, Jenkins, and Security Scanning
Nexus as the Artifact Hub for Your Pipeline
A CI/CD pipeline that pulls from the internet on every run is fragile. Nexus sits between your pipeline and the outside world: proxy repos cache external packages, hosted repos store build outputs, and the group repo gives pipelines a single URL that resolves both.
This guide shows integration patterns for GitHub Actions and Jenkins.
GitHub Actions: Publishing to Nexus
Docker Image to Nexus Hosted Registry
# .github/workflows/publish.yml
name: Build and Publish
on:
push:
branches: [main]
tags: ['v*']
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Log in to Nexus Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.NEXUS_HOST }}:8082
username: ${{ secrets.NEXUS_USER }}
password: ${{ secrets.NEXUS_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ secrets.NEXUS_HOST }}:8082/myapp:latest
${{ secrets.NEXUS_HOST }}:8082/myapp:${{ github.sha }}
Maven Artifact to Nexus
name: Maven Build and Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
server-id: nexus
server-username: NEXUS_USER
server-password: NEXUS_PASSWORD
- name: Build and deploy to Nexus
env:
NEXUS_USER: ${{ secrets.NEXUS_USER }}
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
run: mvn deploy -DskipTests
pom.xml distribution management:
<distributionManagement>
<snapshotRepository>
<id>nexus</id>
<url>http://nexus.example.com:8081/repository/maven-snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus</id>
<url>http://nexus.example.com:8081/repository/maven-releases/</url>
</repository>
</distributionManagement>
npm Package to Nexus
name: Publish npm Package
on:
release:
types: [created]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'http://nexus.example.com:8081/repository/npm-hosted/'
- run: npm ci
- run: npm run build
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NEXUS_NPM_TOKEN }}
Pulling From Nexus Proxy (Speed Up Builds)
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Configure Docker to use Nexus as registry mirror
- name: Configure Docker daemon
run: |
sudo mkdir -p /etc/docker
echo '{"registry-mirrors":["http://nexus.example.com:8083"]}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
# npm packages via Nexus proxy
- uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'http://nexus.example.com:8081/repository/npm-group/'
Jenkins Integration
Jenkinsfile: Maven Build + Nexus Publish
pipeline {
agent any
environment {
NEXUS_URL = 'nexus.example.com:8081'
NEXUS_CREDS = credentials('nexus-credentials')
}
stages {
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Publish to Nexus') {
when {
branch 'main'
}
steps {
withCredentials([usernamePassword(
credentialsId: 'nexus-credentials',
usernameVariable: 'NEXUS_USER',
passwordVariable: 'NEXUS_PASS'
)]) {
sh '''
mvn deploy \
-Dmaven.test.skip=true \
-Dnexus.username=${NEXUS_USER} \
-Dnexus.password=${NEXUS_PASS}
'''
}
}
}
stage('Docker Push') {
when {
branch 'main'
}
steps {
script {
docker.withRegistry("http://${NEXUS_URL}", 'nexus-credentials') {
def image = docker.build("myapp:${env.BUILD_NUMBER}")
image.push()
image.push('latest')
}
}
}
}
}
}
Nexus Plugin for Jenkins
Install the Nexus Artifact Uploader plugin:
stage('Upload Artifact') {
steps {
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: 'http',
nexusUrl: 'nexus.example.com:8081',
groupId: 'com.example',
version: env.BUILD_NUMBER,
repository: 'maven-releases',
credentialsId: 'nexus-credentials',
artifacts: [
[
artifactId: 'myapp',
classifier: '',
file: 'target/myapp.jar',
type: 'jar'
],
[
artifactId: 'myapp',
classifier: '',
file: 'pom.xml',
type: 'pom'
]
]
)
}
}
Artifact Versioning Strategy
Semantic Versioning with Git Tags
# GitHub Actions: tag-based release to releases repo
- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Build and deploy release
run: |
mvn versions:set -DnewVersion=${{ steps.version.outputs.VERSION }}
mvn deploy -DskipTests
env:
NEXUS_USER: ${{ secrets.NEXUS_USER }}
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
SNAPSHOT vs Release Policy
In Maven:
1.0.0-SNAPSHOT→ deploy tomaven-snapshotsrepo (allows re-deploy)1.0.0→ deploy tomaven-releasesrepo (disable re-deploy to prevent overwriting)
Nexus enforces this automatically based on version string.
Nexus IQ: Security Scanning in CI/CD
Nexus IQ (part of Nexus platform, commercial) scans dependencies for CVEs in the pipeline:
# GitHub Actions with Nexus IQ
- name: Nexus IQ Scan
uses: sonatype-nexus-community/iq-github-action@main
with:
serverUrl: http://nexus-iq.example.com:8070
username: ${{ secrets.IQ_USER }}
password: ${{ secrets.IQ_PASSWORD }}
applicationId: myapp
stage: Build
target: target/myapp.jar
Or using the CLI:
# Download Nexus IQ CLI
wget https://download.sonatype.com/clm/scanner/nexus-iq-cli.jar
# Scan
java -jar nexus-iq-cli.jar \
-i myapp \
-s http://nexus-iq.example.com:8070 \
-a username:password \
-t build \
target/myapp.jar
# Fails build if policy violations exceed threshold
Artifact Promotion Workflow
The standard pattern for moving artifacts from dev → staging → production:
build → maven-snapshots repo (SNAPSHOT)
↓ on release branch
tag → maven-releases repo (1.x.x)
↓ after QA approval
promote → maven-prod-releases repo (copy, not re-build)
Nexus supports this via Content Selectors and Routing Rules to lock down who can write to each repo, and Staging (Nexus Pro) for promotion workflows.
Manual promotion via REST API:
# Copy artifact between repos using Nexus REST API
curl -u admin:password -X POST \
"http://nexus.example.com:8081/service/rest/v1/staging/move/maven-prod-releases" \
-H "Content-Type: application/json" \
-d '{
"source": "maven-releases",
"destination": "maven-prod-releases",
"coordinates": {
"groupId": "com.example",
"artifactId": "myapp",
"version": "1.2.0"
}
}'
Was this article helpful?
CI/CD Engineering Lead
Automation evangelist who believes no deployment should require a human. I write pipelines, break pipelines, and write about both. Code-first, always.
Related Articles
JFrog Artifactory: Setup, Repository Configuration, and Pipeline Integration
How to set up JFrog Artifactory, configure local and remote repositories, integrate with Docker and build tools, use Artifactory query language for artifact searches, and set up release bundles.
Nexus Repository Manager: Setup, Docker Registry, and Maven/npm Proxy
How to install and configure Sonatype Nexus Repository Manager 3 — setting up hosted, proxy, and group repositories for Docker, Maven, and npm, with access control and cleanup policies.
Artifact Repositories in CI/CD: Push, Pull, and Promote
Integrate Nexus and Artifactory with Jenkins, GitHub Actions, and GitLab CI — push artifacts, pull dependencies, and implement promotion workflows.
Jenkins Declarative Pipelines: From Zero to Production CI/CD
How to write Jenkins declarative pipelines from scratch — stages, agents, environment variables, credentials, parallel execution, post conditions, and shared libraries. Practical Jenkinsfile patterns for real projects.
Jenkins Kubernetes Agents: Dynamic Build Pods for Scalable CI/CD
Configure Jenkins to dynamically spin up Kubernetes pods as build agents. Covers the Kubernetes plugin, pod templates, JNLP agents, multi-container pods, resource limits, and RBAC — so you never manage static build nodes again.
The Complete Guide to GitHub Actions CI/CD: From Zero to Production-Ready Pipelines
Build production-grade GitHub Actions CI/CD pipelines — from first workflow to reusable workflows, matrix builds, and deployment gates.