Skip to main content

Configuration

AvantiPoint Packages is configured through a combination of appsettings.json and the fluent API in your Program.cs file.

Basic Configuration Structure

Your appsettings.json should include these sections:

{
"Database": {
"Type": "Sqlite"
},
"Storage": {
"Type": "FileStorage",
"Path": "App_Data"
},
"ConnectionStrings": {
"Sqlite": "Data Source=packages.db",
"SqlServer": "Server=(localdb)\\mssqllocaldb;Database=AvantiPointPackages;Trusted_Connection=True;",
"MySql": "Server=localhost;Database=packages;User=root;Password=password;",
"PostgreSql": "Host=localhost;Database=packages;Username=postgres;Password=password;"
},
"Mirror": {
"NuGet.org": {
"FeedUrl": "https://api.nuget.org/v3/index.json"
}
},
"Shields": {
"ServerName": "My Package Feed"
}
}

Database Configuration

AvantiPoint Packages supports four database providers:

SQLite

Perfect for development and small deployments:

{
"Database": {
"Type": "Sqlite"
},
"ConnectionStrings": {
"Sqlite": "Data Source=packages.db"
}
}

In Program.cs:

builder.Services.AddNuGetPackageApi(options =>
{
options.AddSqliteDatabase("Sqlite");
});

SQL Server

Recommended for production Windows deployments:

{
"Database": {
"Type": "SqlServer"
},
"ConnectionStrings": {
"SqlServer": "Server=myserver;Database=AvantiPointPackages;User Id=sa;Password=yourpassword;"
}
}

In Program.cs:

builder.Services.AddNuGetPackageApi(options =>
{
options.AddSqlServerDatabase("SqlServer");
});

MySQL / MariaDB

Great for cross-platform production deployments:

{
"Database": {
"Type": "MySql"
},
"ConnectionStrings": {
"MySql": "Server=localhost;Database=packages;User=root;Password=password;"
}
}

In Program.cs:

builder.Services.AddNuGetPackageApi(options =>
{
// For MySQL
options.AddMySqlDatabase("MySql");

// Or for MariaDB
options.AddMariaDb("MariaDb");
});

PostgreSQL

Excellent for production deployments requiring advanced features:

{
"Database": {
"Type": "PostgreSql"
},
"ConnectionStrings": {
"PostgreSql": "Host=localhost;Database=packages;Username=postgres;Password=password;"
}
}

In Program.cs:

builder.Services.AddNuGetPackageApi(options =>
{
options.AddPostgreSqlDatabase("PostgreSql");
});

Connection String by Name

You can reference connection strings by name from the ConnectionStrings section:

options.AddSqlServerDatabase("SqlServer"); // Uses ConnectionStrings:SqlServer

Environment-Specific Configuration

Use different databases for different environments:

builder.Services.AddNuGetPackageApi(options =>
{
if (options.Environment.IsDevelopment())
{
options.AddSqliteDatabase("Sqlite");
}
else
{
options.AddSqlServerDatabase("SqlServer");
}
});

Or use appsettings.{Environment}.json:

appsettings.Development.json:

{
"Database": {
"Type": "Sqlite"
}
}

appsettings.Production.json:

{
"Database": {
"Type": "SqlServer"
}
}

Storage Configuration

File Storage

Store packages on the local file system:

{
"Storage": {
"Type": "FileStorage",
"Path": "App_Data"
}
}

In Program.cs:

options.AddFileStorage();

The path can be absolute or relative to the application directory. You can also specify a network share:

{
"Storage": {
"Type": "FileStorage",
"Path": "\\\\server\\share\\packages"
}
}

Azure Blob Storage

Store packages in Azure:

First, add the package:

dotnet add package AvantiPoint.Packages.Azure

Configuration:

{
"Storage": {
"Type": "AzureBlobStorage",
"Container": "my-nuget-feed",
"ConnectionString": "DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
}
}

Or use account name and key separately:

{
"Storage": {
"Type": "AzureBlobStorage",
"Container": "my-nuget-feed",
"AccountName": "mystorageaccount",
"AccessKey": "your-access-key"
}
}

In Program.cs:

