user

Best Practices for Authoring Private NuGet Packages at Scale

Introduction

Eric Seng

Eric Seng


LATEST POSTS

NuGet in the Enterprise 11th April, 2024

What are NuGet Package Vulnerabilities and How to Manage Them 09th October, 2023

NuGet

Best Practices for Authoring Private NuGet Packages at Scale

Posted on .

This article is part of our series on NuGet at Scale, also available as a chapter in our free, downloadable eBook

Non-standardized NuGet package authoring is like a messy toolbox with mislabeled tools. Unclear names, versions, and metadata leave developers guessing about a package’s purpose. Extra files or missing dependencies can lead to broken builds, runtime errors, and unexpected failures.

Few talk about this—even Microsoft—because it’s not “cool”, and much advice doesn’t fit private packages on private NuGet servers like ProGet. Proper package authoring often gets overlooked, but it’s essential for keeping your projects dependable and secure.

From naming packages to using NuGet Audit in .NET 9, this article outlines the best practices you need to keep your private NuGet packages secure and under control.

Authoring NuGet Packages at Scale

These days, the easiest way to create a private NuGet package is using an SDK-style project. This newer project format includes the package metadata in the project file itself.

While Microsoft has a pretty good step-by-step tutorial on how to create and publish a NuGet package with Visual Studio, the publishing steps are for nuget.org, and it doesn’t give any guidance for how to manage your project once it’s created. In general, your NuGet project should follow the same conventions that other projects at your organization use:

  • Single Project. This generally means having its own source code (git) repository and issue tracker… even if it’s a small library.
  • Wiki Page. A wiki page will be especially important, even if it’s just a readme file inside your repository. This will help other developers use the library, and allow them to build upon the documentation you start. At a minimum, it should have a brief description of the library, how to use/maintain the project, and links to the issue tracker. Later on, as you make major new versions of the package, you can add upgrade notes to the wiki page.
  • CI/CD Automation. Especially with tools like BuildMaster, it’s easy to create a CI/CD Pipeline for NuGet from the start so that even 1.0.0 is delivered as consistently as others.

Package Metadata at Scale

Metadata is an important aspect of all NuGet packages. Standardizing which properties to use (and how) is important: the wrong metadata can lead to problems like confusion and wasted time for developers, or even deploying the wrong package to production.

You can set package metadata in Visual Studio (Project > [Project Name] Properties > Package), or directly in the project file. These will be added to the .nuspec file once the package is created.

Our general advice for managing Package Metadata at scale is to keep it simple and use only as few fields as necessary. Unlike many package authors on nuget.org, you’re not trying to “sell” people on using your private NuGet package or win a popularity contest with the most downloads.

Package ID: Use the Company name: The NuGet package name is stored in the package’s manifest file, which is stored within the package zip file itself. You can’t just rename the file if you want to change the package name. It’s like trying to change the title page of a PDF document by renaming the file – the contents of the file and the file name have no relation. Microsoft has some good advice for writing unique package identifiers:

💡 Search existing feeds before choosing a name to ensure uniqueness

💡 Use namespace-like names using dot notation and not hyphens

💡 If you have a sample, be explicit with a “.Sample” suffix

You’re likely already using namespace-like names in .NET; that’s great – continue to do that with your private NuGet packages. But unlike libraries in your applications, these packages should be unique across the entire organization and any expansion for years to come.

Start with the company name (“Kramerica”) to avoid conflict with public packages. Be sure to register your company’s name on nuget.org so you’re protected from dependency confusion attacks.

Next, consider standardizing with a division or business name after the company name (“Kramerica.Warehouse” vs. “Kramerica.Offshore”).

Keeping standards is incredibly important since packages are immutable. They cannot be renamed, changed, or edited so standardize, standardize, standardize. You must create a new NuGet package with the same internal contents in order to “rename” a package. You’ll then have two packages: the “new” name one, and the “old” name one. And deleting those “old” packages is a bad idea because applications may be referencing that package. 

Package Version: Use SemVer w/ Prerelease Labels: Our recent blog post about best practices for versioning NuGet packages goes into detail about proper versioning.

In a nutshell: Semantic Version (Version 2.0.0) using PreRelease tags is a must. You should always create a package with a pre-release tag and then repackage it later. The Prerelease tag signifies that the library within the NuGet package is untested, and shouldn’t be deployed to production.

