DEV Community

loach
loach

Posted on Originally published at zenn.dev

Publishing .NET Packages to NuGet.org with an API Key

Publishing a .NET library manually is fine once or twice, but it becomes tedious when releases are frequent or automated through CI/CD.

The standard solution is to push packages to NuGet.org with dotnet nuget push and an API key.

This article covers the basic flow and the most important security consideration: never commit the API key into the repository.

Prerequisites

You need:

  • a .NET project
  • a generated .nupkg file
  • a NuGet.org account

For example, your package might look like this:

./bin/Release/YourPackage.1.0.0.nupkg
Enter fullscreen mode Exit fullscreen mode

Create a NuGet API key

Sign in to NuGet.org and open the API Keys page.

When creating a new key, configure at least:

  • a recognizable key name
  • an expiration period
  • the Push scope
  • an optional package pattern if you want to restrict which packages the key can publish

The generated key should be treated like a password.

Do not put it in source code, scripts committed to Git, or Markdown examples containing a real value.

Push a package

The basic command is:

dotnet nuget push <PACKAGE_FILE> \
  --api-key <YOUR_API_KEY> \
  --source https://api.nuget.org/v3/index.json
Enter fullscreen mode Exit fullscreen mode

For example:

dotnet nuget push ./bin/Release/YourPackage.1.0.0.nupkg \
  --api-key YOUR_API_KEY_HERE \
  --source https://api.nuget.org/v3/index.json
Enter fullscreen mode Exit fullscreen mode

A useful option for CI is --skip-duplicate:

dotnet nuget push ./bin/Release/*.nupkg \
  --api-key "$NUGET_API_KEY" \
  --source https://api.nuget.org/v3/index.json \
  --skip-duplicate
Enter fullscreen mode Exit fullscreen mode

This avoids failing a rerun just because the same package version was already published.

Store the key in GitHub Actions Secrets

For GitHub Actions, store the key as a repository secret, for example:

NUGET_API_KEY
Enter fullscreen mode Exit fullscreen mode

Then reference it from the workflow:

- name: Publish package
  env:
    NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
  run: |
    dotnet nuget push ./bin/Release/*.nupkg \
      --api-key "$NUGET_API_KEY" \
      --source https://api.nuget.org/v3/index.json \
      --skip-duplicate
Enter fullscreen mode Exit fullscreen mode

The API key stays outside the repository while still being available to the CI job.

Prefer narrow credentials

If the publishing key only needs to release one package family, restrict it to that package pattern where possible.

A narrow key reduces the impact if it is ever exposed.

The same principle applies to other CI credentials: give automation only the permissions it actually needs.

Closing thoughts

The mechanics of publishing a NuGet package are simple. The part worth designing carefully is credential handling.

A solid release flow usually looks like this:

build
  ↓
pack
  ↓
secret injected by CI
  ↓
dotnet nuget push
Enter fullscreen mode Exit fullscreen mode

Keeping the credential out of the repository makes the process both automatable and reasonably safe.

Top comments (0)