Deploying a Winget Private Repository

Just a note before kicking off: If you are comfortable with VSCode ,Github, installation of PS modules and connecting to Azure via PowerShell I would advise skimming the Getting Started section, cloning the working source code from here, and picking up from section 4. If you are not that confident it is worth grabbing a coffee and working through each section in sequence. Its a long one but I hope as a reader you get some value out of the detail.

  1. Introduction
  2. Getting Started
    1. What are we Installing?
    2. What are we trying to achieve?
  3. Prepare your Environment
    1. The Basics
    2. Install the winget-rest-source PS module
  4. Creating a Private Winget Respoitory
    1. Sanity Checking the installation
  5. Conclusion

Introduction

Over the last couple of months I have been getting to grips with Windows Package Manager (aka Winget).

It faces a far more challenging application landscape than its Linux based counterparts, and while it is still a little immature as a technology, it has a lot of potential. I believe it is the future of application deployment and management on Windows and I hope that it gets the attention and adoption that it deserves.

If you have no idea what Winget is I would recommend having a read of two earlier articles I have covered on the topic as this one will be a little more technical.

  1. An Introduction to Windows Package Manager (aka Winget)
  2. An Introduction to Winget Private Repositories

As I mentioned in a previous post if you are considering introducing Winget to your environment you may face governance issues (control over the software distribution process), or technical limitation (compatibility problems with specific enterprise software or systems) In these scenarios you may want to consider hosting a private Winget repository to address those challenges.

The good news is that there is a project that provides a reference implementation for creating a REST based private package source for the Winget client. Details can be found here.

The bad news is that it can be a bit of a challenge to get everything set up without a bit of troubleshooting. For those interested in the nuts and bolts: the issue log provided by a helpful, since deleted Gihub account covers the highlights with the summary below:

  • Errors are widely suppressed making it non-obvious why things might not be working
  • Errors that are not suppressed have little context into what’s failing and why
  • Template files are missing from the expected default path, and the build process does not copy them to the expected path
  • Azure Functions .zip file is not in the expected default path, and the build process does not create it
  • Parameter generation is missing expected values for the Azure Function template
  • ASP template is missing entirely which blocks the script from completing successfully
  • KeyVault creation keys only off the -Name parameter value which may conflict globally

Note: The Functions .zip file issue caught me out when completing this write up, I have left the troubleshooting steps in rather than fixing in place as I felt it would be useful to assisit in understanding how the deployment works

I like to think I am a reasonably competent but this particular challenge found those skills wanting. Luckily I was able to find some backup!

Every story needs a hero this role was filled by Gunnar Óttarsson founder and CTO of Well Advised, Gunnar and his team know Azure inside out, I learned so much working with him and if you need an Azure Infrastructure and Dev-Ops experts I could not recommend them enough.

It is Gunnar’s fork of the project that addressed the most of the previously listed challenges that I am using for this walk through and all credit goes to him for helping me to get up and running.

I would also highly recommend having a read of Léon Bouquiet’s blog on the same subject, this was the best write up I have found outside of the project’s Github notes and really helped my understanding of how it all hangs together.

Getting Started

What are we Installing?

A Winget Private Repository consists of a number of Azure hosted components and the (optional) vendor source download location.

App Service PlanA hosting plan that defines a set of resources available for web apps, APIs, and background jobs
Application InsightsCollects various telemetry data from the app, such as request rates, response times, failure rates, dependencies (like databases and external services your app relies on), this will give you “insight” into issues with your Winget Repository 
Azure FunctionsA serverless computing service that allows us to execute small bits of code, or “functions,” in response to various types of events such including HTTP requests to make REST API calls to read, update, create and delete entries on your Winget Repository 
Azure Cosmos DBA fully managed NoSQL database service used to host your private Winget Repository application manifest data
Key VaultCentralizes the storage of application secrets, allowing you to control their distribution. Used in this instance
Storage AccountContains all storage data objects: blobs, files, queues, tables, and disks necessary for the operation of your Winget Repository
Winget Private Repository Objects

There are two additional components to be aware of that are not part of the actual deployment of which you are likely to use when levering Winget to install from a Private Repository.

Storage AccountA separate storage account that Contains the storage data object(s): blobs or files that you may use to host application sources internally that your Winget Repository can reference for download
Vendor Hosted SourceExternal Download Location that a 3rd party vendor may use to host application sources your Winget Repository can reference for download
Ancillary objects required for a Winget Private Repository

Continue reading

An Introduction to Winget Private Repositories

As per my previous Winget article, the out of the box Public implementation of Winget consists of the following components.

  1. The client-side command-line utility
  2. The Gitub hosted Windows Package Manager Community Repository of Package Manifests
  3. The Download Source Location for the Package Payload
  4. The Microsoft Hosted Winget Content Delivery Network (CDN)
  5. The public Microsoft Store

As we can see a Private Implementation of Winget is a little more involved but does offer more flexibility which I cover in greater detail below

  1. Create a package manifest using Windows Package Manager Manifest Creator or YamlCreate.ps1 OR download the existing YAML files for your chosen application from the Community Repository
  2. Leverage Gunnar’s collection of commands here to convert the YAML manifests to JSON
  3. At this point you can make the changes to the manifest such as changing the download location to an internal/private source OR modifying the metadata for internal consistency with a CMDB
  4. Invoke the REST “POST” method to upload the JSON files to your Private Repository
  5. Run the Source Add command on your windows client to add a REST source for the Winget Package Manager. (I have provided a Winget client install script that can complete this step when the appropriate switches are passed to it, read description of script for more detail)
  6. A user or an administrator can now interact with the Private Repository via client commands to programmatically “discover, install, upgrade, remove and configure applications” that are hosted there in the same way as they can with the CDN or the Microsoft Store with the Public implementation of Winget

Continue reading

Running Windows Package Manager (Winget) in the SYSTEM context

I have recently been working on Dev Ops Style image deployments for Azure Virtual Desktop. With AVD or any DaaS product image deployment is unfortunately only half the battle. You have to consider how you will get your applications on there.

While working toward an automation centric AVD design with a little less image management I have been playing around with Winget.

The Background

Winget has tons of potential and I hope that Microsoft give it the love it needs to survive and thrive it has an active Github and is worth checking out the discussions on there if you are interested.

For my use case of deploying applications to AVD Session Hosts at build time my first snag was the inability to run Winget in the SYSTEM context. In a Multi-Session DaaS context this is a hard requirement if Winget is going to become a main stream part of the AVD administrator tool kit. For now, we need a workaround.

Note: Health Warning – Winget does not support running in the SYSTEM context for lots of good reasons, a lot of the applications in the Public Repository are probably not going to install/uninstall gracefully or with the behaviour you expect in the SYSTEM context, use this work around with care and attention and test the applications you plan on deploying in this manner thoroughly before using in a Production context.

Continue reading