Chapter 18Lesson 05240–330 min

Checkpoint Lab — Cleanup Policies, Retention, Component Age, Last-Downloaded Rules, Preview, and Storage Reclamation

Design and execute a complete synthetic retention change: define an SLA, model controlled age/usage evidence, preview a deterministic disposable policy, perform supported logical cleanup, prove what remained, measure reclamation separately, and produce an auditable runbook.

CheckpointRetention SLAEvidence packetRecoveryRunbook

Checkpoint objectives

  • Translate a business retention requirement into explicit policy logic and safety gates.
  • Predict at least two repository/storage changes before execution and verify both independently.
  • Use Community-compatible Nexus operations and a faithful age/usage fixture.
  • Demonstrate the difference between logical deletion and physical reclamation.
  • Deliver an evidence packet and production-shaped runbook that can be reviewed by another operator.

1. Checkpoint brief

You are the artifact-platform operator for a fictional service team. CI produces disposable development artifacts, but the team needs a 30-day debugging window and wants artifacts retained longer when they remain in active use. Releases are not eligible for automatic deletion in this exercise. Storage pressure requires verified reclamation, but only after the logical cleanup set is accepted.

Retention SLA. Development artifact is eligible only when age ≥ 30 days AND last download ≥ 14 days. Release artifacts are protected. Preview is mandatory. Soft-deleted content receives a documented grace period before compaction in production. The live lab uses a deterministic Raw path matcher for immediate execution; the age/usage decision is proven with a synthetic fixture because you must not forge Nexus timestamps.

Version baseline (26 August 2026). Sonatype's current 3.95.x release notes list Nexus Repository 3.95.2 (released 21 August 2026) as the newest patch in that line. The 3.95 release expanded cleanup-policy administration and retain-last-N coverage. Current Nexus Repository 3.95.x system requirements use Java 21; official bundles include the recommended runtime. Record the exact version, edition, database, and blob-store type of your lab before applying any cleanup rule because cleanup behavior and available criteria are version- and format-sensitive.

2. Safety gates

Gate Pass condition
Instance Disposable local Nexus only; no public exposure
Repository cleanup-checkpoint-raw is new and contains only synthetic lab files
Blob store Prefer cleanup-checkpoint-blobs dedicated to this repository
Credentials Temporary lab account; secrets supplied through environment variables; no real tokens in output
Edition Mandatory path works without Pro; retain-last-N and cleanup-policy REST management remain optional theory
Docker Not used for Last Downloaded due current 3.95.2 known issue
Recovery No compaction until candidate set and logical deletion are verified

3. Write predictions before touching Nexus

Your evidence packet must contain these predictions in your own words before execution:

  1. Prediction A — selection: a deterministic live policy matching ^/learner-example/checkpoint/expire/.*$ will select exactly three expire-path assets and no release-path asset.
  2. Prediction B — logical deletion: after the cleanup service runs, expire paths will become unavailable from a fresh client while protected paths remain retrievable.
  3. Prediction C — physical state: logical deletion will not guarantee immediate capacity recovery; compacting the dedicated blob store is the separate physical-reclamation step.

If your preview contradicts Prediction A, stop. The checkpoint is testing diagnosis, not obedience to a sequence.

4. Create the controlled retention dataset

Create this local fixture as checkpoint-retention.csv:

artifact,published_days_ago,last_downloaded_days_ago,class,expected
build-201,61,40,development,DELETE-CANDIDATE
build-202,45,3,development,KEEP-RECENTLY-USED
build-203,10,10,development,KEEP-TOO-NEW
release-5.4.0,120,100,release,KEEP-RELEASE
release-5.5.0,20,5,release,KEEP-RELEASE

Evaluate it with a small script. The code represents the SLA; it does not write to Nexus.

import csv
AGE = 30
IDLE = 14

