REST API, Repository Provisioning, Security Automation, Pagination, and Infrastructure-as-Code Patterns: Concepts, Architecture, and Mental Model
Build the automation mental model before writing curl commands: the REST API is a versioned control-plane boundary over Nexus configuration and security state, while package content, repository metadata, database records, blob bytes, credentials, and external systems remain distinct state domains.
Learning objectives
- Locate and interpret the instance-specific OpenAPI/Swagger contract before mutation.
- Separate API resources, repository content endpoints, database/blob state, and client configuration.
- Explain authentication, authorization, JSON request/response semantics, and HTTP outcomes.
- Implement the continuation-token mental model without assuming one-page results.
- Explain desired state, actual state, idempotence, drift, and version-aware reconciliation.
Version baseline (26 August 2026). These lessons
use Sonatype Nexus Repository 3.95.2-01 as the
dated self-hosted reference point, verified from Sonatype's public
release repository, with Java 21 as the current runtime requirement.
The mandatory lab assumes a small, disposable, loopback-only
self-hosted Community Edition installation using H2 and a file blob
store. The local instance's own
/service/rest/swagger.json is authoritative for the
exact endpoint schema you are about to call; API fields, repository
recipes, security endpoints, and edition entitlements can change
between releases.
Automation safety boundary. Do not put real passwords, user-token passcodes, Authorization headers, production base URLs, or employer namespaces into source files or lesson evidence. The examples use environment variables, synthetic names, loopback URLs, and disposable resources. User Tokens are a Pro capability in current self-hosted Nexus Repository; Community labs therefore use a disposable local account/password only for bootstrap and immediately reduce privileges for the service identity.
Pagination documentation note. Current Sonatype
pages agree on the continuationToken contract but
currently disagree on the documented default item count for
components/assets. The robust automation rule is independent of page
size: process every returned items array, pass the
returned token unchanged, and stop only when
continuationToken is null.
1. The practical problem: repeatability without hidden clicks
Manual administration can be appropriate for learning or one-off recovery, but repeated repository provisioning through the browser has three weaknesses: intent is difficult to review, repeated clicks can create drift, and there is no reliable machine-readable record of what the operator expected. Chapter 20 moves the same repository and security concepts you already know into a documented HTTP control plane.
The goal is not “turn every click into curl.” The goal is reconciliation: inspect actual state, compare it with desired state, mutate only the difference, verify the result, and preserve enough evidence to understand failures.
2. Mental model: control plane versus artifact data plane
flowchart TD D[Desired state file / script] --> C[Reconciler] C -->|HTTPS /service/rest/v1| A[Nexus REST API] A --> Z[Authorization] Z --> R[Repository + security configuration] R --> DB[(Database metadata)] R --> B[(Blob-store references)] P[Package client / CI] -->|repository protocol| E["/repository/... endpoint"] E --> DB E --> B A --> J[HTTP result + JSON] J --> C C --> V[Independent verification]
The automation client is a new actor, not a replacement for Maven,
npm, Docker, pip, or NuGet. Administrative REST calls normally
target /service/rest/.... Package clients continue to
talk to repository-format endpoints. Keeping these paths distinct
prevents a common mistake: treating a successful admin API call as
proof that a package workflow works.
3. The API contract lives with the instance
Current Nexus Repository exposes its OpenAPI document at
<nexus_url>/service/rest/swagger.json and Swagger
UI under Settings → System → API. The document is machine-readable
and tied to the running server.
export NEXUS_URL='http://127.0.0.1:8081'
curl --fail --silent --show-error \
"$NEXUS_URL/service/rest/swagger.json" \
--output /tmp/nexus-swagger.json
python - <<'PY'
import json
p = json.load(open('/tmp/nexus-swagger.json', encoding='utf-8'))
print('basePath:', p.get('basePath'))
for path in sorted(p.get('paths', {})):
if path.startswith('/v1/repositories'):
print(path)
PY
This inspection establishes what the server claims to support before your script sends a mutation. Do not copy a payload from another release and assume fields are unchanged.
4. REST resources and state ownership
| Resource family | Typical intent | State affected | Independent verification |
|---|---|---|---|
| Status | Read readiness/writability/system checks | No intended mutation | HTTP result plus logs/metrics if unhealthy |
| Repositories | List/create/update/delete repository configuration | Repository configuration; deletion can affect stored content references | GET repository + content request + component/assets |
| Components/assets/search | Inspect or operate on stored package objects | Repository metadata and, for mutations, associated blob state | All pages + checksum/download test |
| Security users/roles/privileges | Manage local authorization objects | Security configuration | GET objects + positive/negative authorization tests |
| Tasks | Inspect/run server-side jobs | Depends on task type | Task history/log + affected-state verification |
Chapter 19 is why the final row says “depends.” An endpoint can schedule a job, but the state transition belongs to that task type, not to HTTP itself.
5. Authentication answers “who”; privileges answer “may they do this?”
REST automation needs an identity. In a disposable Community lab, a local account can authenticate with HTTP Basic authentication. In production, prefer a dedicated automation identity and a supported credential mechanism appropriate to your edition and identity architecture. Current self-hosted User Tokens are Pro-only, so they are not required in this chapter's Community path.
A user who can browse a repository is not automatically allowed to create repositories or users. For every automation identity, document the endpoint families and repository paths it needs, then grant the smallest privileges that satisfy that scope.
6. JSON is a contract, not decoration
Many create/update endpoints accept JSON. Distinguish:
- Identity fields such as repository name or role ID.
- Desired configuration fields such as online state, blob store, write policy, or member order.
- Server-generated/read-only fields that may appear in GET responses but must not be blindly echoed into PUT/POST unless the OpenAPI schema permits them.
An IaC-style tool normalizes the fields it owns, compares only those fields, and leaves unrelated server-managed data alone.
7. HTTP status codes are control flow
| Class/example | Automation interpretation | Safe response |
|---|---|---|
| 2xx | Request succeeded according to endpoint contract | Still verify resulting Nexus state |
| 400 | Payload/query violates current contract | Stop; inspect body and local Swagger; do not retry unchanged |
| 401 | Authentication failed/missing | Fix credential path; never print secret |
| 403 | Identity authenticated but lacks authorization | Inspect required privilege; avoid nx-admin as a shortcut |
| 404 | Resource/path not found; malformed URLs can also fail after Jetty 12 stricter parsing | Validate base URL/path/encoding/version |
| 409 | Conflict with current resource/state | Re-read actual state and decide whether conflict is expected drift |
8. Pagination: “200 OK” can still mean “incomplete inventory”
List APIs that return items plus
continuationToken tell you whether another request is
required. Treat the token as opaque.
{
"items": [{"id": "opaque-id", "repository": "learner-api-hosted"}],
"continuationToken": "opaque-token-from-server"
}
Repeat the original filters and add the returned token. Continue
until continuationToken is null.
Processing only the first response can silently miss artifacts and
make unsafe cleanup, migration, or audit decisions.
9. Desired state, actual state, and the reconciliation loop
flowchart TB
S[Load desired state] --> G[GET actual state]
G --> N[Normalize owned fields]
N --> D{Difference?}
D -->|No| K[No-op / verify]
D -->|Create missing| P[POST]
D -->|Update drift| U[PUT]
D -->|Delete only explicit managed lab resource| X[DELETE]
P --> V[GET + functional verification]
U --> V
X --> V
K --> V
Idempotent means rerunning automation against already-correct state produces no unintended additional change. Your reconciliation logic—not the mere choice of an HTTP verb—creates that property.
10. Drift requires an ownership policy
If automation creates a repository with strict content-type validation enabled and a human later disables it, the next run must know whether to restore it, report drift for approval, accept the change into desired state, or ignore the field because another owner controls it. Without an ownership rule, reconciliation becomes a fight between scripts and operators.
11. API version drift and URL correctness
New releases can add fields, formats, endpoints, constraints, or permissions. Since 3.81.0, Jetty 12 also enforces stricter URL parsing; malformed query parameters that older versions tolerated can return 404. Encode query parameters according to RFC 3986 and prefer an HTTP library that performs safe encoding over hand-built query strings.
12. Read-only preflight before mutation
- Record Nexus version/edition and Java runtime.
-
Fetch
swagger.jsonand confirm required paths exist. -
GET
/service/rest/v1/statusand/service/rest/v1/status/writable. - GET repositories and identify the disposable blob store.
- GET privileges and later verify exact repository-view privilege IDs for your lab repository.
- Confirm the base URL resolves only to the disposable loopback/private instance.
- Confirm secret environment variables exist without printing their values.
13. Why this matters in DevOps
Reviewable desired state improves onboarding, disaster reconstruction, environment parity, auditability, and change review. The diff itself becomes an operational artifact: it shows what automation intended to change before Nexus is changed.
14. Knowledge check
Why read the running instance's Swagger document before sending a copied payload?
Endpoint paths, fields, constraints, and entitlements are version-sensitive; the instance-specific schema is the contract for that server.
A components request returns HTTP 200 and a non-null continuationToken. Is inventory complete?
No. Another page exists. Continue until the token is null.
Does using PUT automatically make the provisioning workflow idempotent?
No. Idempotence requires reading actual state, comparing owned fields, handling conflicts, and verifying results.
Why is a successful repository-creation API call not proof that package clients can use it?
Control-plane configuration and data-plane protocol/authentication are different boundaries.
15. Summary and next step
You now have the control-plane model: inspect OpenAPI, authenticate without leaking credentials, authorize narrowly, understand JSON and HTTP outcomes, paginate to completion, compare desired and actual state, and reconcile only owned fields. Lesson 2 turns that model into a disposable API workflow.
Official references and version notes
- Sonatype: Automation / REST API — OpenAPI/Swagger location, API integration, and Jetty 12 URL-encoding requirements.
- Sonatype: Nexus Repository API Reference — current endpoint catalog and request/response models.
- Sonatype: Repositories API — generic and format/type-specific repository configuration endpoints.
- Sonatype: Components API — component list/get/upload/delete behavior and continuation tokens.
- Sonatype: Pagination — continuation-token iteration contract.
- Sonatype: Security Management API — users, roles, privileges, content selectors, LDAP/SAML/OIDC boundaries.
- Sonatype: Authentication — local/external authentication and automation identity boundaries.
- Sonatype: User Tokens — current self-hosted Pro entitlement and token behavior.
- Sonatype: System Requirements — Java/database/storage baseline.
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.