Maven 2 Repositories, Snapshots, Releases, Metadata, Checksums, and Maven Client Configuration: Guided Hands-On Workflow and Core Operations
Build a disposable Maven/Nexus topology, configure an isolated settings.xml and local repository, resolve through a group, deploy synthetic snapshots and releases only to hosted repositories, and inspect metadata and checksums.
Learning objectives
- Create disposable Maven release, snapshot, Central proxy, and group repositories with policies that match their roles.
-
Use a dedicated
settings.xmland local Maven repository so the exercise cannot be confused with a developer's normal cache/configuration. - Resolve a public dependency through the Nexus group and distinguish first proxy fetch from later cached use.
- Deploy synthetic snapshot and release components with the Maven Deploy Plugin only to hosted repositories.
- Verify Maven metadata, component/assets, and checksums after each mutation.
Disposable only. Use a local Nexus 3.95.2 Community instance on loopback. Create a dedicated lab user rather than reusing a production identity. The tutorial never asks for a real company namespace, public endpoint, or administrator password in a command line.
1. Preflight: prove versions and isolate the Maven client
Start with evidence, then create a lab directory. Maven's default
local cache at ~/.m2/repository can hide whether Nexus
served a request, so this chapter gives Maven a separate local
repository. That isolation is as important as the disposable Nexus
repositories.
set -eu
NX_URL=http://127.0.0.1:8081
LAB="${TMPDIR:-/tmp}/academy-nexus-ch06"
rm -rf "$LAB"
mkdir -p "$LAB/m2" "$LAB/project" "$LAB/evidence"
mvn --version | tee "$LAB/evidence/00-maven-version.txt"
curl -fsS "$NX_URL/service/rest/v1/status" | tee "$LAB/evidence/01-nexus-status.txt"
printf 'Lab directory: %s
' "$LAB"
2. Create four repositories with one responsibility each
In Settings → Repository → Repositories, create the following lab-only Maven repositories. Using the UI here makes the policy fields visible to beginners; later chapters automate repository creation via REST.
| Name | Recipe / important settings | Why |
|---|---|---|
academy-ch06-releases |
maven2 hosted · Version policy Release · Layout Strict · Deployment policy Disable redeploy | Stable internal publication target. |
academy-ch06-snapshots |
maven2 hosted · Version policy Snapshot · Layout Strict · Deployment policy Allow redeploy | Repeated development publications and metadata updates. |
academy-ch06-central |
maven2 proxy · Release · Strict ·
https://repo1.maven.org/maven2/
|
Controlled/cacheable route to Central. |
academy-ch06-public |
maven2 group · members releases, snapshots, central in that order | One read endpoint for Maven. |
Record the repository list after creation. The configuration lives in Nexus relational state; proxied or uploaded repository file bytes live in the selected blob store.
curl -fsS "$NX_URL/service/rest/v1/repositories" > "$LAB/evidence/02-repositories-after.json"
grep -E 'academy-ch06-(releases|snapshots|central|public)' "$LAB/evidence/02-repositories-after.json" || true
3. Create a disposable publisher identity
Create a local Nexus user named
academy-ch06-publisher and grant only the privileges
needed to read/browse the group and add/edit content in the two
hosted lab repositories. Do not use the built-in administrator as a
Maven CI pattern. The exact privilege construction is covered deeply
in Chapter 15; here the point is to keep the credential scope
smaller than instance administration.
Load the disposable credentials into environment variables interactively:
read -r -p 'Disposable Nexus username: ' NX_USER
read -r -s -p 'Disposable Nexus password: ' NX_PASS; echo
export NX_USER NX_PASS
Environment variables are used only to keep this lab from embedding a password in HTML, shell history, or project files. For real CI, use the CI platform's secret store and Maven's supported credential protection; clear these variables during cleanup.
4. Build an isolated settings.xml
The mirror sends repository reads to the Nexus group. The profile
enables both releases and snapshots on the logical
central repository so the mirror can serve both from
the group. The two server IDs match the IDs used later by the Deploy
Plugin.
cat > "$LAB/settings.xml" <<'XML'
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<localRepository>${env.MAVEN_LAB_REPO}</localRepository>
<servers>
<server><id>academy-ch06-releases</id><username>${env.NX_USER}</username><password>${env.NX_PASS}</password></server>
<server><id>academy-ch06-snapshots</id><username>${env.NX_USER}</username><password>${env.NX_PASS}</password></server>
</servers>
<mirrors>
<mirror><id>academy-ch06-public</id><mirrorOf>*</mirrorOf><url>http://127.0.0.1:8081/repository/academy-ch06-public/</url></mirror>
</mirrors>
<profiles>
<profile><id>academy-ch06</id><repositories><repository><id>central</id><url>http://central.invalid/</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository></repositories><pluginRepositories><pluginRepository><id>central</id><url>http://central.invalid/</url><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></pluginRepository></pluginRepositories></profile>
</profiles>
<activeProfiles><activeProfile>academy-ch06</activeProfile></activeProfiles>
</settings>
XML
export MAVEN_LAB_REPO="$LAB/m2"
5. Resolve a harmless public dependency through the group
Use Apache Commons Lang only as a read test. A fresh local cache means the first request must leave Maven, hit the group, enter the Central proxy if no hosted member owns the coordinate, reach Central, then populate Nexus proxy state and the isolated Maven cache. A second resolution may be served without the same upstream work.
mvn -s "$LAB/settings.xml" -U org.apache.maven.plugins:maven-dependency-plugin:3.9.0:get -Dartifact=org.apache.commons:commons-lang3:3.20.0 | tee "$LAB/evidence/03-first-resolution.txt"
mvn -s "$LAB/settings.xml" org.apache.maven.plugins:maven-dependency-plugin:3.9.0:get -Dartifact=org.apache.commons:commons-lang3:3.20.0 | tee "$LAB/evidence/04-second-resolution.txt"
Verify in Nexus Browse/Search that the component now exists in
academy-ch06-central. That observation separates
Nexus proxy cache from Maven's local cache: both
may now hold copies, but they are different state stores with
different owners and eviction rules.
6. Create deterministic synthetic Maven files
We use tiny ZIP-based JARs rather than source code so the lesson focuses on repository semantics, not Java compilation.
mkdir -p "$LAB/project/payload"
printf 'chapter=06
artifact=ch06-demo
content=v1
' > "$LAB/project/payload/info.txt"
(cd "$LAB/project/payload" && jar --create --file ../ch06-demo.jar info.txt)
cat > "$LAB/project/release-pom.xml" <<'XML'
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><groupId>com.example.academy</groupId><artifactId>ch06-demo</artifactId><version>1.0.0</version><packaging>jar</packaging></project>
XML
cat > "$LAB/project/snapshot-pom.xml" <<'XML'
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><groupId>com.example.academy</groupId><artifactId>ch06-demo</artifactId><version>1.1.0-SNAPSHOT</version><packaging>jar</packaging></project>
XML
sha256sum "$LAB/project/ch06-demo.jar" | tee "$LAB/evidence/05-source-sha256.txt"
Windows PowerShell: create the same files under a
temporary folder, use the JDK jar.exe, and record
SHA-256 with Get-FileHash -Algorithm SHA256. If
jar is unavailable, use a ZIP utility and name the
archive .jar; the fixture contains no executable
code.
7. Deploy snapshot, then release, to hosted targets only
repositoryId selects the matching
<server> entry. The URL selects the hosted Nexus
target. The client uploads POM/JAR data; Nexus validates repository
format/version/deployment policies, writes relational metadata,
stores assets in the blob store, and updates Maven metadata where
required.
mvn -s "$LAB/settings.xml" org.apache.maven.plugins:maven-deploy-plugin:3.1.4:deploy-file -DrepositoryId=academy-ch06-snapshots -Durl="$NX_URL/repository/academy-ch06-snapshots/" -Dfile="$LAB/project/ch06-demo.jar" -DpomFile="$LAB/project/snapshot-pom.xml" | tee "$LAB/evidence/06-snapshot-deploy.txt"
mvn -s "$LAB/settings.xml" org.apache.maven.plugins:maven-deploy-plugin:3.1.4:deploy-file -DrepositoryId=academy-ch06-releases -Durl="$NX_URL/repository/academy-ch06-releases/" -Dfile="$LAB/project/ch06-demo.jar" -DpomFile="$LAB/project/release-pom.xml" | tee "$LAB/evidence/07-release-deploy.txt"
8. Verify metadata, bytes, and group visibility independently
curl -fsS "$NX_URL/repository/academy-ch06-public/com/example/academy/ch06-demo/1.0.0/ch06-demo-1.0.0.jar" -o "$LAB/evidence/retrieved-release.jar"
sha256sum "$LAB/project/ch06-demo.jar" "$LAB/evidence/retrieved-release.jar"
curl -fsS "$NX_URL/repository/academy-ch06-snapshots/com/example/academy/ch06-demo/1.1.0-SNAPSHOT/maven-metadata.xml" | tee "$LAB/evidence/08-snapshot-metadata.xml"
curl -fsS "$NX_URL/service/rest/v1/search?repository=academy-ch06-releases&group=com.example.academy&name=ch06-demo" | tee "$LAB/evidence/09-release-search.json"
The two SHA-256 values should match. Snapshot metadata should
contain timestamp/build information that connects
1.1.0-SNAPSHOT to a unique stored snapshot. Search
should return the release component and assets.
9. Challenge: choose the control, do not copy a sequence
A developer asks to publish 1.2.0-SNAPSHOT but proposes
sending it to academy-ch06-public because that is the
URL in settings.xml. Decide which endpoint must receive
the deployment and explain three states that would change if it
succeeds.
Expected reasoning: deploy to
academy-ch06-snapshots. The hosted repository's Maven
metadata/database records change, snapshot assets are written to its
blob store, and the group can subsequently expose them to readers.
The group is the read aggregation boundary, not the ordinary
authoritative publish target for this lab.
Knowledge check
Why did the lab use a separate Maven local repository?
To make cache effects observable and prevent the learner's normal ~/.m2 cache from satisfying requests before Nexus is contacted.
Which Nexus repository should receive
1.1.0-SNAPSHOT?
The hosted snapshot repository because its version policy is Snapshot and it is the authoritative publication target.
What should change after the first Central resolution but not necessarily after the second?
The first can populate the Nexus proxy cache and Maven local cache; later requests may be served from one of those caches without another upstream fetch.
Why is matching the source and retrieved SHA-256 useful?
It proves the bytes returned through the group match the bytes published for that fixture. It still does not prove trusted origin or vulnerability safety.
Where should a CI publisher password live in a real pipeline?
In the CI platform's protected secret/credential mechanism or another approved credential store, injected at runtime—not committed to a POM/settings file or passed as a visible command-line argument.
10. Summary
You created a four-repository Maven topology, isolated the client, observed proxy behavior, deployed snapshot/release components to hosted targets, and verified metadata plus exact bytes. The next lesson evaluates the policy choices behind that design.
Official references and version notes
- Nexus Repository Download and 3.95.x release notes — current self-hosted baseline.
- Sonatype: Maven Repositories — Maven version/layout policies, default repositories, grouping, settings and deployment examples.
- Configurable Repository Fields — hosted deployment policy, proxy caching, and group ordering.
- Components API and REST API Reference — supported component/asset inspection and upload boundaries.
- Apache Maven Download — current Maven 3 stable line.
- Apache Maven Settings Reference — localRepository, servers, mirrors, environment interpolation and profiles.
-
Using Mirrors for Repositories
—
mirrorOfmatching and single-repository patterns. - Apache Maven Deploy Plugin — deployment goals and repository-id matching.
- Maven Central repository endpoint — upstream used by the disposable proxy.
Version-sensitive statements were rechecked against Sonatype and Apache Maven primary documentation on 2026-08-26. The mandatory lab pins Nexus Repository Community Edition 3.95.2 and Apache Maven 3.9.16. Nexus 3.95.2 was released 2026-08-21; Maven 3.9.16 is the current recommended Maven 3 release. Nexus 3.87+ requires Java 21 when using an external JVM and official Nexus packages include a bundled Java 21 runtime. Re-check live support/download pages before executing these labs.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.