WinGet, the Windows Package Manager CLI, brings simple, scriptable installs, upgrades, and uninstalls to Windows. In enterprise and team environments, the most powerful capability isnât just consuming public catalogsâitâs running your own private WinGet source. A private repository gives you full control over what software is available, how itâs packaged, and when updates are released. In this handsâon guide youâll learn exactly how to host your own WinGet repository, add it as a source, publish packages, automate updates, and troubleshoot issues. Youâll get practical examples, readyâtoâuse commands, YAML samples, and scripts you can adapt for your environment.
Overview of the Use Case (en heading H2)
What a private WinGet source does, in plain language
- A private WinGet source is your organizationâs own catalog of packages that users access via the WinGet CLI. It hosts package manifests (YAML) and references installers you control (internal mirrors or vendor URLs).
- Users can search, install, upgrade, and uninstall software from your private catalog using the same familiar WinGet commands they use for the public sourcesâexcept now the catalog is curated by you.
Why this matters
- Security and compliance: Only approved software is available. You can mirror installers internally, hash them, and gate access behind your security perimeter.
- Reliability and performance: Faster installs/updates from your LAN/CDN; no dependency on public service uptime.
- Consistency and automation: Pin versions, enforce silent install flags, and coordinate rollouts via CI/CD, Intune, or device management tools.
Common scenarios where a private WinGet repository shines
- Fresh device provisioning: Use a curated baseline of apps during imaging or autopilot onboarding.
- Bulk updates and maintenance: Run one command to upgrade all apps across hundreds or thousands of devices.
- CI/CD automation: Publish new versions when your product releases; automatically update manifests.
- Lab, VDI, and offline/lowâbandwidth deployments: Mirror installers behind the firewall or on an internal share.
- Regulated environments: Maintain auditable manifests and hashes to meet changeâcontrol requirements.
Quick Reference Table (en heading H2)
| Command | Purpose | Example Output |
|---|---|---|
| winget âinfo | Show WinGet version and system info | Windows Package Manager v1.6.xâŚ; System architecture: x64 |
| winget source list | List configured sources | Name Arg Type; winget https://⌠Microsoft.PreIndexed; msstore https://⌠Microsoft.Store; PrivateRepo https://repo.contoso.local/api Microsoft.Rest |
| winget source add âname PrivateRepo âtype Rest âarg https://repo.contoso.local/api | Add your private REST source | Added source: PrivateRepo |
| winget source update âname PrivateRepo | Refresh catalog metadata | Updating source: PrivateRepo; Done |
| winget source reset âforce | Reset sources to defaults (repair) | Resetting sources⌠Done |
| winget search myapp âsource PrivateRepo | Search for a package in your repo | Name Id Version Source; Contoso MyApp Contoso.MyApp 1.2.3 PrivateRepo |
| winget show Contoso.MyApp âsource PrivateRepo | Show manifest details | Id: Contoso.MyApp; Version: 1.2.3; InstallerType: msi; InstallerUrl: https://⌠|
| winget install âid Contoso.MyApp âsource PrivateRepo âsilent | Install from your repo | Successfully installed |
| winget upgrade âsource PrivateRepo âall âsilent | Upgrade all packages from your repo | No applicable upgrades found OR list of upgraded packages |
| winget validate âmanifest .\manifests\Contoso.MyApp.yaml | Validate YAML manifest | Manifest validation succeeded |
| winget hash .\MyApp-x64.msi | Compute SHA256 for manifest | SHA256: ABCDEFâŚ1234 |
| winget export -o .\baseline.json âinclude-versions | Export installed apps | Wrote export file to .\baseline.json |
| winget import -i .\baseline.json âsource PrivateRepo âaccept-package-agreements âaccept-source-agreements | Reinstall baseline from your repo | Installing packages listed in baseline.json⌠|
Key Concepts and Prerequisites (en header H2)
Key concepts
- Source types: WinGet can use different source types. For private hosting, the recommended model is a REST source (Type: Microsoft.Rest), which supports search, show, install, and upgrade.
- Manifests: YAML files describe packagesâIDs, versions, installer URLs, checksums, silent switches, dependencies, etc.
- Installers: Actual binaries (MSI, EXE, MSIX, ZIP, portable) hosted at internal or vendor URLs. WinGet downloads and verifies them via SHA256.
- Search/upgrade integration: With a REST source, your packages integrate into winget search/upgrade workflows just like public sources.
Prerequisites
- WinGet (Windows Package Manager) installed via App Installer (Microsoft Store) on Windows 10 1809+ or Windows 11. Recommended WinGet CLI v1.4+ (ideally 1.6+).
- PowerShell available (5.1+ or PowerShell 7+).
- Administrative rights for system-wide installs and source configuration on managed devices (recommended).
- HTTPS endpoint for your private REST service (TLS certificate configured).
- Storage for manifests and installers (Git repo + CI/CD + object storage/CDN or web server).
How to check your WinGet version
- Command: winget âinfo
- You should see Windows Package Manager v1.4.x or higher. If not, update the App Installer package from the Microsoft Store or your enterprise channel.
Step-by-Step Guide (en heading H2)
This guide uses the recommended REST source model. Youâll deploy a REST API, create manifests, publish them, and connect clients.
Option A (recommended): Host a REST source
H3: 1) Plan your repository and network architecture
- Choose your host: Windows Server with IIS/Kestrel, Linux with Nginx/Apache, or a managed PaaS (App Service). The REST service is a standard HTTPS API.
- Storage:
- Manifests: Keep them in a Git repository for version control.
- Installers: Prefer internal object storage, NAS, or web server under your control. Mirror vendor binaries if allowed and keep checksums updated.
- Access control:
- Internal only: Restrict via firewall/VPN.
- Authenticated: Reverse proxy with auth (e.g., mTLS, OAuth, headerâbased auth). You can place an API gateway in front.
- DNS and TLS:
- Create a DNS name like repo.contoso.local or packages.contoso.com.
- Install a trusted TLS cert on the endpoint.
H3: 2) Deploy the WinGet REST source
- Use the official reference implementation for the Windows Package Manager REST source (often called âwinget-rest-sourceâ). Itâs a .NET web API that implements the WinGet source contract.
- Deployment outline (generic)
- Prepare a host (Windows or Linux) with .NET 6+ runtime (or container host).
- Publish the REST service:
- If using source code: dotnet publish -c Release, then host behind IIS/Kestrel or systemd.
- If using a container image: run it behind a reverse proxy with TLS.
- Configure environment variables or appsettings for:
- Base URL (e.g., https://repo.contoso.local/api)
- Storage/metadata backend for packages and versions (database or files, depending on implementation)
- Read vs. write permissions (set write to CI/CD only; read for clients)
- Test health: curl https://repo.contoso.local/api/information
Notes:
- The REST schema exposes endpoints for searching packages, retrieving manifests, and version queries. Make sure the app responds with 200 OK on /information and supports the manifest search endpoints.
H3: 3) Create a package manifest (YAML)
You can write manifests manually or use a helper (e.g., the wingetcreate tool) to scaffold them. Below is a full singleton YAML example with inline comments.
Example: .\manifests\Contoso.MyApp.yaml
A simple singleton manifest for WinGet
Save as: Contoso.MyApp.yaml (for demonstration; production repos often use multi-file manifests)
Id: Contoso.MyApp # Unique ID (Publisher.App)
Version: 1.2.3 # Semantic version
Name: Contoso MyApp
Publisher: Contoso Ltd.
Author: Contoso Ltd.
License: Proprietary
LicenseUrl: https://contoso.example.com/myapp/license
Homepage: https://contoso.example.com/myapp
AppMoniker: myapp
Description: âContoso MyApp is a sample enterprise tool.â
Tags:
- contoso
- myapp
- enterprise
ReleaseNotes: âBug fixes and performance improvements.â
ReleaseNotesUrl: https://contoso.example.com/myapp/releases/1.2.3
Define how to install (MSI example)
InstallerType: msi # exe | msi | msix | zip | inno | nullsoft | burn | portable
Scope: machine # machine | user
InstallModes:
- silent
- silentWithProgress
InstallerSwitches: # Silent flags are critical for automation
Silent: /qn
SilentWithProgress: /qb
Custom: TRANSFORMS=MyApp.mst
If MSI, include ProductCode to help WinGet track upgrades
ProductCode: â{12345678-90AB-CDEF-1234-567890ABCDEF}â
UpgradeBehavior: install
Expected return codes (optional but recommended for robust automation)
InstallerSuccessCodes:
- 3010 # MSI: restart required
Define installers for each architecture/locale you support
Installers:
- Architecture: x64
InstallerUrl: https://repo.contoso.local/content/myapp/1.2.3/MyApp-x64.msi
InstallerSha256: ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890
SignatureSha256: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF # optional if you sign
NestedInstallerType: none
AppsAndFeaturesEntries:- DisplayName: Contoso MyApp
Publisher: Contoso Ltd.
ProductCode: â{12345678-90AB-CDEF-1234-567890ABCDEF}â
InstallerType: msi
- DisplayName: Contoso MyApp
Commands:
- myapp
Manifest metadata
ManifestType: singleton
ManifestVersion: 1.6.0
Best practices for authoring manifests
- Always set InstallerSha256 for every installer. Compute it with: winget hash .\MyApp-x64.msi
- Use Scope: machine for enterprise apps needing admin install; pair with âsilent in your scripts.
- Provide ProductCode (MSI) so WinGet can detect installed versions and upgrades.
- Include correct InstallerSwitches for silent/silentWithProgress. For MSI: /qn or /qb; for EXE, consult vendor docs.
H3: 4) Validate your manifest locally
Use WinGetâs validation tools before publishing:
Validate YAML schema and basic rules
winget validate âmanifest .\manifests\Contoso.MyApp.yaml
Compute and verify file hashes
winget hash .\MyApp-x64.msi
Make sure the SHA256 in the manifest matches the installer file you intend to host.
H3: 5) Publish manifests and installers to your repository
- Upload installers to your internal web server or object store (the URL used in InstallerUrl).
- Publish the manifest(s) to the storage backend that your REST service uses, or push them to a Git repo and run a pipeline that synchronizes manifests into the REST sourceâs store.
- Common CI/CD approach:
- When a release is tagged, build artifacts (MSI/EXE).
- Compute SHA256, update YAML manifest automatically.
- Validate manifests.
- Publish installers to https://repo.contoso.local/content/⌠and push manifests to the REST backend.
- Trigger a cache refresh (if your implementation has a reindex step).
H3: 6) Add the private source on clients
On any device that should consume your repo:
Optional: verify WinGet availability
winget âinfo
Add your private REST source (name and URL to your service)
winget source add âname PrivateRepo âtype Rest âarg https://repo.contoso.local/api
Confirm it shows up
winget source list
Update metadata (good practice after adding)
winget source update âname PrivateRepo
H3: 7) Install, search, upgrade from your private source
Try these endâtoâend commands:
Search for a package
winget search myapp âsource PrivateRepo
Show details (verify manifest fields)
winget show Contoso.MyApp âsource PrivateRepo
Install silently (perfect for automation)
winget install âid Contoso.MyApp âsource PrivateRepo âsilent âaccept-package-agreements âaccept-source-agreements
Upgrade from your repo (all apps your source tracks)
winget upgrade âsource PrivateRepo âall âsilent âaccept-package-agreements âaccept-source-agreements
Uninstall (if supported)
winget uninstall âid Contoso.MyApp
Option B: Use local manifests without a source (quick and offline-friendly)
If you donât need search/upgrade integration and just want repeatable installs:
- Place YAML manifests and installers on a file share.
- Install directly from YAML:
winget install -m \fileserver\manifests\Contoso.MyApp.yaml âsilent âaccept-package-agreements
This is handy for offline or adâhoc scenarios, but you wonât get sourceâbacked search/upgrade.
Troubleshooting (en heading H2)
Common errors and how to fix them
H3: Hash mismatch (InstallerSha256 mismatch)
Symptoms: WinGet errors that the installer hash does not match the manifest.
-
Causes: Installer file changed, wrong URL, or incorrect SHA.
-
Fix:
-
Download the exact file referenced by InstallerUrl and compute its hash:
winget hash .\MyApp-x64.msi
-
Update InstallerSha256 in the YAML to the correct value.
-
Reâpublish the manifest and update source metadata:
winget source update âname PrivateRepo
-
H3: Multiple installers found / ambiguous match
Symptoms: Search or install finds multiple packages or architectures.
-
Fix:
-
Specify the Id and âexact if needed:
winget install âid Contoso.MyApp âsource PrivateRepo âexact âsilent
-
Ensure your manifest defines Architecture for each installer and avoid overlapping criteria.
-
Include ProductCode (MSI) and consistent naming to help detection.
-
H3: Source not responding / index errors
Symptoms: winget source update fails; search returns no results.
-
Fix:
-
Verify endpoint health: curl https://repo.contoso.local/api/information
-
Check TLS cert validity and firewall rules.
-
Refresh sources:
winget source update âname PrivateRepo
-
As a last resort, reset sources:
winget source reset âforce
-
Then reâadd your source.
-
H3: 401/403 Unauthorized when accessing a private source
- Fix:
- Confirm the device is on the allowed network or VPN.
- If you protect the endpoint behind an auth proxy, configure client trust (certs, device auth) or allow anonymous GET for readâonly package queries.
- Validate time skew and TLS configuration.
H3: Install fails silently in automation
- Fix:
- Ensure correct InstallerSwitches. For MSI, use /qn for true silent; many EXE installers need vendorâspecific silent flags.
- Add âsilent âaccept-package-agreements âaccept-source-agreements to nonâinteractive scripts.
- Check exit codes. Add InstallerSuccessCodes for nonâzero âsuccessâ codes like 3010 (restart required).
H3: Upgrades not detected
-
Fix:
-
Verify Version increments in manifests.
-
For MSI, ensure ProductCode reflects upgrades (same or changed depending on MSI scheme) and that UpgradeCode/ProductVersion rules are correct.
-
Run:
winget upgrade âsource PrivateRepo
-
Automation Tips (en heading H2)
H3: PowerShell bootstrap for devices
Use a single script to configure the source and install a baseline.
Example: Add the source idempotently and install a baseline list
Add private source if missing
$srcName = âPrivateRepoâ
$srcUrl = âhttps://repo.contoso.local/apiâ
$exists = winget source list | Select-String -SimpleMatch $srcName
if (-not $exists) {
winget source add âname $srcName âtype Rest âarg $srcUrl
} else {
winget source update âname $srcName
}
Optional: install a baseline set (by Id)
$packages = @(
âContoso.MyAppâ,
âContoso.Tools.CLIâ,
âContoso.Viewerâ
)
foreach ($pkg in $packages) {
winget install âid $pkg âsource $srcName âsilent âaccept-package-agreements âaccept-source-agreements
}
H3: Scheduled Task to autoâupgrade nightly
- Save a script (Upgrade-PrivateRepo.ps1):
winget source update âname PrivateRepo
winget upgrade âsource PrivateRepo âall âsilent âaccept-package-agreements âaccept-source-agreements
- Create a scheduled task to run as SYSTEM or with admin rights at 3 AM daily.
H3: Intune device script integration
- Push a PowerShell script that:
- Adds the PrivateRepo source.
- Installs required packages with âsilent.
- Optionally runs a periodic winget upgrade âall from your source.
- Scope devices via dynamic groups to control rollout waves.
H3: CI/CD pipeline to publish packages
- On release:
- Build your MSI/EXE artifacts.
- Compute SHA256: winget hash path\to\installer.ext
- Update manifest YAML (bump Version, URLs, hashes).
- Validate: winget validate âmanifest path\to\yaml
- Publish installers to your internal content store.
- Publish manifest(s) to the REST source storage.
- Trigger your REST source to refresh (if your implementation caches results).
H3: Offline and lowâbandwidth sites
- Mirror installers to a local file server in each site and point InstallerUrl to the local mirror (per site DNS).
- Preâstage downloads overnight using a management script.
- For completely offline segments, use local YAML with winget install -m path\to\yaml.
Best Practices (en heading H2)
H3: Governance and security
- Only host trusted installers and verify their hashes. Always update InstallerSha256 after any rebuild.
- Serve your REST source over HTTPS with a valid certificate.
- Control access using network ACLs, VPN, or an authâenabled reverse proxy.
- Separate read (client) and write (publisher) paths; CI/CD should be the only writer.
H3: Manifest quality and consistency
- Use consistent IDs: Publisher.App (e.g., Contoso.MyApp). Donât rename IDs once in use.
- Keep manifests small and focused. For complex apps, consider multiâfile manifests (installer.yaml, locale.yaml, version.yaml) following WinGet schema guidance.
- Include silent install switches and expected return codes to avoid hung installs in unattended runs.
- Specify Architecture for each installer and provide both x64 and arm64 where applicable.
- Include ProductCode for MSI packages and AppsAndFeaturesEntries to aid detection.
H3: Versioning and pinning
-
Use strict semantic versions and avoid reusing a version number for different binaries.
-
For baselines, export with versions and reâimport to pin:
winget export -o .\baseline.json âinclude-versions
winget import -i .\baseline.json âsource PrivateRepo âaccept-package-agreements âaccept-source-agreements
H3: Repository hygiene
- Remove or archive deprecated versions after a deprecation window.
- Keep release notes and metadata updated; include ReleaseNotes and ReleaseNotesUrl.
- Test installs in a staging environment before promoting manifests to production.
H3: Operational excellence
- Monitor your REST source health (availability, latency).
- Log package installs and upgrades on endpoints for auditability.
- Document appâspecific switches and postâinstall tasks (e.g., licensing) in team runbooks.
Conclusion (en heading H2)
Hosting a private WinGet source gives you reliable, secure, and automated software deployment across Windows fleets. You learned how to:
- Deploy a REST source and secure it behind HTTPS.
- Author highâquality YAML manifests with correct hashes and silent flags.
- Publish packages and add your source to clients.
- Automate installs and upgrades via PowerShell, Task Scheduler, Intune, or CI/CD.
- Diagnose and fix common issues fast.
Try the commands in this guide on a test machine, starting with winget source add and winget search. With careful manifests and a solid publishing pipeline, WinGet becomes a safe and powerful foundation for managing Windows software at scale.
FAQ Section (en heading H2)
H4: Can I host installers on an internal server and still use WinGet?
Yes. Set InstallerUrl in your manifest to an internal HTTPS endpoint (e.g., https://repo.contoso.local/content/âŚ). Ensure the endpoint is reachable from clients and that InstallerSha256 matches the hosted file. This is a common pattern for bandwidth control and security.
H4: Do I have to use a REST source, or can I install directly from YAML?
You can install directly from local or network YAML using winget install -m path\to\manifest.yaml. However, without a source you wonât get integrated search/upgrade. For a full catalog experience, use a REST source.
H4: How do I handle packages that use custom EXE installers?
Declare InstallerType: exe and provide the correct silent switches under InstallerSwitches. Common examples include /S, /silent, /verysilent, or vendorâspecific flags. Always test unattended installs, and add nonâzero success codes if needed.
H4: How can I pin versions or prevent automatic upgrades?
Export a baseline with versions and reâimport it for consistent deployments:
- winget export -o .\baseline.json âinclude-versions
- winget import -i .\baseline.json âsource PrivateRepo
For strict pinning, avoid running blanket winget upgrade âall on those devices, or curate your repo so only approved versions are present.
H4: What about portable apps and ZIP installers?
WinGet supports portable and zip types. For ZIP, provide extraction behavior using manifest keys appropriate for your schema version. For portable apps, specify Installers with InstallerType: portable, and define the executable and path actions as required by the schema. Always include a valid InstallerSha256 and test silent behavior if applicable.
Appendix: Additional readyâtoâuse snippets (en heading H2)
H3: Verify and reâpublish a new version endâtoâend
1) Build artifacts and place MyApp-x64.msi at .\dist\MyApp-x64.msi
2) Compute hash
$hash = (winget hash .\dist\MyApp-x64.msi | Select-String âSHA256:â ).ToString().Split()[1]
3) Update manifest (simple example; in CI, edit YAML via a script)
(Get-Content .\manifests\Contoso.MyApp.yaml) -replace âVersion: .â,âVersion: 1.2.4â `
-replace âInstallerSha256: .â,âInstallerSha256: $hashâ | Set-Content .\manifests\Contoso.MyApp.yaml
4) Validate
winget validate âmanifest .\manifests\Contoso.MyApp.yaml
5) Publish installer to your content store and manifest to the REST backend (implementation-specific)
6) Refresh clientsâ view
winget source update âname PrivateRepo
H3: Baseline deployment on a new device
Ensure source is present
winget source add âname PrivateRepo âtype Rest âarg https://repo.contoso.local/api
Install baseline using a JSON export created earlier
winget import -i \share\baselines\standard.json âsource PrivateRepo âaccept-package-agreements âaccept-source-agreements
H3: Silent install and logging
MSI example with logging
winget install âid Contoso.MyApp âsource PrivateRepo âsilent âoverride â/qn /L*v C:\Temp\MyAppInstall.logâ âaccept-package-agreements
Tip: For MSI packages, you can pass vendor flags via âoverride. For EXE installers, ensure the switches are correct; combine with âsilent for nonâinteractive runs.
You now have everything you need to design, deploy, and operate a private WinGet sourceâfrom manifests and hosting to automation and troubleshooting. With a bit of upfront setup and good manifest hygiene, WinGet becomes a robust, enterpriseâgrade delivery mechanism for your Windows applications.
