Chapter 10Lesson 01150–195 min

NuGet Repositories, API Keys, Feeds, Symbols, Proxying, and .NET Package Workflows: Concepts, Architecture, and Mental Model

Model .NET package delivery through Nexus: package ID/version identity, nupkg and snupkg assets, NuGet V2/V3 service endpoints, hosted/proxy/group feeds, API-key and read credentials, nuget.config, source mapping, symbols, caches, and trust boundaries.

NuGet V2/V3nupkg & snupkgAPI keysnuget.configFeed identity

Learning objectives

  • Separate package ID/version identity, a .nupkg archive, feed metadata, service-index resources, symbols, and restored package cache state.
  • Explain why a NuGet V3 source URL ends in /index.json and why omitting it can cause protocol auto-detection problems.
  • Map hosted, proxy, and group NuGet repositories to publish, cache, and aggregate-read responsibilities.
  • Distinguish repository credentials from NuGet deployment API keys and explain the NuGet API-Key Realm.
  • Explain package-source mapping, symbols, checksums/hashes, and deterministic package identity as different controls.

Current baseline. This chapter pins Nexus Repository Community Edition 3.95.2. NuGet hosted/proxy/group repositories and V2/V3 endpoints are available in Community. Nexus 3.95 introduced Chocolatey support plus .snupkg and Microsoft Symbol Server protocol support across NuGet hosted, proxy, and group repositories. The client lab pins .NET 10 SDK 10.0.400. The loopback lab uses HTTP only because it is isolated; production endpoints should use HTTPS.

1. The practical problem: a feed URL is not the package

Chapter 09 showed that a Python project, release, wheel, index entry, and installed import are separate objects. NuGet has the same need for precise boundaries. Learner.Ch10.Widget version 1.0.0 is a package identity. Learner.Ch10.Widget.1.0.0.nupkg is a ZIP-based package file containing compiled assemblies and package metadata. A V3 service index is a JSON document that advertises protocol resources. A client global-packages folder is yet another copy of package content.

If an operator says “NuGet is broken” without stating which feed endpoint, source configuration, package identity, repository member, cache, credential, or symbol path failed, troubleshooting begins with ambiguity. This chapter removes that ambiguity.

2. Package identity and concrete assets

Object Example Meaning
Package ID Learner.Ch10.Widget Logical NuGet package name.
Version 1.0.0 Release identity combined with package ID.
Package Learner.Ch10.Widget.1.0.0.nupkg Concrete ZIP-based package bytes and embedded nuspec metadata.
Symbol package Learner.Ch10.Widget.1.0.0.snupkg Companion portable-PDB package supported by Nexus 3.95+ V3 repositories.
Service index .../repository/academy-nuget-group/index.json V3 discovery document that tells the client where protocol resources live.
Client cache NUGET_PACKAGES directory A local consumer copy; not authoritative Nexus state.

Package ID plus version is the release coordinate. A SHA-256 of a .nupkg can prove whether two byte sequences are equal, but it does not prove trusted provenance or vulnerability safety. Keep identity, origin, authorization, signing, and security analysis separate.

3. V2 and V3 are protocol contracts, not “old URL versus new URL”

Nexus supports both NuGet V2 and V3. V3 is the preferred modern client path. When you configure a V3 source, append /index.json. Current Sonatype guidance explicitly warns that a group root without that suffix may be auto-detected as V2 and can produce a protocol mismatch such as HTTP 502.

A V3 client discovers resources before downloading package bytes
flowchart LR
  C[dotnet / NuGet client] -->|GET .../index.json| G[NuGet group]
  G -->|service index JSON| C
  C -->|registration / flat-container request| G
  G --> H[Hosted internal]
  G --> P[Proxy nuget.org]
  P --> U[api.nuget.org v3]
  H --> B[(Blob bytes)]
  P --> B
  H --> D[(Database metadata)]
  P --> D

The first request discovers resources. Later requests fetch registration metadata and package content. The group routes those reads across members; it is not where release publication should land.

4. Hosted, proxy, and group: one format, three responsibilities

Type Authority Typical action Persistent effect
Hosted Your organization Push internal .nupkg/.snupkg Creates package/component metadata and binary blob assets.
Proxy Remote feed such as nuget.org Resolve public dependencies Caches remote metadata and package bytes according to proxy freshness settings.
Group Aggregation only Restore/search through one URL Presents member content; request-path authorization and member order still matter.

Keep write and read endpoints conceptually separate. Publishing to a group or proxy is the wrong mental model. A CI publisher writes to hosted. Developers and CI consumers normally read from a group.

5. Restore credentials and deployment API keys solve different problems

