Skip to main content

Private Sources

Create and manage custom package sources for WinGet, enabling organizations to distribute internal applications and control package availability.

Understanding Sources

WinGet sources provide the package metadata and download locations for applications. While the default winget source serves the public repository, organizations can add private sources for:
  • Internal enterprise applications
  • Custom package versions
  • Approved software catalogs
  • Isolated development environments
Only add sources from trusted, secure locations. Sources have access to install software on client machines.

Source Types

Microsoft.PreIndexed.Package

Pre-indexed package sources (default type):
winget source add --name Contoso \
  --arg "https://contoso.com/cache" \
  --type Microsoft.PreIndexed.Package
  • Uses a pre-built package index
  • Optimized for fast searches
  • Requires index generation infrastructure
  • Recommended for large catalogs

Microsoft.Rest

REST API-based sources:
winget source add --name ContosoRest \
  --arg "https://api.contoso.com/packages" \
  --type Microsoft.Rest
  • Dynamic queries via REST API
  • No pre-indexing required
  • More flexible for smaller catalogs
  • Supports custom HTTP headers

Managing Sources

Adding a Source

1

Identify Source Details

Gather required information:
  • Source name (friendly identifier)
  • Source URL or UNC path
  • Source type (if not default)
2

Add the Source

winget source add --name CompanyApps \
  --arg "https://packages.company.com/cache"
3

Verify Addition

winget source list
Your source should appear in the output.

Listing Sources

View all configured sources:
winget source list
View details for a specific source:
winget source list --name winget
Output includes:
  • Name: Source identifier
  • Type: Source type
  • Arg: URL or path
  • Data: Optional package name
  • Updated: Last update timestamp

Updating Sources

Update a specific source:
winget source update --name CompanyApps
Update all sources:
winget source update
Source updates fetch the latest package index. WinGet automatically updates sources based on the configured interval (default: 15 minutes).

Removing a Source

Remove a source by name:
winget source remove --name CompanyApps
Removing a source doesn’t uninstall packages from that source. It only prevents future installations.

Resetting Sources

Reset to default configuration:
winget source reset
This removes ALL sources and restores only the default winget source. Use with caution.

Exporting Source Configuration

Export current source configuration:
winget source export
This outputs JSON representing your source configuration, useful for:
  • Backup and restore
  • Sharing configuration with team members
  • Group Policy configuration

REST Source Configuration

Custom HTTP Headers

Pass custom headers to REST sources for authentication or feature flags:
winget install --id Contoso.App \
  --source ContosoRest \
  --header "X-Custom-Token: abc123"
The header is sent as the value of the Windows-Package-Manager HTTP header to the REST source.

Header Limitations

  • Maximum length: 1024 characters
  • Requires --source to specify a REST source
  • Ignored for non-REST sources (with warning)

Supported Commands with Headers

winget search vscode --source ContosoRest \
  --header "Environment: Production"

Source Priority

When multiple sources contain the same package:

Default Behavior

WinGet searches all sources and may prompt for disambiguation:
winget install --id Git.Git
If found in multiple sources, specify explicitly:
winget install --id Git.Git --source winget

Source Priority Feature

Enable experimental source priority:
{
  "experimentalFeatures": {
    "sourcePriority": true
  }
}
With source priority enabled, higher-priority sources appear first in search results and are preferred for new installations.
Configure source priorities via Group Policy (see Group Policy Guide).

Enterprise Source Deployment

Network Share (UNC Path)

Deploy sources via network shares:
winget source add --name InternalApps \
  --arg "\\fileserver\packages\cache"
  • Share must be accessible to all client machines
  • Read permissions for all users
  • Network connectivity to file server
  • Index files must be kept up-to-date

HTTPS Repository

Secure source hosting:
winget source add --name SecureApps \
  --arg "https://secure-packages.contoso.com/cache" \
  --type Microsoft.PreIndexed.Package
  • Use HTTPS for all remote sources
  • Implement certificate pinning where possible
  • Monitor access logs for anomalies
  • Keep source infrastructure patched

Azure Blob Storage

Host package indexes in Azure:
winget source add --name AzureApps \
  --arg "https://contosopkgs.blob.core.windows.net/packages/cache"
Configure blob storage with anonymous read access or integrate authentication via custom headers for REST sources.

Group Policy Integration

Additional Sources Policy

Define sources via Group Policy that users cannot remove:
1

Export Source Configuration

On a reference machine:
winget source list --name CompanyApps
Note the configuration details.
2

Configure Policy

In Group Policy Editor:
  1. Navigate to: Computer Configuration > Administrative Templates > Windows Components > Desktop App Installer
  2. Enable: Enable Windows Package Manager Additional Sources
  3. Add source with format: {"Name":"CompanyApps","Arg":"https://...","Type":"Microsoft.PreIndexed.Package"}
3

Deploy Policy

Apply GPO to target OUs. Sources appear automatically on client machines.
Sources defined via Additional Sources policy cannot be removed by users.

Allowed Sources Policy

Restrict users to specific sources only:
1

Enable Policy

Enable: Enable Windows Package Manager Allowed Sources
2

Define Allowed Sources

List each permitted source:
{"Name":"winget","Arg":"https://cdn.winget.microsoft.com/cache","Type":"Microsoft.PreIndexed.Package"}
{"Name":"CompanyApps","Arg":"https://packages.company.com/cache","Type":"Microsoft.PreIndexed.Package"}
3

Test Enforcement

