# Working with the NuGet registry

You can configure the dotnet command-line interface (CLI) to publish NuGet packages to GitHub Packages and to use packages stored on GitHub Packages as dependencies in a .NET project.

<!-- 2148AF7B-5FF8-4B28-A808-D692FEE2225A -->

> \[!NOTE]
> This package type may not be available for your instance, because site administrators can enable or disable each supported package type. For more information, see [Configuring package ecosystem support for your enterprise](/en/enterprise-server@3.19/admin/configuring-packages/configuring-package-ecosystem-support-for-your-enterprise).

## Authenticating to GitHub Packages

> \[!NOTE]
> GitHub Packages only supports authentication using a personal access token (classic). For more information, see [Managing your personal access tokens](/en/enterprise-server@3.19/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).

You need an access token to publish, install, and delete private, internal, and public packages.

You can use a personal access token (classic) to authenticate to GitHub Packages or the GitHub API. When you create a personal access token (classic), you can assign the token different scopes depending on your needs. For more information about packages-related scopes for a personal access token (classic), see [About permissions for GitHub Packages](/en/enterprise-server@3.19/packages/learn-github-packages/about-permissions-for-github-packages#about-scopes-and-permissions-for-package-registries).

To authenticate to a GitHub Packages registry within a GitHub Actions workflow, you can use:

* `GITHUB_TOKEN` to publish packages associated with the workflow repository.
* A personal access token (classic) with at least `read:packages` scope to install packages associated with other private repositories (`GITHUB_TOKEN` can be used if the repository is granted read access to the package. See [Configuring a package's access control and visibility](/en/enterprise-server@3.19/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility)).

### Authenticating in a GitHub Actions workflow

Use the following command to authenticate to GitHub Packages in a GitHub Actions workflow using the `GITHUB_TOKEN` instead of hardcoding a personal access token in a nuget.config file in the repository:

```shell
dotnet nuget add source --username USERNAME --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.HOSTNAME/NAMESPACE/index.json"
```

Replace `NAMESPACE` with the name of the personal account or organization that owns the repository where your packages are hosted.

Replace `USERNAME` with the username to be used when connecting to an authenticated source.

For more information about `GITHUB_TOKEN` used in GitHub Actions workflows, see [Use GITHUB\_TOKEN for authentication in workflows](/en/enterprise-server@3.19/actions/tutorials/authenticate-with-github_token#using-the-github_token-in-a-workflow).

### Authenticating with a personal access token

> \[!NOTE]
> GitHub Packages only supports authentication using a personal access token (classic). For more information, see [Managing your personal access tokens](/en/enterprise-server@3.19/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).

You need an access token to publish, install, and delete private, internal, and public packages.

You can use a personal access token (classic) to authenticate to GitHub Packages or the GitHub API. When you create a personal access token (classic), you can assign the token different scopes depending on your needs. For more information about packages-related scopes for a personal access token (classic), see [About permissions for GitHub Packages](/en/enterprise-server@3.19/packages/learn-github-packages/about-permissions-for-github-packages#about-scopes-and-permissions-for-package-registries).

To authenticate to a GitHub Packages registry within a GitHub Actions workflow, you can use:

* `GITHUB_TOKEN` to publish packages associated with the workflow repository.
* A personal access token (classic) with at least `read:packages` scope to install packages associated with other private repositories (`GITHUB_TOKEN` can be used if the repository is granted read access to the package. See [Configuring a package's access control and visibility](/en/enterprise-server@3.19/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility)).

You must use a personal access token (classic) with the appropriate scopes to publish and install packages in GitHub Packages. For more information, see [Introduction to GitHub Packages](/en/enterprise-server@3.19/packages/learn-github-packages/introduction-to-github-packages#authenticating-to-github-packages).

To authenticate to GitHub Packages with the `dotnet` command-line interface (CLI), create a *nuget.config* file in your project directory specifying GitHub Packages as a source under `packageSources` for the `dotnet` CLI client.

You must replace:

* `USERNAME` with the name of your personal account on GitHub.
* `TOKEN` with your personal access token (classic).
* `NAMESPACE` with the name of the personal account or organization that owns the repository where your packages are hosted.
* `HOSTNAME` with the host name for your GitHub Enterprise Server instance.

If your instance has subdomain isolation enabled:

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <packageSources>
        <clear />
        <add key="github" value="https://nuget.HOSTNAME/NAMESPACE/index.json" />
    </packageSources>
    <packageSourceCredentials>
        <github>
            <add key="Username" value="USERNAME" />
            <add key="ClearTextPassword" value="TOKEN" />
        </github>
    </packageSourceCredentials>
</configuration>
```

If your instance has subdomain isolation disabled:

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <packageSources>
        <clear />
        <add key="github" value="https://HOSTNAME/_registry/nuget/NAMESPACE/index.json" />
    </packageSources>
    <packageSourceCredentials>
        <github>
            <add key="Username" value="USERNAME" />
            <add key="ClearTextPassword" value="TOKEN" />
        </github>
    </packageSourceCredentials>
</configuration>
```

## Publishing a package

You can publish a package to GitHub Packages by authenticating with a *nuget.config* file, using the `--api-key` command line option with your GitHub personal access token (classic) or by using command that can be run directly from the command line using the `dotnet` command-line interface (CLI).

Replace `OWNER` with your username or company name, and `YOUR_GITHUB_PAT` with your personal access token.

```shell
dotnet nuget add source --username OWNER --password YOUR_GITHUB_PAT --store-password-in-clear-text --name github "https://nuget.HOSTNAME/OWNER/index.json"
```

### Publishing a package using a GitHub personal access token as your API key

If you don't already have a personal access token to use for your account on GitHub, see [Managing your personal access tokens](/en/enterprise-server@3.19/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).

1. Create a new project. Replace `PROJECT_NAME` with the name you'd like to give the project.

   ```shell
   dotnet new console --name PROJECT_NAME
   ```

2. Package the project.

   ```shell
   dotnet pack --configuration Release
   ```

3. Publish the package using your personal access token as the API key. Replace `PROJECT_NAME` with the name of the project, `1.0.0` with the version number of the package, and `YOUR_GITHUB_PAT` with your personal access token.

   ```shell
   dotnet nuget push "bin/Release/PROJECT_NAME.1.0.0.nupkg" --api-key YOUR_GITHUB_PAT --source "github"
   ```

After you publish a package, you can view the package on GitHub. For more information, see [Viewing packages](/en/enterprise-server@3.19/packages/learn-github-packages/viewing-packages).

### Publishing a package using a *nuget.config* file

When publishing, the `OWNER` of the repository specified in your *.csproj* file must match the `NAMESPACE` that you use in your *nuget.config* authentication file. Specify or increment the version number in your *.csproj* file, then use the `dotnet pack` command to create a *.nuspec* file for that version. For more information on creating your package, see [Create and publish a package](https://docs.microsoft.com/nuget/quickstart/create-and-publish-a-package-using-the-dotnet-cli) in the Microsoft documentation.

1. Authenticate to GitHub Packages. For more information, see [Authenticating to GitHub Packages](#authenticating-to-github-packages).

2. Create a new project. Replace `PROJECT_NAME` with the name you'd like to give the project.

   ```shell
   dotnet new console --name PROJECT_NAME
   ```

3. Add your project's specific information to your project's file, which ends in *.csproj*. Make sure to replace:

   * `1.0.0` with the version number of the package.
   * `OWNER` with the name of the personal account or organization that owns the repository to which you want to publish your package.
   * `REPOSITORY` with the name of the repository to which you want to connect your package.
   * `HOSTNAME` with the host name for your GitHub Enterprise Server instance.

   ```xml
   <Project Sdk="Microsoft.NET.Sdk">

     <PropertyGroup>
       <OutputType>Exe</OutputType>
       <TargetFramework>netcoreapp3.0</TargetFramework>
       <PackageId>PROJECT_NAME</PackageId>
       <Version>1.0.0</Version>
       <Authors>AUTHORS</Authors>
       <Company>COMPANY_NAME</Company>
       <PackageDescription>PACKAGE_DESCRIPTION</PackageDescription>
       <RepositoryUrl>https://HOSTNAME/OWNER/REPOSITORY</RepositoryUrl>
     </PropertyGroup>

   </Project>
   ```

4. Package the project.

   ```shell
   dotnet pack --configuration Release
   ```

5. Publish the package using the `key` you specified in the *nuget.config* file. Replace `PROJECT_NAME` with the name of the project, and replace `1.0.0` with the version number of the package.

   ```shell
   dotnet nuget push "bin/Release/PROJECT_NAME.1.0.0.nupkg" --source "github"
   ```

After you publish a package, you can view the package on GitHub. For more information, see [Viewing packages](/en/enterprise-server@3.19/packages/learn-github-packages/viewing-packages).

## Publishing multiple packages to the same repository

To connect multiple packages to the same repository, use the same GitHub repository URL in the `RepositoryURL` fields in all *.csproj* project files. GitHub matches the repository based on that field.

The following example publishes the projects MY\_APP and MY\_OTHER\_APP to the same repository:

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <PackageId>MY_APP</PackageId>
    <Version>1.0.0</Version>
    <Authors>Octocat</Authors>
    <Company>GitHub</Company>
    <PackageDescription>This package adds a singing Octocat!</PackageDescription>
    <RepositoryUrl>https://HOSTNAME/my-org/my-repo</RepositoryUrl>
  </PropertyGroup>

</Project>
```

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <PackageId>MY_OTHER_APP</PackageId>
    <Version>1.0.0</Version>
    <Authors>Octocat</Authors>
    <Company>GitHub</Company>
    <PackageDescription>This package adds a dancing Octocat!</PackageDescription>
    <RepositoryUrl>https://HOSTNAME/my-org/my-repo</RepositoryUrl>
  </PropertyGroup>

</Project>
```

## Installing a package

Using packages from GitHub in your project is similar to using packages from *nuget.org*. Add your package dependencies to your *.csproj* file, specifying the package name and version. For more information on using a *.csproj* file in your project, see [Working with NuGet packages](https://docs.microsoft.com/nuget/consume-packages/overview-and-workflow) in the Microsoft documentation.

1. Authenticate to GitHub Packages. For more information, see [Authenticating to GitHub Packages](#authenticating-to-github-packages).

2. To use a package, add `ItemGroup` and configure the `PackageReference` field in the *.csproj* project file. Replace the `PACKAGE_NAME` value in `Include="PACKAGE_NAME"` with your package dependency, and replace the `X.X.X` value in `Version="X.X.X"` with the version of the package you want to use:

   ```xml
   <Project Sdk="Microsoft.NET.Sdk">

     <PropertyGroup>
       <OutputType>Exe</OutputType>
       <TargetFramework>netcoreapp3.0</TargetFramework>
       <PackageId>My-app</PackageId>
       <Version>1.0.0</Version>
      <Authors>Octocat</Authors>
       <Company>GitHub</Company>
      <PackageDescription>This package adds an Octocat!</PackageDescription>
       <RepositoryUrl>https://HOSTNAME/OWNER/REPOSITORY</RepositoryUrl>
     </PropertyGroup>

     <ItemGroup>
       <PackageReference Include="PACKAGE_NAME" Version="X.X.X" />
     </ItemGroup>

   </Project>
   ```

3. Install the packages with the `restore` command.

   ```shell
   dotnet restore
   ```

## Troubleshooting

Your NuGet package may fail to push if the `RepositoryUrl` in *.csproj* is not set to the expected repository.

If you're using a nuspec file, ensure that it has a `repository` element with the required `type` and `url` attributes.

If you're using a `GITHUB_TOKEN` to authenticate to a GitHub Packages registry within a GitHub Actions workflow, the token cannot access private repository-based packages in a different repository other than where the workflow is running in. To access packages associated with other repositories, instead generate a personal access token (classic) with the `read:packages` scope and pass this token in as a secret.

### Intermittent 403 errors when restoring public packages

If you're using GitHub Packages alongside *nuget.org* and experiencing intermittent 403 Forbidden errors when restoring standard public packages (like `Microsoft.Extensions.*`), this may occur because NuGet queries all configured package sources for every package. If GitHub Packages authentication fails temporarily, it can block the entire restore—even for packages that don't exist on GitHub Packages.

To avoid this, use [NuGet Package Source Mapping](https://learn.microsoft.com/nuget/consume-packages/package-source-mapping) to route packages to specific sources.

Replace:

* `NAMESPACE` with the name of the personal account or organization that owns your GitHub Packages NuGet feed.
* `PACKAGE-ID-PREFIX` with the NuGet package ID prefix that you use for packages hosted on GitHub Packages. If you use multiple prefixes, add additional `<package>` entries for each prefix.
* `HOSTNAME` with the host name for your GitHub Enterprise Server instance.

If your instance has subdomain isolation enabled:

```xml
<configuration>
    <packageSources>
        <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
        <add key="github" value="https://nuget.HOSTNAME/NAMESPACE/index.json" />
    </packageSources>
    <packageSourceMapping>
        <packageSource key="nuget.org">
            <package pattern="*" />
        </packageSource>
        <packageSource key="github">
            <package pattern="PACKAGE-ID-PREFIX.*" />
        </packageSource>
    </packageSourceMapping>
</configuration>
```

If your instance has subdomain isolation disabled:

```xml
<configuration>
    <packageSources>
        <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
        <add key="github" value="https://HOSTNAME/_registry/nuget/NAMESPACE/index.json" />
    </packageSources>
    <packageSourceMapping>
        <packageSource key="nuget.org">
            <package pattern="*" />
        </packageSource>
        <packageSource key="github">
            <package pattern="PACKAGE-ID-PREFIX.*" />
        </packageSource>
    </packageSourceMapping>
</configuration>
```

NuGet uses the [most specific matching pattern](https://learn.microsoft.com/nuget/consume-packages/package-source-mapping#package-pattern-precedence), so packages matching `PACKAGE-ID-PREFIX.*` are fetched only from GitHub Packages, while all other packages are fetched from *nuget.org*. This also helps prevent dependency confusion attacks by ensuring your private packages can only come from your GitHub Packages feed.

## Further reading

* [Deleting and restoring a package](/en/enterprise-server@3.19/packages/learn-github-packages/deleting-and-restoring-a-package)