Authors: Only use Company name: Author is a required field, but it should be considered optional for private use in scaling organizations. Set one name as the author to keep with the standard; either the company name or a team name (“Kramerica” or “Kramerica.DevOps”).

Description: Use Internal Wiki: The Microsoft best practices come up short on description – ironic since we consider a short description key. The character limit is 4000, but it’s completely unnecessary to write that much. Use the description to link to the company Wiki page so you can maintain the most up-to-date information.

Be concise; reuse copy from the Wiki if necessary (likely to be pre-approved and reliable). NuGet Packages cannot be edited or updated, so hyperlinking to internal documentation is best.

Repository: Use Source Link: A Source Control Repository gives traceability to a NuGet package. There are four fields; type, URL, branch, and commit. Source Link will automatically add repositoryURL and RepositoryType to the package metadata, saving time.

This property is complex, requiring a CI/CD pipeline for your NuGet packages.

✅ Icon: Optional, a quick visual cue: An icon can be useful for quickly differentiating a NuGet package from others in a private NuGet repository on Visual Studio. If you have an appropriate icon file, feel free to include it, but it’s not necessary.

Note:  “iconURL” is deprecated so use “icon”

NuGet Audit: Optional but recommended, scan for vulnerabilities: NuGet Audit adds vulnerability scanning to your private packages using these two lines in either your .csproj file or a shared MSBuild file like Directory.Build.props:

xmlCopyEdit<PropertyGroup>
  <NuGetAuditMode>all</NuGetAuditMode>
  <NuGetAuditLevel>moderate</NuGetAuditLevel>
</PropertyGroup>

This setup flags security issues in both direct and transitive dependencies when you run dotnet restore. It’s recommended to configure this at the repository level to ensure consistent and automatic coverage across all projects.

Package Metadata Properties to Avoid

✗ Copyright: Ignore, not needed: Your NuGet packages will be private or published on a private repository, so they don’t need a copyright. If a project document doesn’t need “(C) Kramerica” on them, neither does a private NuGet package.

✗ Licensing: Ignore, not needed: Similar to Copyright, your packages will be private and therefore don’t need a license file, licenseURL, or requiredLicenseAcceptance.

✗ Project URL: Ignore, link to Internal Wiki: Following these guides, you will already include a link to the Wiki’s project page in the description, making this field redundant. If you think this field should be filled, use the same project page link in the description.

✗ Tags: Ignore, worse than free-text search: Tags are a bad replacement for private use without a standardized system, especially compared to free-text searches. Creating tags and then maintaining their standards will also occupy a lot of time unnecessarily. 

✗ Release Notes: Ignore, redundant to Wiki: The Wiki’s project page should also link to issue trackers, give upgrade guidance, and other show release notes, making this field redundant to the description. In Visual Studio, some UI sections may display release notes instead of the description which can cause confusion, so it’s best to leave this field blank and rely on the description to do the heavy lifting.

✗ Title: Ignore, not needed with ID: The title field is not shown in Visual Studio or on nuget.org. Generally, it’s not used for display purposes, so just use ID and leave this field blank.

✗ Summary: Ignore, redundant to the description: The summary field is deprecated and shouldn’t be used, plus it’s redundant to the description anyway. It has been replaced by the title, but as seen above it’s not needed either. Leave this field blank. 

✗ Readme: Ignore, not needed with Wiki: Readmes are not where developers typically go for documentation. Guides for using a NuGet package should be included in the Wiki anyway, so a readme will be redundant. Be sure to hyperlink to internal, up-to-date documentation that would be considered readme-worthy.

Standardizing Metadata Usage

Without standardized NuGet package authoring, your private feed can quickly turn into a mess—leading to broken builds, runtime errors, and security vulnerabilities.

Implementing best practices like consistent metadata, semantic versioning, and NuGet Audit integration transforms your package management into an organized, secure, and scalable system. Keeping property usage to a minimum will make it easier for developers to create and contribute while avoiding headaches down the line.

That’s a lot to absorb, so be sure to keep track of it and reference it later. Or, even better why not download our free eBook, “NuGet at Scale”. It covers everything here, plus it’s packed with helpful info on how NuGet packages work, using CI/CD pipelines for your NuGet packages, and more! Get your copy today!

Eric Seng

Eric Seng

Navigation