Skip to content
Go back

.NET 私有 NuGet 源实战:Azure Artifacts 与 GitHub Packages

NuGet.org 是开源包的绝佳归宿,但不是所有包都该上去。内部公共库、跨微服务共享的专有代码、还没准备好公开发布的库——这些场景下,一个私有 NuGet 源才是正确的选择。

本文覆盖两种最常用的托管方案:Azure Artifacts 和 GitHub Packages。你会看到各自的源配置方式、本地和 CI/CD 认证怎么搞、以及怎么在同一个项目里同时使用公开和私有源。

什么时候不该用 NuGet.org

NuGet.org 是公开的。推上去的包全世界都能看到和下载——对开源工作来说完美,但日常团队场景往往会出问题:

简单说:私有源解决的问题是——在一个你定义的边界内可靠分发编译好的代码,而不暴露到边界之外。

Azure Artifacts 作为私有 NuGet 源

Azure Artifacts 是 Azure DevOps 的一部分。如果你的团队已经在用 Azure DevOps 做源码管理、任务跟踪或流水线,那 Azure Artifacts 就在同一个生态里,是自然的第一选择。

源的范围:组织级 vs 项目级

组织级源对 Azure DevOps 组织内所有项目可见——适合多团队共享的内部包,比如通用日志库或共享 API 客户端。

项目级源只对单个 Azure DevOps 项目可见,更隔离,权限管理更容易。适合只在某个产品或团队内使用的包。

源 URL 格式

创建源之后,NuGet v3 源 URL 格式如下:

https://pkgs.dev.azure.com/{org}/{project}/_packaging/{feedName}/nuget/v3/index.json

组织级源(无项目)去掉 /{project} 段。

上游源

Azure Artifacts 的上游源值得单独提一句。配置上游源后,你的私有源可以代理转发对 NuGet.org(或其他 NuGet 源)的请求。意思是所有开发者从你私有源这一个源恢复包——即使那些包本身是公开的。Azure Artifacts 代取并缓存公开包。

这对公司防火墙配置和审计都有好处:所有在用包通过一个可审计的源获取。

Azure Artifacts 认证配置

Azure Artifacts 使用 Microsoft Entra ID 做认证。最简单的方式是安装 Azure Artifacts Credential Provider

iex "& { $(irm https://aka.ms/install-artifacts-credprovider.ps1) }"

安装后,首次从 Azure Artifacts 源恢复包时会弹出交互式登录提示。

本地开发时可以直接把源 URL 加到用户级 nuget.config 并存储凭据:

dotnet nuget add source "https://pkgs.dev.azure.com/myorg/myproject/_packaging/MyFeed/nuget/v3/index.json" `
    --name "MyAzureArtifactsFeed" `
    --username "myuser" `
    --password "MY_PERSONAL_ACCESS_TOKEN" `
    --store-password-in-clear-text

PAT 至少需要 Azure DevOps 中的 Packaging (read) 权限。

GitHub Packages 作为私有 NuGet 源

GitHub Packages 内建在 GitHub 里。如果你的团队用 GitHub 管理代码,GitHub Packages 很自然地跟仓库搭配使用。

两个常见意外:

https://nuget.pkg.github.com/{OWNER}/index.json

nuget.config 多源配置

大多数实际项目同时用 NuGet.org 和一个或多个私有源。nuget.config 是声明所有这些源的地方。

使用 Azure Artifacts

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="MyAzureArtifactsFeed"
         value="https://pkgs.dev.azure.com/myorg/myproject/_packaging/MyFeed/nuget/v3/index.json" />
  </packageSources>

  <packageSourceCredentials>
    <MyAzureArtifactsFeed>
      <add key="Username" value="optional-username" />
      <add key="ClearTextPassword" value="%AZURE_DEVOPS_TOKEN%" />
    </MyAzureArtifactsFeed>
  </packageSourceCredentials>
</configuration>

%AZURE_DEVOPS_TOKEN% 语法告诉 NuGet 在恢复时从环境变量读取,避免把真实凭据写在文件里。安装 credential provider 后,本地开发甚至可以省略整个 <packageSourceCredentials> 块。

使用 GitHub Packages

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="GitHubPackages"
         value="https://nuget.pkg.github.com/MyGitHubOrg/index.json" />
  </packageSources>

  <packageSourceCredentials>
    <GitHubPackages>
      <add key="Username" value="x-access-token" />
      <add key="ClearTextPassword" value="%NUGET_AUTH_TOKEN%" />
    </GitHubPackages>
  </packageSourceCredentials>
</configuration>

Usernamex-access-token 是 GitHub 的标准值——它对 GITHUB_TOKEN 和 PAT 认证都生效。NUGET_AUTH_TOKEN 是约定俗成的环境变量名。

在 Visual Studio 和 CLI 中使用私有包

nuget.config 和认证配好后,从私有源消费包和从 NuGet.org 消费完全一样:

dotnet restore
dotnet add package MyCompany.SharedUtils --version 1.2.0
dotnet add package MyCompany.SharedUtils --source MyAzureArtifactsFeed

NuGet 按顺序搜索所有配置的源。不指定 --source 时,会在所有源里找。在 Visual Studio 中,NuGet 包管理器的源下拉框里会出现你的私有源——选中、搜包名、正常安装就行。

CI/CD 中处理凭据

本地交互式登录不能在无头 CI 环境中工作,需要通过环境变量或流水线密钥传入凭据。

GitHub Actions + GitHub Packages

最简场景:GITHUB_TOKEN 由 GitHub Actions 自动注入,对同一组织的包默认有 read:packages 权限:

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      packages: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '9.0.x'

      - name: Restore packages
        env:
          NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: dotnet restore

      - name: Build
        run: dotnet build --no-restore

Azure Pipelines + Azure Artifacts

Azure Pipelines 通过 NuGetAuthenticate 任务原生支持 Azure Artifacts:

steps:
  - task: NuGetAuthenticate@1
    displayName: 'Authenticate with Azure Artifacts'
  - script: dotnet restore
    displayName: 'Restore packages'

NuGetAuthenticate 自动为 nuget.config 中找到的所有 Azure Artifacts 源注入凭据,不需要手动设置令牌。

Azure Artifacts vs GitHub Packages 对比

Azure ArtifactsGitHub Packages
原生集成Azure DevOpsGitHub Actions
认证Entra ID / PAT + credential providerGitHub PAT (read:packages)
读取权限需组织成员或显式共享即便是公开包也需要认证
上游源支持 NuGet.org 代理不支持
免费额度每组织 2 GB,之后按用量计费包含在 GitHub 计划中
CI 工具NuGetAuthenticate 任务GITHUB_TOKEN 内置密钥
源 URL 范围按源(组织或项目级)按 owner(组织或用户)

选 Azure Artifacts:团队已经在 Azure DevOps 工作、想要上游源代理、需要项目级源隔离。

选 GitHub Packages:团队在 GitHub 生态里、包跟特定仓库紧密关联、想要最简配置。

两者也可以同时用——nuget.config 里配多个源就好。

结语

私有 NuGet 源解决一个实际问题:在组织内部安全分发专有或未公开的 NuGet 包。Azure Artifacts 和 GitHub Packages 是两种主流方案,各自跟自己的 CI/CD 生态天然集成。

核心要点:

参考


Tags


Previous

ASP.NET Core 自定义用户管理:从注册到管理员面板

Next

MCP 传输层选型:C# 中 stdio、Streamable HTTP 与 SSE 对比