A private group can require ordinary Nexus repository authentication for read requests. NuGet can obtain those credentials from NuGetPackageSourceCredentials_<sourceName> environment variables, a credential provider, or nuget.config. For publication, Nexus also supports a user-specific NuGet API key when the NuGet API-Key Realm is active and the user has the current nx-apikey-all privilege.

Regenerating the NuGet API key invalidates the previous key. That makes rotation observable and testable. It is not equivalent to changing the user's account password, and it does not grant repository write privileges by itself—the repository authorization matrix still applies.

Security boundary. The mandatory labs never put a repository password or API key in a URL, project file, shell history literal, or evidence file. Read credentials are supplied through an environment variable. With current NuGet 7.6+ behavior, the publish key can be supplied through NUGET_API_KEY instead of a command-line --api-key value.

6. nuget.config is client routing state

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="AcademyGroup"
         value="http://127.0.0.1:8081/repository/academy-ch10-group/index.json"
         protocolVersion="3"
         allowInsecureConnections="true" />
  </packageSources>
</configuration>

<clear /> removes inherited package sources for this configuration scope. That matters because NuGet otherwise merges configuration from machine, user, solution, and directory levels. The HTTP opt-out is acceptable only for this loopback exercise. Do not copy it into production instead of configuring TLS.

7. Source ordering is not a dependency-confusion policy

For modern PackageReference restore, source order is not a deterministic priority system. If multiple independently configured sources can provide the same package, the client can choose from candidates across those sources. Package Source Mapping, introduced in NuGet 6.0, constrains which source may satisfy which package ID patterns.

A single Nexus group can simplify client configuration, but client source mapping cannot distinguish individual members hidden behind that one group URL. If internal namespaces must never reach a public upstream, either use repository topology/routing that enforces that invariant or expose separate controlled sources and map package ID prefixes deliberately. Do not assume “internal source listed first” is sufficient.

8. Symbols are companion debugging content, not the package itself

A modern .snupkg contains portable PDB files. Starting with Nexus 3.95, V3 NuGet hosted repositories can accept these companion packages and Nexus can serve symbols through the Microsoft Symbol Server protocol. The symbol-server request path ends under /symbols. A debugger can retrieve PDB data on demand using the binary's debug identity.

This adds a new operational state: package bytes can be correct while symbol indexing or symbol retrieval is broken. Nexus provides a NuGet symbol-index repair task for specific repair scenarios; current documentation marks that repair task as Pro. Routine package upload does not require manually rebuilding the symbol index.

9. Read-only inspection before mutation

dotnet --info | tee dotnet-info.txt
curl -fsS http://127.0.0.1:8081/service/rest/v1/status | tee nexus-status.txt
curl -fsS http://127.0.0.1:8081/service/rest/v1/repositories | tee repositories-before.json

Then inspect existing NuGet repositories in the UI. Record format, type, remote URL for proxies, group members, deployment policy for hosted repositories, and whether the NuGet API-Key Realm is active. Do not change anything until you can explain the current state.

10. Trust boundaries

Boundary Question to ask
Client → Nexus Which exact source URL and credentials are in effect?
Group → member Which member can satisfy this package ID/version?
Proxy → upstream Is Nexus contacting the intended upstream, and is cached metadata fresh?
Publisher → hosted Does this identity have only the required add/read privileges?
Package → consumer Do the restored bytes match expected package identity and source evidence?
Debugger → symbol endpoint Is symbol retrieval allowed intentionally, and does the PDB correspond to the binary?

11. Why this matters in DevOps

Build reliability depends on feed semantics being explicit. A pipeline should know exactly where it restores packages, where it publishes, how release identities are protected, how credentials are scoped, and how symbols are retained. A “successful restore” does not prove the intended source served the package; record source and package hash evidence when provenance matters.

Knowledge check

Why should a V3 Nexus NuGet source end in /index.json?

Does a NuGet API key grant write permission by itself?

Why is source order not a strong dependency-confusion defense?

What identity should remain stable for an immutable release?

What Nexus version introduced snupkg/Symbol Server support?

12. Summary and next step

NuGet package flow is a protocol interaction among a client source configuration, V2/V3 feed resources, hosted/proxy/group routing, repository authorization, package bytes, local caches, and optional symbol services. Keep publish and restore endpoints separate, use V3 explicitly, isolate credentials, and make source selection observable.

Lesson 2 turns this model into a disposable end-to-end workflow.

Official references and version notes

Version-sensitive statements were rechecked on 2026-08-26. The mandatory lab assumes a disposable self-hosted Nexus Repository Community Edition 3.95.2 instance, Java 21 on the Nexus side, and .NET 10 SDK 10.0.400 on the client side. The NuGet symbol/Chocolatey features used here were introduced in Nexus 3.95.0. Record the actual dotnet --info and Nexus version in evidence before execution.

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.