Users can only add/remove sources listed in the policy.
See the Group Policy Guide for detailed policy configuration.

Building a Private Source

Index Structure Requirements

For Microsoft.PreIndexed.Package sources:
  1. Package manifests: YAML files describing each package
  2. Index database: SQLite database with package metadata
  3. Index file: index.db at the source root

Manifest Repository

Organize manifests in a repository structure:
manifests/
├── contoso/
│   ├── app1/
│   │   ├── 1.0.0/
│   │   │   ├── contoso.app1.installer.yaml
│   │   │   ├── contoso.app1.locale.en-US.yaml
│   │   │   └── contoso.app1.yaml
│   │   └── 2.0.0/
│   └── app2/
└── fabrikam/

Index Generation

Use the WinGet source tools to generate indexes:
# Example using winget-pkgs tools
./Tools/GeneratePackageIndex.ps1 -ManifestsPath ./manifests -OutputPath ./cache
Index generation tools are available in the winget-pkgs repository.

Hosting Considerations

Bandwidth

Sources should handle concurrent client requests. Use CDN for larger deployments.

Update Frequency

Re-generate indexes when manifests change. Automate with CI/CD pipelines.

Versioning

Maintain old package versions in archive for rollback scenarios.

Security

Host over HTTPS, implement access controls, audit package submissions.

REST API Implementation

API Endpoints

Implement these endpoints for a REST source:
Endpoint: GET /packages?query={query}Returns packages matching the search query.Response:
{
  "Data": [
    {
      "PackageIdentifier": "Contoso.App1",
      "PackageName": "Contoso Application",
      "Publisher": "Contoso Ltd"
    }
  ]
}
Endpoint: GET /packages/{packageId}Returns full manifest for a specific package.Response:
{
  "PackageIdentifier": "Contoso.App1",
  "Versions": [
    {
      "PackageVersion": "1.0.0",
      "Installers": [
        {
          "Architecture": "x64",
          "InstallerType": "msi",
          "InstallerUrl": "https://downloads.contoso.com/app1-1.0.0-x64.msi",
          "InstallerSha256": "abc123..."
        }
      ]
    }
  ]
}

Custom Header Processing

Read the Windows-Package-Manager header for custom behavior:
app.get('/packages', (req, res) => {
  const customHeader = req.headers['windows-package-manager'];
  
  // Process header for authentication, routing, etc.
  if (customHeader) {
    // Custom logic based on header value
  }
  
  // Return package data
});

Authentication Strategies

# Client sends header
winget install --id Contoso.App \
  --source ContosoAPI \
  --header "Bearer eyJhbGc..."

# Server validates token in header
Headers are sent in plain text unless using HTTPS. Always use encrypted connections for sensitive data.

Common Workflows

Multi-Source Installation

Search across all sources but install from specific one:
# Search all sources
winget search nodejs

# Install from company source
winget install --id OpenJS.NodeJS --source CompanyApps -e

Source-Specific Upgrades

Upgrade packages from a particular source:
winget upgrade --source CompanyApps

Testing New Sources

Validate source connectivity before deployment:
# Add test source
winget source add --name TestSource --arg "https://test.contoso.com/cache"

# Test search
winget search test --source TestSource

# Test installation
winget install --id Test.Package --source TestSource

# Remove after testing
winget source remove --name TestSource

Troubleshooting

Symptoms: Packages don’t appear after adding to sourceSolutions:
  1. Force update: winget source update --name YourSource
  2. Check network connectivity to source URL
  3. Verify index file timestamp at source location
  4. Check firewall/proxy settings
  5. Remove and re-add source
Symptoms: Cannot access sourceSolutions:
  1. Verify URL is correct
  2. Check anonymous read permissions
  3. Test URL in browser
  4. Review server access logs
  5. Verify SSL/TLS certificate validity
Symptoms: Same package ID in multiple sourcesSolutions:
  1. Always specify --source when installing
  2. Use --exact flag for precise matching
  3. Consider source priority feature
  4. Review source naming conventions
Symptoms: Search returns inconsistent resultsSolutions:
  1. Regenerate source index
  2. Clear client cache: winget source reset
  3. Force source update
  4. Verify index.db file integrity

Security Best Practices

Use HTTPS

Always use encrypted connections for remote sources. Never expose package repositories over plain HTTP.

Validate Packages

Implement package validation and scanning before adding to private sources.

Access Control

Restrict who can submit packages to your private source. Use authentication and authorization.

Audit Logging

Log all package submissions, modifications, and access attempts for security review.

Hash Verification

Always include SHA256 hashes in manifests. WinGet validates downloads against these hashes.

Network Isolation

Consider network segmentation for internal package repositories.

Performance Optimization

Caching Strategy

Implement caching at multiple levels:
  1. CDN caching: For global deployments
  2. Proxy caching: For large offices
  3. Client caching: WinGet automatically caches indexes

Index Optimization

  • Keep index files compact
  • Remove old package versions periodically
  • Implement index file compression
  • Use incremental index updates where possible

Bandwidth Management

{
  "source": {
    "autoUpdateIntervalInMinutes": 60
  },
  "network": {
    "downloader": "do",
    "doProgressTimeoutInSeconds": 120
  }
}
Increase update intervals for bandwidth-constrained environments.

Group Policy

Enforce source policies across your organization

Configuration Files

Configure source update intervals and behavior

Package Management

Install and manage packages from private sources

Build docs developers (and LLMs) love