using AvantiPoint.Packages.Azure;

options.AddAzureBlobStorage();

AWS S3 Storage

Store packages in Amazon S3:

First, add the package:

dotnet add package AvantiPoint.Packages.Aws

Configuration:

{
"Storage": {
"Type": "AwsS3",
"Region": "us-west-2",
"Bucket": "my-nuget-feed",
"Prefix": "packages",
"UseInstanceProfile": true
}
}

For explicit credentials:

{
"Storage": {
"Type": "AwsS3",
"Region": "us-west-2",
"Bucket": "my-nuget-feed",
"AccessKey": "your-access-key",
"SecretKey": "your-secret-key"
}
}

In Program.cs:

using AvantiPoint.Packages.Aws;

options.AddAwsS3Storage();

Upstream Mirrors

Configure upstream package sources to mirror or proxy. In v4, sources are PackageSource entities with a per-source CachingStrategy (IndexAndCache, CacheOnly, or ProxyOnly).

{
"PackageSources": [
{
"Name": "NuGet.org",
"FeedUrl": "https://api.nuget.org/v3/index.json",
"Type": "Upstream",
"CachingStrategy": "IndexAndCache",
"IsEnabled": true
}
],
"Search": {
"Type": "Database",
"IncludeMirroredPackages": true,
"EnableUpstreamSearch": false,
"UpstreamSearchTimeout": "00:00:02",
"MergeStrategy": "LocalPreferred"
}
}

Configure PackageSource rows via the Host UI (/Account/PackageSources), database seeding, or Mirror:NuGetConfigPath. Combine CachingStrategy with Search.IncludeMirroredPackages per Deployment Scenarios.

Deprecated: The legacy Mirror dictionary and AddUpstreamSource code helpers are deprecated in v4.0. See Upstream Mirrors for migration guidance.

Local NuGet cache

The feed can read package archives from an existing NuGet global packages folder before contacting configured upstream sources:

{
"LocalCache": {
"Enabled": true,
"Path": "/nuget-cache",
"CopyToFeedStorage": false
}
}
SettingDefaultBehavior
EnabledfalseEnables local cache reads
PathNUGET_PACKAGES, then ~/.nuget/packagesRoot of the NuGet global packages folder
CopyToFeedStoragefalseCopies cache hits into feed storage without database or search records

When copying is disabled, the package is streamed directly from the global packages folder and no duplicate is created. The folder can therefore be mounted read-only. Local cache lookups only apply to exact package content requests. Package version discovery still comes from the feed database or configured upstream sources.

Via Code (deprecated)

builder.Services.AddNuGetPackageApi(options =>
{
options.AddFileStorage();
options.AddSqliteDatabase("Sqlite");

// Deprecated in v4 — use PackageSources instead
options.AddUpstreamSource("NuGet.org", "https://api.nuget.org/v3/index.json");
options.AddUpstreamSource("Telerik", "https://nuget.telerik.com/nuget", "user@example.com", "password");
});

Note: Sources added via code will override configuration-based sources.

Shields.io Badges

Enable package version badges:

{
"Shields": {
"ServerName": "My Feed"
}
}

With this enabled, you can use badges in your documentation:

