Checkpoint Lab — Artifact Repository Foundations, Package Supply Chains, Components, Assets, and Repository Managers
Complete an integrated multi-ecosystem checkpoint: publish synthetic Maven and npm artifacts, prove coordinates and bytes, map trust boundaries, inject a safe failure, and clean up.
Learning objectives
- Map a small multi-ecosystem supply chain from producer to hosted repository to consumer.
- Publish only synthetic Maven and npm artifacts to disposable hosted repositories.
- Record component coordinates, assets, metadata, checksums, repository type, and trust boundaries.
- Predict repository and blob/metadata state changes before executing them.
- Produce an evidence packet that distinguishes Nexus state from client-local state.
- Clean up the entire lab without touching shared repositories, blob stores, databases, or production credentials.
Checkpoint safety. This lab creates and deletes
repository content. Use only a disposable local Community instance
or a dedicated training namespace explicitly approved for deletion.
The artifact names contain academy-ch01 and
DO_NOT_DEPLOY by design. If you cannot obtain an
isolated Nexus instance, complete the fixture/simulation path and
mark execution evidence as simulated rather than using a production
server.
Shell note. Executable examples use POSIX/Bash. On
Windows, use equivalent PowerShell filesystem/hash commands plus
curl.exe or Invoke-RestMethod; store
temporary credentials in a private file and delete it immediately
after each authenticated request.
1. Scenario and success criteria
You are onboarding a small service team that produces a Java library and a JavaScript utility. The team must understand what Nexus stores, how two package ecosystems differ, and why release evidence needs both logical coordinates and exact byte identity. You will create one disposable Maven hosted repository and one disposable npm hosted repository, upload synthetic packages, consume/inspect them through controlled endpoints, and then remove only the lab state.
flowchart LR JM[Java producer] --> MH[Maven hosted repository] NP[JavaScript producer] --> NH[npm hosted repository] MH --> NX[Nexus Repository service] NH --> NX NX --> JC[Java consumer] NX --> NC[npm consumer] NX --> DB[(Database metadata)] NX --> BLOB[(Blob store bytes)] CI[Future CI publisher] -. scoped credentials .-> NX
Pass conditions: exact repository format/type is recorded; both synthetic packages are visible as components/assets; locally calculated and downloaded package checksums match; no production secret/URL appears; client caches are identified separately; the evidence packet can explain every mutation; cleanup removes only the two lab repositories and local files.
2. Preflight and environment record
The content baseline is Nexus 3.95.2, released August 21, 2026. Your instance may be another supported version, so record it. Current Nexus requires Java 21; official installers/images normally include the recommended Java runtime. The lab itself does not require Pro features.
mkdir -p nexus-ch01-checkpoint/{evidence,maven,npm,downloads}
cd nexus-ch01-checkpoint
export NX_URL="http://127.0.0.1:8081"
curl -i "$NX_URL/service/rest/v1/status" | tee evidence/01-status.txt
curl -i "$NX_URL/service/rest/v1/status/writable" | tee evidence/02-writable.txt
curl -fsS "$NX_URL/service/rest/v1/repositories" | tee evidence/03-repositories-before.json | python -m json.tool
printf 'Nexus baseline checked: 3.95.2 / 2026-08-26\n' > evidence/00-version-assumptions.txt
Before creating anything, predict and write down these state changes:
- Creating two repositories will change repository configuration but create no package components yet.
- Uploading a Maven component may create multiple assets for one logical component; uploading an npm tarball creates an npm component with format metadata indexed by Nexus.
- Downloading from Nexus should not change the authoritative hosted package bytes, although access metadata/logs may change and the client may create local cache state.
3. Create two disposable hosted repositories
In the training UI, navigate to Settings → Repository → Repositories → Create repository. Create:
-
academy-ch01-mavenusing maven2 (hosted). -
academy-ch01-npmusing npm (hosted).
Use only a disposable/local blob store. Do not enable a Pro-only workflow merely for the lab. After creation, inspect the repositories API and confirm the two entries are hosted and have the intended formats.
curl -fsS "$NX_URL/service/rest/v1/repositories" | tee evidence/04-repositories-after.json | python -m json.tool
curl -fsS "$NX_URL/service/rest/v1/components?repository=academy-ch01-maven" | tee evidence/05-maven-empty.json | python -m json.tool
curl -fsS "$NX_URL/service/rest/v1/components?repository=academy-ch01-npm" | tee evidence/06-npm-empty.json | python -m json.tool
4. Build and upload a synthetic Maven component
No Maven build is required to learn repository semantics. Create a
tiny JAR-shaped archive with the JDK jar tool and an
explicit POM, then upload both as one Maven component through the
Components API. The content is non-executable training data.
cd maven
mkdir -p payload/META-INF
printf '%s\n' 'DevOps Academy CH01 synthetic Maven payload - DO_NOT_DEPLOY' > payload/README.txt
jar --create --file academy-ledger-1.0.0.jar -C payload .
cat > academy-ledger-1.0.0.pom <<'EOF'
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.academy</groupId>
<artifactId>academy-ledger</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>DevOps Academy synthetic checkpoint</name>
</project>
EOF
sha256sum academy-ledger-1.0.0.jar academy-ledger-1.0.0.pom | tee ../evidence/07-maven-local.sha256
cd ..
read -r -p 'Disposable Nexus username: ' NX_USER
read -r -s -p 'Disposable Nexus password: ' NX_PASS; echo
NX_AUTH_FILE="$(mktemp)"
chmod 600 "$NX_AUTH_FILE"
printf 'machine 127.0.0.1 login %s password %s
' "$NX_USER" "$NX_PASS" > "$NX_AUTH_FILE"
unset NX_PASS
curl --fail-with-body --netrc-file "$NX_AUTH_FILE" -X POST "$NX_URL/service/rest/v1/components?repository=academy-ch01-maven" -F 'maven2.groupId=com.example.academy' -F 'maven2.artifactId=academy-ledger' -F 'maven2.version=1.0.0' -F 'maven2.asset1=@maven/academy-ledger-1.0.0.jar' -F 'maven2.asset1.extension=jar' -F 'maven2.asset2=@maven/academy-ledger-1.0.0.pom' -F 'maven2.asset2.extension=pom'
rm -f "$NX_AUTH_FILE"
unset NX_USER NX_AUTH_FILE
Expected REST result is HTTP 204 for a successful component upload.
Then list the component and assets. Predict that one Maven component
at GAV com.example.academy:academy-ledger:1.0.0 owns at
least the uploaded JAR and POM assets; additional generated
checksum/metadata behavior depends on format/version and should be
observed rather than invented.
curl -fsS "$NX_URL/service/rest/v1/components?repository=academy-ch01-maven" | tee evidence/08-maven-components.json | python -m json.tool
curl -fsS "$NX_URL/service/rest/v1/assets?repository=academy-ch01-maven" | tee evidence/09-maven-assets.json | python -m json.tool
curl -fsS "$NX_URL/repository/academy-ch01-maven/com/example/academy/academy-ledger/1.0.0/academy-ledger-1.0.0.jar" -o downloads/academy-ledger-1.0.0.jar
sha256sum downloads/academy-ledger-1.0.0.jar | tee evidence/10-maven-downloaded.sha256
5. Build and upload a synthetic npm component
The npm path demonstrates a different coordinate model: package name + version rather than Maven GAV. Use the free npm CLI only to pack the synthetic tarball; upload it through the same Nexus Components API so no npm login/token workflow is required in this chapter.
cd npm
cat > package.json <<'EOF'
{
"name": "academy-ch01-widget",
"version": "1.0.0",
"description": "DevOps Academy synthetic Nexus checkpoint - DO_NOT_DEPLOY",
"main": "index.js",
"license": "UNLICENSED",
"private": false
}
EOF
printf '%s\n' 'module.exports = "DO_NOT_DEPLOY";' > index.js
# npm pack is free/local; it creates academy-ch01-widget-1.0.0.tgz.
npm pack
sha256sum academy-ch01-widget-1.0.0.tgz | tee ../evidence/11-npm-local.sha256
cd ..
read -r -p 'Disposable Nexus username: ' NX_USER
read -r -s -p 'Disposable Nexus password: ' NX_PASS; echo
NX_AUTH_FILE="$(mktemp)"
chmod 600 "$NX_AUTH_FILE"
printf 'machine 127.0.0.1 login %s password %s
' "$NX_USER" "$NX_PASS" > "$NX_AUTH_FILE"
unset NX_PASS
curl --fail-with-body --netrc-file "$NX_AUTH_FILE" -X POST "$NX_URL/service/rest/v1/components?repository=academy-ch01-npm" -F 'npm.asset=@npm/academy-ch01-widget-1.0.0.tgz'
rm -f "$NX_AUTH_FILE"
unset NX_USER NX_AUTH_FILE
curl -fsS "$NX_URL/service/rest/v1/components?repository=academy-ch01-npm" | tee evidence/12-npm-components.json | python -m json.tool
curl -fsS "$NX_URL/service/rest/v1/assets?repository=academy-ch01-npm" | tee evidence/13-npm-assets.json | python -m json.tool
If Node/npm is unavailable, do not install random tooling solely to
make the checkbox green. Use an instructor-provided synthetic
.tgz fixture or complete the npm half as a clearly
marked simulation: inspect the Components API documentation showing
npm.asset, predict the state, and retain “not executed
— npm unavailable” in the evidence packet.
6. Compare the two ecosystems without forcing one model onto the other
| Question | Maven example | npm example |
|---|---|---|
| Coordinate | com.example.academy:academy-ledger:1.0.0 |
academy-ch01-widget@1.0.0 |
| Primary upload | JAR + POM uploaded as assets of one Maven component |
Package .tgz uploaded as npm component asset;
Nexus indexes package metadata.
|
| Client protocol | Maven repository path + POM/metadata conventions | npm registry protocol/metadata. |
| Hosted authority | academy-ch01-maven |
academy-ch01-npm |
| Byte identity | SHA-256 of JAR/POM assets | SHA-256 of package tarball |
| Do not infer | JAR checksum does not prove trusted build/provenance | Tarball checksum does not prove trusted publisher/package safety |
The common Nexus abstraction helps operations: repositories have format/type, components have logical identity, assets have files/checksums, and APIs expose state. The ecosystem-specific coordinate and metadata rules still matter. This is the right balance between a universal repository mental model and protocol-specific correctness.
7. Controlled consumption and independent verification
For Maven, direct HTTP retrieval gives a deterministic checkpoint without requiring a full Maven project. For npm, you can either download the asset URL returned by the Assets API or, if your disposable account/realm/client configuration is already prepared, use the npm registry URL. In either case, calculate the downloaded SHA-256 and compare it to the producer-side record.
# Extract download URLs without assuming exact server-generated paths.
python - <<'PY2'
import json
for fn in ['evidence/09-maven-assets.json','evidence/13-npm-assets.json']:
data=json.load(open(fn, encoding='utf-8'))
print(fn)
for item in data.get('items',[]):
print(' ', item.get('path'), item.get('downloadUrl'), item.get('checksum'))
PY2
# Keep the evidence packet secret-free.
grep -RniE '(password|token-FAKE_DO_NOT_USE|Authorization:|_auth=)' evidence && echo 'Review matches before retaining evidence' || true
The best verification is independent: compare producer-side digest, Nexus-reported checksum when available, and digest of bytes downloaded from Nexus. If they disagree, stop and diagnose; do not rewrite the expected checksum.
8. Trust-boundary map and evidence packet
Create evidence/14-trust-boundaries.md with these rows:
| Boundary | Credential / identity | Evidence | Failure question |
|---|---|---|---|
| Producer → Maven hosted | Disposable publisher | HTTP upload response + component/assets + digest | Was the publisher authorized for this repository/coordinate? |
| Producer → npm hosted | Disposable publisher | Upload response + component/assets + tarball digest | Did the uploaded package metadata identify the expected name/version? |
| Consumer → Nexus | Anonymous or scoped reader | Download URL/status + downloaded digest | Did the consumer reach Nexus rather than a local cache/direct upstream? |
| Nexus → database/blob | Nexus service identity | Conceptual state map; no direct edits | Can metadata and bytes be recovered consistently? |
| Future CI → Nexus | Scoped non-human identity | Design note only in Ch01 | How would secret rotation and least privilege be enforced? |
The packet should include repository lists before/after, component/assets JSON, producer and consumer checksums, environment/version assumptions, and a short decision note. Screenshots may supplement, but machine-readable API evidence is easier to compare and sanitize.
9. Failure injection: predict first, then observe
Pick one safe failure. Recommended: change the Maven download URL
from academy-ch01-maven to
academy-ch01-mavne (intentional typo). Predict: no
repository with that name exists; hosted component/blob state should
not change; the client request should fail at routing/not-found
before authorization or component lookup matters.
curl -sS -D evidence/15-typo-headers.txt -o evidence/15-typo-body.txt -w 'http=%{http_code}\n' "$NX_URL/repository/academy-ch01-mavne/com/example/academy/academy-ledger/1.0.0/academy-ledger-1.0.0.jar" | tee evidence/15-typo-summary.txt
# Correct only the repository name and verify again.
curl -fsS "$NX_URL/repository/academy-ch01-maven/com/example/academy/academy-ledger/1.0.0/academy-ledger-1.0.0.jar" -o downloads/academy-ledger-retry.jar
sha256sum downloads/academy-ledger-retry.jar | tee evidence/16-retry.sha256
If your observation differs from the prediction, preserve it and explain the actual layer reached. The exercise is about causal reasoning, not forcing a predetermined HTTP code.
10. Cleanup and rollback
Before deleting anything, list repositories again and confirm the
exact two lab names. In the UI, delete only
academy-ch01-maven and academy-ch01-npm if
they were created solely for this checkpoint. Repository deletion is
destructive; never select a similarly named shared repository. Do
not delete or compact the blob store as part of Chapter 01.
unset NX_USER NX_PASS
cd ..
# Retain evidence if desired; otherwise remove only the checkpoint directory.
# rm -rf nexus-ch01-checkpoint
# Never substitute commands that delete Nexus data directories,
# database files, shared blob stores, or normal package-manager caches.
Rollback verification: the two lab repository names no longer appear in the repository list; no unrelated repository disappeared; the Nexus status endpoint remains serviceable; all retained evidence is sanitized.
11. What Chapter 01 adds to the operating model
You can now reason about Nexus without hiding behind UI clicks. You know what is authoritative, what is cached, how logical component identity differs from asset bytes, why protocols remain format-specific, which state changes when a repository/package is created, and how to prove those changes through APIs/checksums. That model is the prerequisite for installing and operating Nexus correctly rather than treating it as a generic file server.
Knowledge check
The Maven and npm components both have version
1.0.0. Are they the same coordinate?
No. Coordinates are format-specific. Maven uses fields such as group/artifact/version; npm identifies package name + version. The shared version string alone has no cross-format identity meaning.
After deleting the two hosted repositories, should you manually remove their blob files to “finish cleanup”?
No. Direct blob manipulation is outside the supported application lifecycle and can corrupt consistency. Cleanup must use supported Nexus operations and remain scoped to disposable state.
Your downloaded JAR digest matches the producer digest, but the source commit is unknown. Is provenance complete?
No. Byte identity is established, but source/build provenance is incomplete. Record source commit/build identity as separate evidence.
The npm CLI is unavailable. What is better: install an unverified binary from a random URL or mark the npm execution simulated using the official API schema?
Use the verified/free tooling path when available; otherwise mark the step simulated. Never weaken supply-chain hygiene merely to complete a lab.
Why did the typo failure not require cache deletion?
The error was at endpoint/repository routing. Changing unrelated client or server caches would destroy evidence and would not address the root cause.
Which chapter comes next, and why?
Chapter 02 covers Nexus editions, deployment models, architecture, installation, and Java runtime planning—the infrastructure needed to host the repository model learned here safely.
12. Summary
The checkpoint joined two ecosystems behind one repository-management discipline: hosted authorities, format-specific coordinates, component/assets evidence, exact byte digests, scoped publisher/consumer trust boundaries, API-based verification, predicted failure behavior, and controlled cleanup. You are ready to move from logical repository behavior to supported Nexus deployment architecture.
Official references and version notes
- Nexus Repository 3.95.0–3.95.2 release notes — 3.95.2 was released August 21, 2026 and is the current self-hosted baseline used in this chapter.
- Nexus Repository system requirements — current Java, H2/PostgreSQL, storage, memory, operating-system, and deployment constraints.
- Repository Manager Concepts — components, assets, coordinates, repository formats, proxy behavior, routing, and repository-manager purpose.
- Repository Types — hosted, proxy, and group semantics and group ordering.
- Self-Hosted Nexus Repository Feature Matrix — Community-versus-Pro capability boundaries.
- Nexus Repository API Reference — current REST API surface and embedded Swagger model.
- Status API — readiness and writable-state HTTP checks.
- Search API — component/asset search and the SQL-search behavior used by current releases.
- Components API — listing and uploading components to hosted repositories.
- Assets API — listing and inspecting individual assets.
- Uploading Components — hosted-only upload constraints and UI workflow.
- How Components are Defined within Nexus Repository — format-specific component identity and asset cardinality, including Raw and npm.
- Automation — current REST/Swagger access and request-format considerations.
Version-sensitive statements were rechecked against Sonatype primary documentation on 2026-08-26. The mandatory path remains self-hosted, Community/free-compatible, and disposable; production credentials, production repositories, and paid-only capabilities are outside the lab boundary.
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.