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 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 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 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 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 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 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 Keeping the credential out of the repository makes the process both automatable and reasonably safe.