![Version](https://my-feed.example.com/api/shields/v/MyPackage.svg)

If ServerName is null or empty, the shields endpoint is disabled.

Advanced Options

Package Deletion

Allow or disallow package deletion (default: allow):

{
"PackageDeletion": {
"Enabled": false
}
}

Search and discovery

Configure package search behavior and which package origins appear in browse/search results:

{
"Search": {
"Type": "Database",
"IncludeMirroredPackages": true
}
}

IncludeMirroredPackages

Controls whether mirrored upstream packages appear in search, autocomplete, and registration discovery. Defaults to true.

ValueSearch includesRestore behavior
true (default)Published and Mirrored packagesAll origins available for restore
falsePublished packages onlyMirrored and cached packages still restorable by id/version

Packages with origin Cached (CacheOnly strategy) are never included in search, regardless of this setting.

This setting works together with per-source CachingStrategy on PackageSources. See Deployment Scenarios for recommended combinations.

Defaults that preserve existing behavior:

  • Search.IncludeMirroredPackages defaults to true
  • PackageSource.CachingStrategy defaults to IndexAndCache

No changes are required when upgrading unless you want a different deployment pattern (commercial/private feed, lightweight Docker, etc.).

Search provider type

Search.Type selects the search backend: Database (default), Null, AzureSearch, OpenSearch, or Elasticsearch. External search providers honor the same origin filters via IncludeMirroredPackages.

Set Search.EnableUpstreamSearch to true to merge each local NuGet search page with live results from enabled upstream PackageSource rows. This is useful for lightweight developer feeds that proxy packages without indexing the entire upstream catalog. It is disabled by default, so existing deployments do not make additional network requests.

UpstreamSearchTimeout limits the complete upstream operation across all configured sources. If that timeout expires, the request returns the local results. A failure from one source does not discard results from other sources.

MergeStrategy accepts these values:

ValueBehavior
LocalPreferred (default)Return one entry per package ID and retain local metadata when the same ID exists upstream
DeduplicateReturn one entry per package ID and select the entry with the highest package version
UnionReturn all entries in source-priority order, including repeated package IDs

Federation applies to the NuGet search endpoint only. Autocomplete, version enumeration, and dependent queries continue to use the configured local search provider. Upstream credentials and priority come from the existing PackageSource configuration.

Repository Package Signing

Enable repository-level package signing:

{
"Signing": {
"Mode": "SelfSigned",
"CertificatePasswordSecret": "Signing:CertificatePassword",
"TimestampServerUrl": "http://timestamp.digicert.com",
"PublishSignaturePolicy": "ReSign",
"SelfSigned": {
"SubjectName": "CN=My Repository Signer, O=MyOrg, C=US",
"KeySize": "KeySize4096",
"ValidityInDays": 3650,
"CertificatePath": "certs/repository-signing.pfx"
}
}
}

Signing Modes:

  • SelfSigned - Automatically generate and manage certificates
  • StoredCertificate - Use existing certificate from file or certificate store
  • AzureKeyVault - Use certificate from Azure Key Vault (requires AvantiPoint.Packages.Signing.Azure package)
  • AwsKms - Use AWS KMS with HSM-backed keys (requires AvantiPoint.Packages.Signing.Aws package)
  • AwsSigner - Use AWS Signer managed code signing (requires AvantiPoint.Packages.Signing.Aws package)
  • GcpKms - Use Google Cloud KMS with HSM protection (requires AvantiPoint.Packages.Signing.Gcp package)
  • GcpHsm - Use Google Cloud HSM (requires AvantiPoint.Packages.Signing.Gcp package)

Publish-Time Signature Policy:

  • ReSign (default) - Strip existing repository signatures and replace with our own
  • Reject - Reject packages that already have repository signatures

For detailed signing configuration, see Package Signing.

Complete Example

Here's a complete production configuration:

appsettings.Production.json:

{
"Database": {
"Type": "SqlServer"
},
"Storage": {
"Type": "AzureBlobStorage",
"Container": "packages",
"ConnectionString": "DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=...;EndpointSuffix=core.windows.net"
},
"ConnectionStrings": {
"SqlServer": "Server=tcp:myserver.database.windows.net,1433;Database=packages;User ID=admin;Password=...;Encrypt=true;"
},
"Mirror": {
"NuGet.org": {
"FeedUrl": "https://api.nuget.org/v3/index.json"
}
},
"Shields": {
"ServerName": "Contoso Packages"
}
}

Program.cs:

using AvantiPoint.Packages;
using AvantiPoint.Packages.Azure;
using AvantiPoint.Packages.Core;
using AvantiPoint.Packages.Hosting;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<IPackageAuthenticationService, MyAuthService>();
builder.Services.AddScoped<INuGetFeedActionHandler, MyActionHandler>();

builder.Services.AddNuGetPackageApi(options =>
{
options.AddAzureBlobStorage();
options.AddSqlServerDatabase("SqlServer");
});

var app = builder.Build();

app.UseHttpsRedirection();
app.UseRouting();
app.MapNuGetApiRoutes();

await app.RunAsync();

See Also