with open("checkpoint-retention.csv", newline="", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        candidate = (
            row["class"] == "development"
            and int(row["published_days_ago"]) >= AGE
            and int(row["last_downloaded_days_ago"]) >= IDLE
        )
        actual = "DELETE-CANDIDATE" if candidate else (
            "KEEP-RELEASE" if row["class"] == "release" else
            "KEEP-RECENTLY-USED" if int(row["last_downloaded_days_ago"]) < IDLE else
            "KEEP-TOO-NEW"
        )
        print(row["artifact"], actual, "OK" if actual == row["expected"] else "MISMATCH")

Expected outcome: only build-201 is eligible under the age/usage SLA. Explain why each other row is retained before continuing.

5. Live setup: isolated repository and blob store

  1. Record Nexus version, edition, runtime, database, and current repository/task list.
  2. Create file blob store cleanup-checkpoint-blobs if safe and supported in your disposable lab.
  3. Create Raw hosted repository cleanup-checkpoint-raw using that store.
  4. Create/use a temporary writer identity and a separate reader identity if practical.
  5. Do not enable anonymous write and do not reuse production credentials.

Upload five tiny files: three under learner-example/checkpoint/expire/ and two under learner-example/checkpoint/protected/.

BASE='http://127.0.0.1:8081'
REPO='cleanup-checkpoint-raw'
: "${NEXUS_USER:?set disposable writer}"
: "${NEXUS_PASS:?set disposable password}"

mkdir -p checkpoint-files
printf 'build 201\n' > checkpoint-files/build-201.txt
printf 'build 202\n' > checkpoint-files/build-202.txt
printf 'build 203\n' > checkpoint-files/build-203.txt
printf 'release 5.4.0\n' > checkpoint-files/release-5.4.0.txt
printf 'release 5.5.0\n' > checkpoint-files/release-5.5.0.txt

for f in build-201 build-202 build-203; do
  curl -fsS -u "$NEXUS_USER:$NEXUS_PASS" --upload-file "checkpoint-files/$f.txt"     "$BASE/repository/$REPO/learner-example/checkpoint/expire/$f.txt"
done
for f in release-5.4.0 release-5.5.0; do
  curl -fsS -u "$NEXUS_USER:$NEXUS_PASS" --upload-file "checkpoint-files/$f.txt"     "$BASE/repository/$REPO/learner-example/checkpoint/protected/$f.txt"
done
sha256sum checkpoint-files/*.txt > checkpoint-sha256.txt

6. Baseline evidence

Before policy creation, capture:

  • repository name, format, type, and blob-store assignment;
  • five Browse/search paths;
  • five controlled GET/HEAD outcomes;
  • local SHA-256 file;
  • blob-store/volume capacity observation;
  • cleanup-service and compact-task schedules;
  • policy list showing that cleanup-checkpoint-expire does not yet exist.

This baseline is what makes post-run differences meaningful.

7. Create and preview the policy

Create Raw cleanup policy cleanup-checkpoint-expire with:

Asset Name Matcher (H2/PostgreSQL Java regex):
^/learner-example/checkpoint/expire/.*$

Associate it only with cleanup-checkpoint-raw. In 3.95 the current UI can manage repository association from policy configuration; an exact patch/interface may also expose association from the repository Cleanup section. Use the supported screen shown by your running version.

Preview the policy and compare it with Prediction A. The preview must include exactly the three build paths and exclude both protected release paths. Save a screenshot or exported report if available.

If the candidate set is not exact, do not execute. Correct the pattern or association, preview again, and explain the mistake in the evidence packet.

8. Execute logical cleanup

Run the current system cleanup service task manually in the disposable lab or wait for its schedule. Record task status and timing. Then verify with a fresh controlled client:

check() {
  local path="$1"
  curl -sS -o /dev/null -w '%{http_code}' -u "$NEXUS_USER:$NEXUS_PASS"     "$BASE/repository/$REPO/$path"
}

printf 'expire build-201: %s\n' "$(check learner-example/checkpoint/expire/build-201.txt)"
printf 'expire build-202: %s\n' "$(check learner-example/checkpoint/expire/build-202.txt)"
printf 'expire build-203: %s\n' "$(check learner-example/checkpoint/expire/build-203.txt)"
printf 'protected 5.4.0: %s\n' "$(check learner-example/checkpoint/protected/release-5.4.0.txt)"
printf 'protected 5.5.0: %s\n' "$(check learner-example/checkpoint/protected/release-5.5.0.txt)"

The three expire paths should be unavailable and the two protected paths should remain available. Confirm with Browse/search too. This satisfies Prediction B.

9. Prove logical versus physical state

Record capacity immediately after logical cleanup. Do not expect a four-digit filesystem delta from tiny files; the key fact is that repository visibility changed before hard-deletion/compaction. Inspect task history and blob-store status rather than individual blob files.

Evidence Before cleanup After logical cleanup After compaction
Expire paths Readable Unavailable Unavailable
Protected paths Readable Readable Readable
Soft-deleted blob state None from this action Can remain Eligible entries permanently removed
Filesystem/blob capacity Baseline May look similar May improve; tiny lab may be below visible granularity
Recovery flexibility Full Greater than after hard deletion Depends on validated external backup/recovery

10. Optional live compaction on the dedicated lab blob store

If cleanup-checkpoint-blobs contains only checkpoint content, configure/run Admin - Compact blob store for that store after accepting the deletion set. Record the Blobs Older Than value and explain what grace period it creates. For immediate training proof you may use a lab-appropriate value only on this disposable store; in production, choose a deliberate recovery window.

If the store is shared or its ownership is uncertain, do not compact. Mark Prediction C as verified conceptually from the state model and official task documentation, and note that physical reclamation was intentionally skipped for safety.

11. Failure injection: catch a dangerous change before execution

Temporarily edit the policy matcher in your notes—not in a production system—to this broader pattern:

^/learner-example/checkpoint/.*$

Predict that it would now include both expire and protected paths. If your disposable UI allows a safe preview without running cleanup, preview the broadened rule and confirm the dangerous selection, then restore the narrow policy and preview again. This is the key operational skill: preview should stop an unsafe change before mutation.

12. Produce the retention runbook

Your runbook must contain:

  1. Purpose: which artifact class is being controlled and why.
  2. Scope: exact repository names, formats, types, blob stores, edition/database assumptions.
  3. Criteria: age, usage, release/asset rules with plain-language semantics.
  4. Known issues: version-specific caveats such as Docker lastDownloaded behavior.
  5. Preflight: version, capacity, backup/recovery status, task conflicts, policy attachment.
  6. Preview gate: who reviews candidate evidence and what is unacceptable.
  7. Execution: which supported Nexus task/API/UI action runs cleanup.
  8. Verification: representative kept/deleted coordinates or paths from fresh clients.
  9. Reclamation: compact task, grace period, maintenance window, and expected IO.
  10. Rollback: stop compaction, preserve evidence, supported recovery/backup path.
  11. Cleanup of lab resources: repository, policy, blob store, local files, credentials.

13. Required evidence packet

Artifact Minimum content
environment.txt Nexus version/edition, Java, database, blob-store type
retention-sla.md 30/14-day rule, release protection, owners, assumptions
checkpoint-retention.csv controlled age/usage fixture
fixture-evaluation.txt script output proving candidate logic
checkpoint-sha256.txt pre-upload artifact identity
preview evidence policy name, repo, matcher, candidate paths/count, timestamp
task evidence cleanup task result and compact result/skipped rationale
verification.txt fresh-client HTTP outcomes for deleted/protected paths
capacity.txt before/logical-cleanup/post-compaction observations
runbook.md production-shaped operating procedure and rollback

14. Cleanup and rollback

  1. Detach the checkpoint policy.
  2. Delete the checkpoint repository through supported Nexus administration.
  3. Delete the policy if nothing else references it.
  4. Delete the dedicated blob store only after Nexus confirms it is unused.
  5. Remove local fixture/payload files after saving the evidence packet outside the disposable instance.
  6. Unset temporary credentials and remove the lab user if created solely for this exercise.
  7. Do not delete internal Nexus database/blob files manually.

15. Knowledge check

Why are there two datasets in the checkpoint—a live Raw path set and a CSV age/usage fixture?

What is the single most important gate before cleanup execution?

A policy preview selects a release that must be retained. What should you do?

Why is compaction not part of “proving the policy matched correctly”?

What evidence would you preserve first if an important artifact disappeared?

What new operational subject follows this chapter?

16. Chapter checkpoint summary

You can now treat repository retention as an auditable control: define lifecycle intent, model age and usage, respect format/version caveats, preview before mutation, execute supported logical cleanup, verify kept/deleted content, delay hard reclamation until accepted, and preserve a recovery path. The next chapter generalizes this operational discipline to Nexus scheduled tasks, repair jobs, metadata rebuilds, and housekeeping.

Official references and version notes

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.